Favivon - Correção

This commit is contained in:
2026-05-30 19:59:39 -03:00
parent 76ddaa815d
commit d7dfd221f0
32859 changed files with 5459654 additions and 404 deletions
+46
View File
@@ -0,0 +1,46 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
class BoxLineGeometry extends THREE.BufferGeometry {
constructor(width, height, depth, widthSegments, heightSegments, depthSegments) {
super();
width = width || 1;
height = height || 1;
depth = depth || 1;
widthSegments = Math.floor(widthSegments) || 1;
heightSegments = Math.floor(heightSegments) || 1;
depthSegments = Math.floor(depthSegments) || 1;
const widthHalf = width / 2;
const heightHalf = height / 2;
const depthHalf = depth / 2;
const segmentWidth = width / widthSegments;
const segmentHeight = height / heightSegments;
const segmentDepth = depth / depthSegments;
const vertices = [];
let x = -widthHalf, y = -heightHalf, z = -depthHalf;
for (let i = 0; i <= widthSegments; i++) {
vertices.push(x, -heightHalf, -depthHalf, x, heightHalf, -depthHalf);
vertices.push(x, heightHalf, -depthHalf, x, heightHalf, depthHalf);
vertices.push(x, heightHalf, depthHalf, x, -heightHalf, depthHalf);
vertices.push(x, -heightHalf, depthHalf, x, -heightHalf, -depthHalf);
x += segmentWidth;
}
for (let i = 0; i <= heightSegments; i++) {
vertices.push(-widthHalf, y, -depthHalf, widthHalf, y, -depthHalf);
vertices.push(widthHalf, y, -depthHalf, widthHalf, y, depthHalf);
vertices.push(widthHalf, y, depthHalf, -widthHalf, y, depthHalf);
vertices.push(-widthHalf, y, depthHalf, -widthHalf, y, -depthHalf);
y += segmentHeight;
}
for (let i = 0; i <= depthSegments; i++) {
vertices.push(-widthHalf, -heightHalf, z, -widthHalf, heightHalf, z);
vertices.push(-widthHalf, heightHalf, z, widthHalf, heightHalf, z);
vertices.push(widthHalf, heightHalf, z, widthHalf, -heightHalf, z);
vertices.push(widthHalf, -heightHalf, z, -widthHalf, -heightHalf, z);
z += segmentDepth;
}
this.setAttribute("position", new THREE.Float32BufferAttribute(vertices, 3));
}
}
exports.BoxLineGeometry = BoxLineGeometry;
//# sourceMappingURL=BoxLineGeometry.cjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"BoxLineGeometry.cjs","sources":["../../src/geometries/BoxLineGeometry.js"],"sourcesContent":["import { BufferGeometry, Float32BufferAttribute } from 'three'\n\nclass BoxLineGeometry extends BufferGeometry {\n constructor(width, height, depth, widthSegments, heightSegments, depthSegments) {\n super()\n\n width = width || 1\n height = height || 1\n depth = depth || 1\n\n widthSegments = Math.floor(widthSegments) || 1\n heightSegments = Math.floor(heightSegments) || 1\n depthSegments = Math.floor(depthSegments) || 1\n\n const widthHalf = width / 2\n const heightHalf = height / 2\n const depthHalf = depth / 2\n\n const segmentWidth = width / widthSegments\n const segmentHeight = height / heightSegments\n const segmentDepth = depth / depthSegments\n\n const vertices = []\n\n let x = -widthHalf,\n y = -heightHalf,\n z = -depthHalf\n\n for (let i = 0; i <= widthSegments; i++) {\n vertices.push(x, -heightHalf, -depthHalf, x, heightHalf, -depthHalf)\n vertices.push(x, heightHalf, -depthHalf, x, heightHalf, depthHalf)\n vertices.push(x, heightHalf, depthHalf, x, -heightHalf, depthHalf)\n vertices.push(x, -heightHalf, depthHalf, x, -heightHalf, -depthHalf)\n\n x += segmentWidth\n }\n\n for (let i = 0; i <= heightSegments; i++) {\n vertices.push(-widthHalf, y, -depthHalf, widthHalf, y, -depthHalf)\n vertices.push(widthHalf, y, -depthHalf, widthHalf, y, depthHalf)\n vertices.push(widthHalf, y, depthHalf, -widthHalf, y, depthHalf)\n vertices.push(-widthHalf, y, depthHalf, -widthHalf, y, -depthHalf)\n\n y += segmentHeight\n }\n\n for (let i = 0; i <= depthSegments; i++) {\n vertices.push(-widthHalf, -heightHalf, z, -widthHalf, heightHalf, z)\n vertices.push(-widthHalf, heightHalf, z, widthHalf, heightHalf, z)\n vertices.push(widthHalf, heightHalf, z, widthHalf, -heightHalf, z)\n vertices.push(widthHalf, -heightHalf, z, -widthHalf, -heightHalf, z)\n\n z += segmentDepth\n }\n\n this.setAttribute('position', new Float32BufferAttribute(vertices, 3))\n }\n}\n\nexport { BoxLineGeometry }\n"],"names":["BufferGeometry","Float32BufferAttribute"],"mappings":";;;AAEA,MAAM,wBAAwBA,MAAAA,eAAe;AAAA,EAC3C,YAAY,OAAO,QAAQ,OAAO,eAAe,gBAAgB,eAAe;AAC9E,UAAO;AAEP,YAAQ,SAAS;AACjB,aAAS,UAAU;AACnB,YAAQ,SAAS;AAEjB,oBAAgB,KAAK,MAAM,aAAa,KAAK;AAC7C,qBAAiB,KAAK,MAAM,cAAc,KAAK;AAC/C,oBAAgB,KAAK,MAAM,aAAa,KAAK;AAE7C,UAAM,YAAY,QAAQ;AAC1B,UAAM,aAAa,SAAS;AAC5B,UAAM,YAAY,QAAQ;AAE1B,UAAM,eAAe,QAAQ;AAC7B,UAAM,gBAAgB,SAAS;AAC/B,UAAM,eAAe,QAAQ;AAE7B,UAAM,WAAW,CAAE;AAEnB,QAAI,IAAI,CAAC,WACP,IAAI,CAAC,YACL,IAAI,CAAC;AAEP,aAAS,IAAI,GAAG,KAAK,eAAe,KAAK;AACvC,eAAS,KAAK,GAAG,CAAC,YAAY,CAAC,WAAW,GAAG,YAAY,CAAC,SAAS;AACnE,eAAS,KAAK,GAAG,YAAY,CAAC,WAAW,GAAG,YAAY,SAAS;AACjE,eAAS,KAAK,GAAG,YAAY,WAAW,GAAG,CAAC,YAAY,SAAS;AACjE,eAAS,KAAK,GAAG,CAAC,YAAY,WAAW,GAAG,CAAC,YAAY,CAAC,SAAS;AAEnE,WAAK;AAAA,IACN;AAED,aAAS,IAAI,GAAG,KAAK,gBAAgB,KAAK;AACxC,eAAS,KAAK,CAAC,WAAW,GAAG,CAAC,WAAW,WAAW,GAAG,CAAC,SAAS;AACjE,eAAS,KAAK,WAAW,GAAG,CAAC,WAAW,WAAW,GAAG,SAAS;AAC/D,eAAS,KAAK,WAAW,GAAG,WAAW,CAAC,WAAW,GAAG,SAAS;AAC/D,eAAS,KAAK,CAAC,WAAW,GAAG,WAAW,CAAC,WAAW,GAAG,CAAC,SAAS;AAEjE,WAAK;AAAA,IACN;AAED,aAAS,IAAI,GAAG,KAAK,eAAe,KAAK;AACvC,eAAS,KAAK,CAAC,WAAW,CAAC,YAAY,GAAG,CAAC,WAAW,YAAY,CAAC;AACnE,eAAS,KAAK,CAAC,WAAW,YAAY,GAAG,WAAW,YAAY,CAAC;AACjE,eAAS,KAAK,WAAW,YAAY,GAAG,WAAW,CAAC,YAAY,CAAC;AACjE,eAAS,KAAK,WAAW,CAAC,YAAY,GAAG,CAAC,WAAW,CAAC,YAAY,CAAC;AAEnE,WAAK;AAAA,IACN;AAED,SAAK,aAAa,YAAY,IAAIC,MAAAA,uBAAuB,UAAU,CAAC,CAAC;AAAA,EACtE;AACH;;"}
+12
View File
@@ -0,0 +1,12 @@
import { BufferGeometry } from 'three'
export class BoxLineGeometry extends BufferGeometry {
constructor(
width?: number,
height?: number,
depth?: number,
widthSegments?: number,
heightSegments?: number,
depthSegments?: number,
)
}
+46
View File
@@ -0,0 +1,46 @@
import { BufferGeometry, Float32BufferAttribute } from "three";
class BoxLineGeometry extends BufferGeometry {
constructor(width, height, depth, widthSegments, heightSegments, depthSegments) {
super();
width = width || 1;
height = height || 1;
depth = depth || 1;
widthSegments = Math.floor(widthSegments) || 1;
heightSegments = Math.floor(heightSegments) || 1;
depthSegments = Math.floor(depthSegments) || 1;
const widthHalf = width / 2;
const heightHalf = height / 2;
const depthHalf = depth / 2;
const segmentWidth = width / widthSegments;
const segmentHeight = height / heightSegments;
const segmentDepth = depth / depthSegments;
const vertices = [];
let x = -widthHalf, y = -heightHalf, z = -depthHalf;
for (let i = 0; i <= widthSegments; i++) {
vertices.push(x, -heightHalf, -depthHalf, x, heightHalf, -depthHalf);
vertices.push(x, heightHalf, -depthHalf, x, heightHalf, depthHalf);
vertices.push(x, heightHalf, depthHalf, x, -heightHalf, depthHalf);
vertices.push(x, -heightHalf, depthHalf, x, -heightHalf, -depthHalf);
x += segmentWidth;
}
for (let i = 0; i <= heightSegments; i++) {
vertices.push(-widthHalf, y, -depthHalf, widthHalf, y, -depthHalf);
vertices.push(widthHalf, y, -depthHalf, widthHalf, y, depthHalf);
vertices.push(widthHalf, y, depthHalf, -widthHalf, y, depthHalf);
vertices.push(-widthHalf, y, depthHalf, -widthHalf, y, -depthHalf);
y += segmentHeight;
}
for (let i = 0; i <= depthSegments; i++) {
vertices.push(-widthHalf, -heightHalf, z, -widthHalf, heightHalf, z);
vertices.push(-widthHalf, heightHalf, z, widthHalf, heightHalf, z);
vertices.push(widthHalf, heightHalf, z, widthHalf, -heightHalf, z);
vertices.push(widthHalf, -heightHalf, z, -widthHalf, -heightHalf, z);
z += segmentDepth;
}
this.setAttribute("position", new Float32BufferAttribute(vertices, 3));
}
}
export {
BoxLineGeometry
};
//# sourceMappingURL=BoxLineGeometry.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"BoxLineGeometry.js","sources":["../../src/geometries/BoxLineGeometry.js"],"sourcesContent":["import { BufferGeometry, Float32BufferAttribute } from 'three'\n\nclass BoxLineGeometry extends BufferGeometry {\n constructor(width, height, depth, widthSegments, heightSegments, depthSegments) {\n super()\n\n width = width || 1\n height = height || 1\n depth = depth || 1\n\n widthSegments = Math.floor(widthSegments) || 1\n heightSegments = Math.floor(heightSegments) || 1\n depthSegments = Math.floor(depthSegments) || 1\n\n const widthHalf = width / 2\n const heightHalf = height / 2\n const depthHalf = depth / 2\n\n const segmentWidth = width / widthSegments\n const segmentHeight = height / heightSegments\n const segmentDepth = depth / depthSegments\n\n const vertices = []\n\n let x = -widthHalf,\n y = -heightHalf,\n z = -depthHalf\n\n for (let i = 0; i <= widthSegments; i++) {\n vertices.push(x, -heightHalf, -depthHalf, x, heightHalf, -depthHalf)\n vertices.push(x, heightHalf, -depthHalf, x, heightHalf, depthHalf)\n vertices.push(x, heightHalf, depthHalf, x, -heightHalf, depthHalf)\n vertices.push(x, -heightHalf, depthHalf, x, -heightHalf, -depthHalf)\n\n x += segmentWidth\n }\n\n for (let i = 0; i <= heightSegments; i++) {\n vertices.push(-widthHalf, y, -depthHalf, widthHalf, y, -depthHalf)\n vertices.push(widthHalf, y, -depthHalf, widthHalf, y, depthHalf)\n vertices.push(widthHalf, y, depthHalf, -widthHalf, y, depthHalf)\n vertices.push(-widthHalf, y, depthHalf, -widthHalf, y, -depthHalf)\n\n y += segmentHeight\n }\n\n for (let i = 0; i <= depthSegments; i++) {\n vertices.push(-widthHalf, -heightHalf, z, -widthHalf, heightHalf, z)\n vertices.push(-widthHalf, heightHalf, z, widthHalf, heightHalf, z)\n vertices.push(widthHalf, heightHalf, z, widthHalf, -heightHalf, z)\n vertices.push(widthHalf, -heightHalf, z, -widthHalf, -heightHalf, z)\n\n z += segmentDepth\n }\n\n this.setAttribute('position', new Float32BufferAttribute(vertices, 3))\n }\n}\n\nexport { BoxLineGeometry }\n"],"names":[],"mappings":";AAEA,MAAM,wBAAwB,eAAe;AAAA,EAC3C,YAAY,OAAO,QAAQ,OAAO,eAAe,gBAAgB,eAAe;AAC9E,UAAO;AAEP,YAAQ,SAAS;AACjB,aAAS,UAAU;AACnB,YAAQ,SAAS;AAEjB,oBAAgB,KAAK,MAAM,aAAa,KAAK;AAC7C,qBAAiB,KAAK,MAAM,cAAc,KAAK;AAC/C,oBAAgB,KAAK,MAAM,aAAa,KAAK;AAE7C,UAAM,YAAY,QAAQ;AAC1B,UAAM,aAAa,SAAS;AAC5B,UAAM,YAAY,QAAQ;AAE1B,UAAM,eAAe,QAAQ;AAC7B,UAAM,gBAAgB,SAAS;AAC/B,UAAM,eAAe,QAAQ;AAE7B,UAAM,WAAW,CAAE;AAEnB,QAAI,IAAI,CAAC,WACP,IAAI,CAAC,YACL,IAAI,CAAC;AAEP,aAAS,IAAI,GAAG,KAAK,eAAe,KAAK;AACvC,eAAS,KAAK,GAAG,CAAC,YAAY,CAAC,WAAW,GAAG,YAAY,CAAC,SAAS;AACnE,eAAS,KAAK,GAAG,YAAY,CAAC,WAAW,GAAG,YAAY,SAAS;AACjE,eAAS,KAAK,GAAG,YAAY,WAAW,GAAG,CAAC,YAAY,SAAS;AACjE,eAAS,KAAK,GAAG,CAAC,YAAY,WAAW,GAAG,CAAC,YAAY,CAAC,SAAS;AAEnE,WAAK;AAAA,IACN;AAED,aAAS,IAAI,GAAG,KAAK,gBAAgB,KAAK;AACxC,eAAS,KAAK,CAAC,WAAW,GAAG,CAAC,WAAW,WAAW,GAAG,CAAC,SAAS;AACjE,eAAS,KAAK,WAAW,GAAG,CAAC,WAAW,WAAW,GAAG,SAAS;AAC/D,eAAS,KAAK,WAAW,GAAG,WAAW,CAAC,WAAW,GAAG,SAAS;AAC/D,eAAS,KAAK,CAAC,WAAW,GAAG,WAAW,CAAC,WAAW,GAAG,CAAC,SAAS;AAEjE,WAAK;AAAA,IACN;AAED,aAAS,IAAI,GAAG,KAAK,eAAe,KAAK;AACvC,eAAS,KAAK,CAAC,WAAW,CAAC,YAAY,GAAG,CAAC,WAAW,YAAY,CAAC;AACnE,eAAS,KAAK,CAAC,WAAW,YAAY,GAAG,WAAW,YAAY,CAAC;AACjE,eAAS,KAAK,WAAW,YAAY,GAAG,WAAW,CAAC,YAAY,CAAC;AACjE,eAAS,KAAK,WAAW,CAAC,YAAY,GAAG,CAAC,WAAW,CAAC,YAAY,CAAC;AAEnE,WAAK;AAAA,IACN;AAED,SAAK,aAAa,YAAY,IAAI,uBAAuB,UAAU,CAAC,CAAC;AAAA,EACtE;AACH;"}
+27
View File
@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const ConvexHull = require("../math/ConvexHull.cjs");
class ConvexGeometry extends THREE.BufferGeometry {
constructor(points = []) {
super();
const vertices = [];
const normals = [];
const convexHull = new ConvexHull.ConvexHull().setFromPoints(points);
const faces = convexHull.faces;
for (let i = 0; i < faces.length; i++) {
const face = faces[i];
let edge = face.edge;
do {
const point = edge.head().point;
vertices.push(point.x, point.y, point.z);
normals.push(face.normal.x, face.normal.y, face.normal.z);
edge = edge.next;
} while (edge !== face.edge);
}
this.setAttribute("position", new THREE.Float32BufferAttribute(vertices, 3));
this.setAttribute("normal", new THREE.Float32BufferAttribute(normals, 3));
}
}
exports.ConvexGeometry = ConvexGeometry;
//# sourceMappingURL=ConvexGeometry.cjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"ConvexGeometry.cjs","sources":["../../src/geometries/ConvexGeometry.js"],"sourcesContent":["import { BufferGeometry, Float32BufferAttribute } from 'three'\nimport { ConvexHull } from '../math/ConvexHull'\n\nclass ConvexGeometry extends BufferGeometry {\n constructor(points = []) {\n super()\n\n // buffers\n\n const vertices = []\n const normals = []\n\n const convexHull = new ConvexHull().setFromPoints(points)\n\n // generate vertices and normals\n\n const faces = convexHull.faces\n\n for (let i = 0; i < faces.length; i++) {\n const face = faces[i]\n let edge = face.edge\n\n // we move along a doubly-connected edge list to access all face points (see HalfEdge docs)\n\n do {\n const point = edge.head().point\n\n vertices.push(point.x, point.y, point.z)\n normals.push(face.normal.x, face.normal.y, face.normal.z)\n\n edge = edge.next\n } while (edge !== face.edge)\n }\n\n // build geometry\n\n this.setAttribute('position', new Float32BufferAttribute(vertices, 3))\n this.setAttribute('normal', new Float32BufferAttribute(normals, 3))\n }\n}\n\nexport { ConvexGeometry }\n"],"names":["BufferGeometry","ConvexHull","Float32BufferAttribute"],"mappings":";;;;AAGA,MAAM,uBAAuBA,MAAAA,eAAe;AAAA,EAC1C,YAAY,SAAS,IAAI;AACvB,UAAO;AAIP,UAAM,WAAW,CAAE;AACnB,UAAM,UAAU,CAAE;AAElB,UAAM,aAAa,IAAIC,WAAAA,aAAa,cAAc,MAAM;AAIxD,UAAM,QAAQ,WAAW;AAEzB,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,OAAO,MAAM,CAAC;AACpB,UAAI,OAAO,KAAK;AAIhB,SAAG;AACD,cAAM,QAAQ,KAAK,KAAI,EAAG;AAE1B,iBAAS,KAAK,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AACvC,gBAAQ,KAAK,KAAK,OAAO,GAAG,KAAK,OAAO,GAAG,KAAK,OAAO,CAAC;AAExD,eAAO,KAAK;AAAA,MACpB,SAAe,SAAS,KAAK;AAAA,IACxB;AAID,SAAK,aAAa,YAAY,IAAIC,MAAAA,uBAAuB,UAAU,CAAC,CAAC;AACrE,SAAK,aAAa,UAAU,IAAIA,MAAAA,uBAAuB,SAAS,CAAC,CAAC;AAAA,EACnE;AACH;;"}
+5
View File
@@ -0,0 +1,5 @@
import { BufferGeometry, Vector3 } from 'three'
export class ConvexGeometry extends BufferGeometry {
constructor(points?: Vector3[])
}
+27
View File
@@ -0,0 +1,27 @@
import { BufferGeometry, Float32BufferAttribute } from "three";
import { ConvexHull } from "../math/ConvexHull.js";
class ConvexGeometry extends BufferGeometry {
constructor(points = []) {
super();
const vertices = [];
const normals = [];
const convexHull = new ConvexHull().setFromPoints(points);
const faces = convexHull.faces;
for (let i = 0; i < faces.length; i++) {
const face = faces[i];
let edge = face.edge;
do {
const point = edge.head().point;
vertices.push(point.x, point.y, point.z);
normals.push(face.normal.x, face.normal.y, face.normal.z);
edge = edge.next;
} while (edge !== face.edge);
}
this.setAttribute("position", new Float32BufferAttribute(vertices, 3));
this.setAttribute("normal", new Float32BufferAttribute(normals, 3));
}
}
export {
ConvexGeometry
};
//# sourceMappingURL=ConvexGeometry.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"ConvexGeometry.js","sources":["../../src/geometries/ConvexGeometry.js"],"sourcesContent":["import { BufferGeometry, Float32BufferAttribute } from 'three'\nimport { ConvexHull } from '../math/ConvexHull'\n\nclass ConvexGeometry extends BufferGeometry {\n constructor(points = []) {\n super()\n\n // buffers\n\n const vertices = []\n const normals = []\n\n const convexHull = new ConvexHull().setFromPoints(points)\n\n // generate vertices and normals\n\n const faces = convexHull.faces\n\n for (let i = 0; i < faces.length; i++) {\n const face = faces[i]\n let edge = face.edge\n\n // we move along a doubly-connected edge list to access all face points (see HalfEdge docs)\n\n do {\n const point = edge.head().point\n\n vertices.push(point.x, point.y, point.z)\n normals.push(face.normal.x, face.normal.y, face.normal.z)\n\n edge = edge.next\n } while (edge !== face.edge)\n }\n\n // build geometry\n\n this.setAttribute('position', new Float32BufferAttribute(vertices, 3))\n this.setAttribute('normal', new Float32BufferAttribute(normals, 3))\n }\n}\n\nexport { ConvexGeometry }\n"],"names":[],"mappings":";;AAGA,MAAM,uBAAuB,eAAe;AAAA,EAC1C,YAAY,SAAS,IAAI;AACvB,UAAO;AAIP,UAAM,WAAW,CAAE;AACnB,UAAM,UAAU,CAAE;AAElB,UAAM,aAAa,IAAI,aAAa,cAAc,MAAM;AAIxD,UAAM,QAAQ,WAAW;AAEzB,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,OAAO,MAAM,CAAC;AACpB,UAAI,OAAO,KAAK;AAIhB,SAAG;AACD,cAAM,QAAQ,KAAK,KAAI,EAAG;AAE1B,iBAAS,KAAK,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AACvC,gBAAQ,KAAK,KAAK,OAAO,GAAG,KAAK,OAAO,GAAG,KAAK,OAAO,CAAC;AAExD,eAAO,KAAK;AAAA,MACpB,SAAe,SAAS,KAAK;AAAA,IACxB;AAID,SAAK,aAAa,YAAY,IAAI,uBAAuB,UAAU,CAAC,CAAC;AACrE,SAAK,aAAa,UAAU,IAAI,uBAAuB,SAAS,CAAC,CAAC;AAAA,EACnE;AACH;"}
+182
View File
@@ -0,0 +1,182 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
class DecalGeometry extends THREE.BufferGeometry {
constructor(mesh, position, orientation, size) {
super();
const vertices = [];
const normals = [];
const uvs = [];
const plane = new THREE.Vector3();
const projectorMatrix = new THREE.Matrix4();
projectorMatrix.makeRotationFromEuler(orientation);
projectorMatrix.setPosition(position);
const projectorMatrixInverse = new THREE.Matrix4();
projectorMatrixInverse.copy(projectorMatrix).invert();
generate();
this.setAttribute("position", new THREE.Float32BufferAttribute(vertices, 3));
this.setAttribute("normal", new THREE.Float32BufferAttribute(normals, 3));
this.setAttribute("uv", new THREE.Float32BufferAttribute(uvs, 2));
function generate() {
let i;
let decalVertices = [];
const vertex = new THREE.Vector3();
const normal = new THREE.Vector3();
if (mesh.geometry.isGeometry === true) {
console.error("THREE.DecalGeometry no longer supports THREE.Geometry. Use BufferGeometry instead.");
return;
}
const geometry = mesh.geometry;
const positionAttribute = geometry.attributes.position;
const normalAttribute = geometry.attributes.normal;
if (geometry.index !== null) {
const index = geometry.index;
for (i = 0; i < index.count; i++) {
vertex.fromBufferAttribute(positionAttribute, index.getX(i));
normal.fromBufferAttribute(normalAttribute, index.getX(i));
pushDecalVertex(decalVertices, vertex, normal);
}
} else {
for (i = 0; i < positionAttribute.count; i++) {
vertex.fromBufferAttribute(positionAttribute, i);
normal.fromBufferAttribute(normalAttribute, i);
pushDecalVertex(decalVertices, vertex, normal);
}
}
decalVertices = clipGeometry(decalVertices, plane.set(1, 0, 0));
decalVertices = clipGeometry(decalVertices, plane.set(-1, 0, 0));
decalVertices = clipGeometry(decalVertices, plane.set(0, 1, 0));
decalVertices = clipGeometry(decalVertices, plane.set(0, -1, 0));
decalVertices = clipGeometry(decalVertices, plane.set(0, 0, 1));
decalVertices = clipGeometry(decalVertices, plane.set(0, 0, -1));
for (i = 0; i < decalVertices.length; i++) {
const decalVertex = decalVertices[i];
uvs.push(0.5 + decalVertex.position.x / size.x, 0.5 + decalVertex.position.y / size.y);
decalVertex.position.applyMatrix4(projectorMatrix);
vertices.push(decalVertex.position.x, decalVertex.position.y, decalVertex.position.z);
normals.push(decalVertex.normal.x, decalVertex.normal.y, decalVertex.normal.z);
}
}
function pushDecalVertex(decalVertices, vertex, normal) {
vertex.applyMatrix4(mesh.matrixWorld);
vertex.applyMatrix4(projectorMatrixInverse);
normal.transformDirection(mesh.matrixWorld);
decalVertices.push(new DecalVertex(vertex.clone(), normal.clone()));
}
function clipGeometry(inVertices, plane2) {
const outVertices = [];
const s = 0.5 * Math.abs(size.dot(plane2));
for (let i = 0; i < inVertices.length; i += 3) {
let v1Out, v2Out, v3Out, total = 0;
let nV1, nV2, nV3, nV4;
const d1 = inVertices[i + 0].position.dot(plane2) - s;
const d2 = inVertices[i + 1].position.dot(plane2) - s;
const d3 = inVertices[i + 2].position.dot(plane2) - s;
v1Out = d1 > 0;
v2Out = d2 > 0;
v3Out = d3 > 0;
total = (v1Out ? 1 : 0) + (v2Out ? 1 : 0) + (v3Out ? 1 : 0);
switch (total) {
case 0: {
outVertices.push(inVertices[i]);
outVertices.push(inVertices[i + 1]);
outVertices.push(inVertices[i + 2]);
break;
}
case 1: {
if (v1Out) {
nV1 = inVertices[i + 1];
nV2 = inVertices[i + 2];
nV3 = clip(inVertices[i], nV1, plane2, s);
nV4 = clip(inVertices[i], nV2, plane2, s);
}
if (v2Out) {
nV1 = inVertices[i];
nV2 = inVertices[i + 2];
nV3 = clip(inVertices[i + 1], nV1, plane2, s);
nV4 = clip(inVertices[i + 1], nV2, plane2, s);
outVertices.push(nV3);
outVertices.push(nV2.clone());
outVertices.push(nV1.clone());
outVertices.push(nV2.clone());
outVertices.push(nV3.clone());
outVertices.push(nV4);
break;
}
if (v3Out) {
nV1 = inVertices[i];
nV2 = inVertices[i + 1];
nV3 = clip(inVertices[i + 2], nV1, plane2, s);
nV4 = clip(inVertices[i + 2], nV2, plane2, s);
}
outVertices.push(nV1.clone());
outVertices.push(nV2.clone());
outVertices.push(nV3);
outVertices.push(nV4);
outVertices.push(nV3.clone());
outVertices.push(nV2.clone());
break;
}
case 2: {
if (!v1Out) {
nV1 = inVertices[i].clone();
nV2 = clip(nV1, inVertices[i + 1], plane2, s);
nV3 = clip(nV1, inVertices[i + 2], plane2, s);
outVertices.push(nV1);
outVertices.push(nV2);
outVertices.push(nV3);
}
if (!v2Out) {
nV1 = inVertices[i + 1].clone();
nV2 = clip(nV1, inVertices[i + 2], plane2, s);
nV3 = clip(nV1, inVertices[i], plane2, s);
outVertices.push(nV1);
outVertices.push(nV2);
outVertices.push(nV3);
}
if (!v3Out) {
nV1 = inVertices[i + 2].clone();
nV2 = clip(nV1, inVertices[i], plane2, s);
nV3 = clip(nV1, inVertices[i + 1], plane2, s);
outVertices.push(nV1);
outVertices.push(nV2);
outVertices.push(nV3);
}
break;
}
}
}
return outVertices;
}
function clip(v0, v1, p, s) {
const d0 = v0.position.dot(p) - s;
const d1 = v1.position.dot(p) - s;
const s0 = d0 / (d0 - d1);
const v = new DecalVertex(
new THREE.Vector3(
v0.position.x + s0 * (v1.position.x - v0.position.x),
v0.position.y + s0 * (v1.position.y - v0.position.y),
v0.position.z + s0 * (v1.position.z - v0.position.z)
),
new THREE.Vector3(
v0.normal.x + s0 * (v1.normal.x - v0.normal.x),
v0.normal.y + s0 * (v1.normal.y - v0.normal.y),
v0.normal.z + s0 * (v1.normal.z - v0.normal.z)
)
);
return v;
}
}
}
class DecalVertex {
constructor(position, normal) {
this.position = position;
this.normal = normal;
}
clone() {
return new this.constructor(this.position.clone(), this.normal.clone());
}
}
exports.DecalGeometry = DecalGeometry;
exports.DecalVertex = DecalVertex;
//# sourceMappingURL=DecalGeometry.cjs.map
File diff suppressed because one or more lines are too long
+10
View File
@@ -0,0 +1,10 @@
import { BufferGeometry, Euler, Mesh, Vector3 } from 'three'
export class DecalGeometry extends BufferGeometry {
constructor(mesh: Mesh, position: Vector3, orientation: Euler, size: Vector3)
}
export class DecalVertex {
constructor(position: Vector3, normal: Vector3)
clone(): this
}
+182
View File
@@ -0,0 +1,182 @@
import { BufferGeometry, Vector3, Matrix4, Float32BufferAttribute } from "three";
class DecalGeometry extends BufferGeometry {
constructor(mesh, position, orientation, size) {
super();
const vertices = [];
const normals = [];
const uvs = [];
const plane = new Vector3();
const projectorMatrix = new Matrix4();
projectorMatrix.makeRotationFromEuler(orientation);
projectorMatrix.setPosition(position);
const projectorMatrixInverse = new Matrix4();
projectorMatrixInverse.copy(projectorMatrix).invert();
generate();
this.setAttribute("position", new Float32BufferAttribute(vertices, 3));
this.setAttribute("normal", new Float32BufferAttribute(normals, 3));
this.setAttribute("uv", new Float32BufferAttribute(uvs, 2));
function generate() {
let i;
let decalVertices = [];
const vertex = new Vector3();
const normal = new Vector3();
if (mesh.geometry.isGeometry === true) {
console.error("THREE.DecalGeometry no longer supports THREE.Geometry. Use BufferGeometry instead.");
return;
}
const geometry = mesh.geometry;
const positionAttribute = geometry.attributes.position;
const normalAttribute = geometry.attributes.normal;
if (geometry.index !== null) {
const index = geometry.index;
for (i = 0; i < index.count; i++) {
vertex.fromBufferAttribute(positionAttribute, index.getX(i));
normal.fromBufferAttribute(normalAttribute, index.getX(i));
pushDecalVertex(decalVertices, vertex, normal);
}
} else {
for (i = 0; i < positionAttribute.count; i++) {
vertex.fromBufferAttribute(positionAttribute, i);
normal.fromBufferAttribute(normalAttribute, i);
pushDecalVertex(decalVertices, vertex, normal);
}
}
decalVertices = clipGeometry(decalVertices, plane.set(1, 0, 0));
decalVertices = clipGeometry(decalVertices, plane.set(-1, 0, 0));
decalVertices = clipGeometry(decalVertices, plane.set(0, 1, 0));
decalVertices = clipGeometry(decalVertices, plane.set(0, -1, 0));
decalVertices = clipGeometry(decalVertices, plane.set(0, 0, 1));
decalVertices = clipGeometry(decalVertices, plane.set(0, 0, -1));
for (i = 0; i < decalVertices.length; i++) {
const decalVertex = decalVertices[i];
uvs.push(0.5 + decalVertex.position.x / size.x, 0.5 + decalVertex.position.y / size.y);
decalVertex.position.applyMatrix4(projectorMatrix);
vertices.push(decalVertex.position.x, decalVertex.position.y, decalVertex.position.z);
normals.push(decalVertex.normal.x, decalVertex.normal.y, decalVertex.normal.z);
}
}
function pushDecalVertex(decalVertices, vertex, normal) {
vertex.applyMatrix4(mesh.matrixWorld);
vertex.applyMatrix4(projectorMatrixInverse);
normal.transformDirection(mesh.matrixWorld);
decalVertices.push(new DecalVertex(vertex.clone(), normal.clone()));
}
function clipGeometry(inVertices, plane2) {
const outVertices = [];
const s = 0.5 * Math.abs(size.dot(plane2));
for (let i = 0; i < inVertices.length; i += 3) {
let v1Out, v2Out, v3Out, total = 0;
let nV1, nV2, nV3, nV4;
const d1 = inVertices[i + 0].position.dot(plane2) - s;
const d2 = inVertices[i + 1].position.dot(plane2) - s;
const d3 = inVertices[i + 2].position.dot(plane2) - s;
v1Out = d1 > 0;
v2Out = d2 > 0;
v3Out = d3 > 0;
total = (v1Out ? 1 : 0) + (v2Out ? 1 : 0) + (v3Out ? 1 : 0);
switch (total) {
case 0: {
outVertices.push(inVertices[i]);
outVertices.push(inVertices[i + 1]);
outVertices.push(inVertices[i + 2]);
break;
}
case 1: {
if (v1Out) {
nV1 = inVertices[i + 1];
nV2 = inVertices[i + 2];
nV3 = clip(inVertices[i], nV1, plane2, s);
nV4 = clip(inVertices[i], nV2, plane2, s);
}
if (v2Out) {
nV1 = inVertices[i];
nV2 = inVertices[i + 2];
nV3 = clip(inVertices[i + 1], nV1, plane2, s);
nV4 = clip(inVertices[i + 1], nV2, plane2, s);
outVertices.push(nV3);
outVertices.push(nV2.clone());
outVertices.push(nV1.clone());
outVertices.push(nV2.clone());
outVertices.push(nV3.clone());
outVertices.push(nV4);
break;
}
if (v3Out) {
nV1 = inVertices[i];
nV2 = inVertices[i + 1];
nV3 = clip(inVertices[i + 2], nV1, plane2, s);
nV4 = clip(inVertices[i + 2], nV2, plane2, s);
}
outVertices.push(nV1.clone());
outVertices.push(nV2.clone());
outVertices.push(nV3);
outVertices.push(nV4);
outVertices.push(nV3.clone());
outVertices.push(nV2.clone());
break;
}
case 2: {
if (!v1Out) {
nV1 = inVertices[i].clone();
nV2 = clip(nV1, inVertices[i + 1], plane2, s);
nV3 = clip(nV1, inVertices[i + 2], plane2, s);
outVertices.push(nV1);
outVertices.push(nV2);
outVertices.push(nV3);
}
if (!v2Out) {
nV1 = inVertices[i + 1].clone();
nV2 = clip(nV1, inVertices[i + 2], plane2, s);
nV3 = clip(nV1, inVertices[i], plane2, s);
outVertices.push(nV1);
outVertices.push(nV2);
outVertices.push(nV3);
}
if (!v3Out) {
nV1 = inVertices[i + 2].clone();
nV2 = clip(nV1, inVertices[i], plane2, s);
nV3 = clip(nV1, inVertices[i + 1], plane2, s);
outVertices.push(nV1);
outVertices.push(nV2);
outVertices.push(nV3);
}
break;
}
}
}
return outVertices;
}
function clip(v0, v1, p, s) {
const d0 = v0.position.dot(p) - s;
const d1 = v1.position.dot(p) - s;
const s0 = d0 / (d0 - d1);
const v = new DecalVertex(
new Vector3(
v0.position.x + s0 * (v1.position.x - v0.position.x),
v0.position.y + s0 * (v1.position.y - v0.position.y),
v0.position.z + s0 * (v1.position.z - v0.position.z)
),
new Vector3(
v0.normal.x + s0 * (v1.normal.x - v0.normal.x),
v0.normal.y + s0 * (v1.normal.y - v0.normal.y),
v0.normal.z + s0 * (v1.normal.z - v0.normal.z)
)
);
return v;
}
}
}
class DecalVertex {
constructor(position, normal) {
this.position = position;
this.normal = normal;
}
clone() {
return new this.constructor(this.position.clone(), this.normal.clone());
}
}
export {
DecalGeometry,
DecalVertex
};
//# sourceMappingURL=DecalGeometry.js.map
File diff suppressed because one or more lines are too long
+563
View File
@@ -0,0 +1,563 @@
"use strict";
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const SimplexNoise = require("../math/SimplexNoise.cjs");
const LightningStrike = /* @__PURE__ */ (() => {
const _LightningStrike = class extends THREE.BufferGeometry {
constructor(rayParameters = {}) {
super();
this.isLightningStrike = true;
this.type = "LightningStrike";
this.init(_LightningStrike.copyParameters(rayParameters, rayParameters));
this.createMesh();
}
static createRandomGenerator() {
const numSeeds = 2053;
const seeds = [];
for (let i = 0; i < numSeeds; i++) {
seeds.push(Math.random());
}
const generator = {
currentSeed: 0,
random: function() {
const value = seeds[generator.currentSeed];
generator.currentSeed = (generator.currentSeed + 1) % numSeeds;
return value;
},
getSeed: function() {
return generator.currentSeed / numSeeds;
},
setSeed: function(seed) {
generator.currentSeed = Math.floor(seed * numSeeds) % numSeeds;
}
};
return generator;
}
static copyParameters(dest = {}, source = {}) {
const vecCopy = function(v) {
if (source === dest) {
return v;
} else {
return v.clone();
}
};
dest.sourceOffset = source.sourceOffset !== void 0 ? vecCopy(source.sourceOffset) : new THREE.Vector3(0, 100, 0), dest.destOffset = source.destOffset !== void 0 ? vecCopy(source.destOffset) : new THREE.Vector3(0, 0, 0), dest.timeScale = source.timeScale !== void 0 ? source.timeScale : 1, dest.roughness = source.roughness !== void 0 ? source.roughness : 0.9, dest.straightness = source.straightness !== void 0 ? source.straightness : 0.7, dest.up0 = source.up0 !== void 0 ? vecCopy(source.up0) : new THREE.Vector3(0, 0, 1);
dest.up1 = source.up1 !== void 0 ? vecCopy(source.up1) : new THREE.Vector3(0, 0, 1), dest.radius0 = source.radius0 !== void 0 ? source.radius0 : 1, dest.radius1 = source.radius1 !== void 0 ? source.radius1 : 1, dest.radius0Factor = source.radius0Factor !== void 0 ? source.radius0Factor : 0.5, dest.radius1Factor = source.radius1Factor !== void 0 ? source.radius1Factor : 0.2, dest.minRadius = source.minRadius !== void 0 ? source.minRadius : 0.2, // These parameters should not be changed after lightning creation. They can be changed but the ray will change its form abruptly:
dest.isEternal = source.isEternal !== void 0 ? source.isEternal : source.birthTime === void 0 || source.deathTime === void 0, dest.birthTime = source.birthTime, dest.deathTime = source.deathTime, dest.propagationTimeFactor = source.propagationTimeFactor !== void 0 ? source.propagationTimeFactor : 0.1, dest.vanishingTimeFactor = source.vanishingTimeFactor !== void 0 ? source.vanishingTimeFactor : 0.9, dest.subrayPeriod = source.subrayPeriod !== void 0 ? source.subrayPeriod : 4, dest.subrayDutyCycle = source.subrayDutyCycle !== void 0 ? source.subrayDutyCycle : 0.6;
dest.maxIterations = source.maxIterations !== void 0 ? source.maxIterations : 9;
dest.isStatic = source.isStatic !== void 0 ? source.isStatic : false;
dest.ramification = source.ramification !== void 0 ? source.ramification : 5;
dest.maxSubrayRecursion = source.maxSubrayRecursion !== void 0 ? source.maxSubrayRecursion : 3;
dest.recursionProbability = source.recursionProbability !== void 0 ? source.recursionProbability : 0.6;
dest.generateUVs = source.generateUVs !== void 0 ? source.generateUVs : false;
dest.randomGenerator = source.randomGenerator, dest.noiseSeed = source.noiseSeed, dest.onDecideSubrayCreation = source.onDecideSubrayCreation, dest.onSubrayCreation = source.onSubrayCreation;
return dest;
}
update(time) {
if (this.isStatic)
return;
if (this.rayParameters.isEternal || this.rayParameters.birthTime <= time && time <= this.rayParameters.deathTime) {
this.updateMesh(time);
if (time < this.subrays[0].endPropagationTime) {
this.state = _LightningStrike.RAY_PROPAGATING;
} else if (time > this.subrays[0].beginVanishingTime) {
this.state = _LightningStrike.RAY_VANISHING;
} else {
this.state = _LightningStrike.RAY_STEADY;
}
this.visible = true;
} else {
this.visible = false;
if (time < this.rayParameters.birthTime) {
this.state = _LightningStrike.RAY_UNBORN;
} else {
this.state = _LightningStrike.RAY_EXTINGUISHED;
}
}
}
init(rayParameters) {
this.rayParameters = rayParameters;
this.maxIterations = rayParameters.maxIterations !== void 0 ? Math.floor(rayParameters.maxIterations) : 9;
rayParameters.maxIterations = this.maxIterations;
this.isStatic = rayParameters.isStatic !== void 0 ? rayParameters.isStatic : false;
rayParameters.isStatic = this.isStatic;
this.ramification = rayParameters.ramification !== void 0 ? Math.floor(rayParameters.ramification) : 5;
rayParameters.ramification = this.ramification;
this.maxSubrayRecursion = rayParameters.maxSubrayRecursion !== void 0 ? Math.floor(rayParameters.maxSubrayRecursion) : 3;
rayParameters.maxSubrayRecursion = this.maxSubrayRecursion;
this.recursionProbability = rayParameters.recursionProbability !== void 0 ? rayParameters.recursionProbability : 0.6;
rayParameters.recursionProbability = this.recursionProbability;
this.generateUVs = rayParameters.generateUVs !== void 0 ? rayParameters.generateUVs : false;
rayParameters.generateUVs = this.generateUVs;
if (rayParameters.randomGenerator !== void 0) {
this.randomGenerator = rayParameters.randomGenerator;
this.seedGenerator = rayParameters.randomGenerator;
if (rayParameters.noiseSeed !== void 0) {
this.seedGenerator.setSeed(rayParameters.noiseSeed);
}
} else {
this.randomGenerator = _LightningStrike.createRandomGenerator();
this.seedGenerator = Math;
}
if (rayParameters.onDecideSubrayCreation !== void 0) {
this.onDecideSubrayCreation = rayParameters.onDecideSubrayCreation;
} else {
this.createDefaultSubrayCreationCallbacks();
if (rayParameters.onSubrayCreation !== void 0) {
this.onSubrayCreation = rayParameters.onSubrayCreation;
}
}
this.state = _LightningStrike.RAY_INITIALIZED;
this.maxSubrays = Math.ceil(1 + Math.pow(this.ramification, Math.max(0, this.maxSubrayRecursion - 1)));
rayParameters.maxSubrays = this.maxSubrays;
this.maxRaySegments = 2 * (1 << this.maxIterations);
this.subrays = [];
for (let i = 0; i < this.maxSubrays; i++) {
this.subrays.push(this.createSubray());
}
this.raySegments = [];
for (let i = 0; i < this.maxRaySegments; i++) {
this.raySegments.push(this.createSegment());
}
this.time = 0;
this.timeFraction = 0;
this.currentSegmentCallback = null;
this.currentCreateTriangleVertices = this.generateUVs ? this.createTriangleVerticesWithUVs : this.createTriangleVerticesWithoutUVs;
this.numSubrays = 0;
this.currentSubray = null;
this.currentSegmentIndex = 0;
this.isInitialSegment = false;
this.subrayProbability = 0;
this.currentVertex = 0;
this.currentIndex = 0;
this.currentCoordinate = 0;
this.currentUVCoordinate = 0;
this.vertices = null;
this.uvs = null;
this.indices = null;
this.positionAttribute = null;
this.uvsAttribute = null;
this.simplexX = new SimplexNoise.SimplexNoise(this.seedGenerator);
this.simplexY = new SimplexNoise.SimplexNoise(this.seedGenerator);
this.simplexZ = new SimplexNoise.SimplexNoise(this.seedGenerator);
this.forwards = new THREE.Vector3();
this.forwardsFill = new THREE.Vector3();
this.side = new THREE.Vector3();
this.down = new THREE.Vector3();
this.middlePos = new THREE.Vector3();
this.middleLinPos = new THREE.Vector3();
this.newPos = new THREE.Vector3();
this.vPos = new THREE.Vector3();
this.cross1 = new THREE.Vector3();
}
createMesh() {
const maxDrawableSegmentsPerSubRay = 1 << this.maxIterations;
const maxVerts = 3 * (maxDrawableSegmentsPerSubRay + 1) * this.maxSubrays;
const maxIndices = 18 * maxDrawableSegmentsPerSubRay * this.maxSubrays;
this.vertices = new Float32Array(maxVerts * 3);
this.indices = new Uint32Array(maxIndices);
if (this.generateUVs) {
this.uvs = new Float32Array(maxVerts * 2);
}
this.fillMesh(0);
this.setIndex(new THREE.Uint32BufferAttribute(this.indices, 1));
this.positionAttribute = new THREE.Float32BufferAttribute(this.vertices, 3);
this.setAttribute("position", this.positionAttribute);
if (this.generateUVs) {
this.uvsAttribute = new THREE.Float32BufferAttribute(new Float32Array(this.uvs), 2);
this.setAttribute("uv", this.uvsAttribute);
}
if (!this.isStatic) {
this.index.usage = THREE.DynamicDrawUsage;
this.positionAttribute.usage = THREE.DynamicDrawUsage;
if (this.generateUVs) {
this.uvsAttribute.usage = THREE.DynamicDrawUsage;
}
}
this.vertices = this.positionAttribute.array;
this.indices = this.index.array;
if (this.generateUVs) {
this.uvs = this.uvsAttribute.array;
}
}
updateMesh(time) {
this.fillMesh(time);
this.drawRange.count = this.currentIndex;
this.index.needsUpdate = true;
this.positionAttribute.needsUpdate = true;
if (this.generateUVs) {
this.uvsAttribute.needsUpdate = true;
}
}
fillMesh(time) {
const scope = this;
this.currentVertex = 0;
this.currentIndex = 0;
this.currentCoordinate = 0;
this.currentUVCoordinate = 0;
this.fractalRay(time, function fillVertices(segment) {
const subray = scope.currentSubray;
if (time < subray.birthTime) {
return;
} else if (this.rayParameters.isEternal && scope.currentSubray.recursion == 0) {
scope.createPrism(segment);
scope.onDecideSubrayCreation(segment, scope);
} else if (time < subray.endPropagationTime) {
if (scope.timeFraction >= segment.fraction0 * subray.propagationTimeFactor) {
scope.createPrism(segment);
scope.onDecideSubrayCreation(segment, scope);
}
} else if (time < subray.beginVanishingTime) {
scope.createPrism(segment);
scope.onDecideSubrayCreation(segment, scope);
} else {
if (scope.timeFraction <= subray.vanishingTimeFactor + segment.fraction1 * (1 - subray.vanishingTimeFactor)) {
scope.createPrism(segment);
}
scope.onDecideSubrayCreation(segment, scope);
}
});
}
addNewSubray() {
return this.subrays[this.numSubrays++];
}
initSubray(subray, rayParameters) {
subray.pos0.copy(rayParameters.sourceOffset);
subray.pos1.copy(rayParameters.destOffset);
subray.up0.copy(rayParameters.up0);
subray.up1.copy(rayParameters.up1);
subray.radius0 = rayParameters.radius0;
subray.radius1 = rayParameters.radius1;
subray.birthTime = rayParameters.birthTime;
subray.deathTime = rayParameters.deathTime;
subray.timeScale = rayParameters.timeScale;
subray.roughness = rayParameters.roughness;
subray.straightness = rayParameters.straightness;
subray.propagationTimeFactor = rayParameters.propagationTimeFactor;
subray.vanishingTimeFactor = rayParameters.vanishingTimeFactor;
subray.maxIterations = this.maxIterations;
subray.seed = rayParameters.noiseSeed !== void 0 ? rayParameters.noiseSeed : 0;
subray.recursion = 0;
}
fractalRay(time, segmentCallback) {
this.time = time;
this.currentSegmentCallback = segmentCallback;
this.numSubrays = 0;
this.initSubray(this.addNewSubray(), this.rayParameters);
for (let subrayIndex = 0; subrayIndex < this.numSubrays; subrayIndex++) {
const subray = this.subrays[subrayIndex];
this.currentSubray = subray;
this.randomGenerator.setSeed(subray.seed);
subray.endPropagationTime = THREE.MathUtils.lerp(subray.birthTime, subray.deathTime, subray.propagationTimeFactor);
subray.beginVanishingTime = THREE.MathUtils.lerp(subray.deathTime, subray.birthTime, 1 - subray.vanishingTimeFactor);
const random1 = this.randomGenerator.random;
subray.linPos0.set(random1(), random1(), random1()).multiplyScalar(1e3);
subray.linPos1.set(random1(), random1(), random1()).multiplyScalar(1e3);
this.timeFraction = (time - subray.birthTime) / (subray.deathTime - subray.birthTime);
this.currentSegmentIndex = 0;
this.isInitialSegment = true;
const segment = this.getNewSegment();
segment.iteration = 0;
segment.pos0.copy(subray.pos0);
segment.pos1.copy(subray.pos1);
segment.linPos0.copy(subray.linPos0);
segment.linPos1.copy(subray.linPos1);
segment.up0.copy(subray.up0);
segment.up1.copy(subray.up1);
segment.radius0 = subray.radius0;
segment.radius1 = subray.radius1;
segment.fraction0 = 0;
segment.fraction1 = 1;
segment.positionVariationFactor = 1 - subray.straightness;
this.subrayProbability = this.ramification * Math.pow(this.recursionProbability, subray.recursion) / (1 << subray.maxIterations);
this.fractalRayRecursive(segment);
}
this.currentSegmentCallback = null;
this.currentSubray = null;
}
fractalRayRecursive(segment) {
if (segment.iteration >= this.currentSubray.maxIterations) {
this.currentSegmentCallback(segment);
return;
}
this.forwards.subVectors(segment.pos1, segment.pos0);
let lForwards = this.forwards.length();
if (lForwards < 1e-6) {
this.forwards.set(0, 0, 0.01);
lForwards = this.forwards.length();
}
const middleRadius = (segment.radius0 + segment.radius1) * 0.5;
const middleFraction = (segment.fraction0 + segment.fraction1) * 0.5;
const timeDimension = this.time * this.currentSubray.timeScale * Math.pow(2, segment.iteration);
this.middlePos.lerpVectors(segment.pos0, segment.pos1, 0.5);
this.middleLinPos.lerpVectors(segment.linPos0, segment.linPos1, 0.5);
const p = this.middleLinPos;
this.newPos.set(
this.simplexX.noise4d(p.x, p.y, p.z, timeDimension),
this.simplexY.noise4d(p.x, p.y, p.z, timeDimension),
this.simplexZ.noise4d(p.x, p.y, p.z, timeDimension)
);
this.newPos.multiplyScalar(segment.positionVariationFactor * lForwards);
this.newPos.add(this.middlePos);
const newSegment1 = this.getNewSegment();
newSegment1.pos0.copy(segment.pos0);
newSegment1.pos1.copy(this.newPos);
newSegment1.linPos0.copy(segment.linPos0);
newSegment1.linPos1.copy(this.middleLinPos);
newSegment1.up0.copy(segment.up0);
newSegment1.up1.copy(segment.up1);
newSegment1.radius0 = segment.radius0;
newSegment1.radius1 = middleRadius;
newSegment1.fraction0 = segment.fraction0;
newSegment1.fraction1 = middleFraction;
newSegment1.positionVariationFactor = segment.positionVariationFactor * this.currentSubray.roughness;
newSegment1.iteration = segment.iteration + 1;
const newSegment2 = this.getNewSegment();
newSegment2.pos0.copy(this.newPos);
newSegment2.pos1.copy(segment.pos1);
newSegment2.linPos0.copy(this.middleLinPos);
newSegment2.linPos1.copy(segment.linPos1);
this.cross1.crossVectors(segment.up0, this.forwards.normalize());
newSegment2.up0.crossVectors(this.forwards, this.cross1).normalize();
newSegment2.up1.copy(segment.up1);
newSegment2.radius0 = middleRadius;
newSegment2.radius1 = segment.radius1;
newSegment2.fraction0 = middleFraction;
newSegment2.fraction1 = segment.fraction1;
newSegment2.positionVariationFactor = segment.positionVariationFactor * this.currentSubray.roughness;
newSegment2.iteration = segment.iteration + 1;
this.fractalRayRecursive(newSegment1);
this.fractalRayRecursive(newSegment2);
}
createPrism(segment) {
this.forwardsFill.subVectors(segment.pos1, segment.pos0).normalize();
if (this.isInitialSegment) {
this.currentCreateTriangleVertices(segment.pos0, segment.up0, this.forwardsFill, segment.radius0, 0);
this.isInitialSegment = false;
}
this.currentCreateTriangleVertices(
segment.pos1,
segment.up0,
this.forwardsFill,
segment.radius1,
segment.fraction1
);
this.createPrismFaces();
}
createTriangleVerticesWithoutUVs(pos, up, forwards, radius) {
this.side.crossVectors(up, forwards).multiplyScalar(radius * _LightningStrike.COS30DEG);
this.down.copy(up).multiplyScalar(-radius * _LightningStrike.SIN30DEG);
const p = this.vPos;
const v = this.vertices;
p.copy(pos).sub(this.side).add(this.down);
v[this.currentCoordinate++] = p.x;
v[this.currentCoordinate++] = p.y;
v[this.currentCoordinate++] = p.z;
p.copy(pos).add(this.side).add(this.down);
v[this.currentCoordinate++] = p.x;
v[this.currentCoordinate++] = p.y;
v[this.currentCoordinate++] = p.z;
p.copy(up).multiplyScalar(radius).add(pos);
v[this.currentCoordinate++] = p.x;
v[this.currentCoordinate++] = p.y;
v[this.currentCoordinate++] = p.z;
this.currentVertex += 3;
}
createTriangleVerticesWithUVs(pos, up, forwards, radius, u) {
this.side.crossVectors(up, forwards).multiplyScalar(radius * _LightningStrike.COS30DEG);
this.down.copy(up).multiplyScalar(-radius * _LightningStrike.SIN30DEG);
const p = this.vPos;
const v = this.vertices;
const uv = this.uvs;
p.copy(pos).sub(this.side).add(this.down);
v[this.currentCoordinate++] = p.x;
v[this.currentCoordinate++] = p.y;
v[this.currentCoordinate++] = p.z;
uv[this.currentUVCoordinate++] = u;
uv[this.currentUVCoordinate++] = 0;
p.copy(pos).add(this.side).add(this.down);
v[this.currentCoordinate++] = p.x;
v[this.currentCoordinate++] = p.y;
v[this.currentCoordinate++] = p.z;
uv[this.currentUVCoordinate++] = u;
uv[this.currentUVCoordinate++] = 0.5;
p.copy(up).multiplyScalar(radius).add(pos);
v[this.currentCoordinate++] = p.x;
v[this.currentCoordinate++] = p.y;
v[this.currentCoordinate++] = p.z;
uv[this.currentUVCoordinate++] = u;
uv[this.currentUVCoordinate++] = 1;
this.currentVertex += 3;
}
createPrismFaces(vertex) {
const indices = this.indices;
vertex = this.currentVertex - 6;
indices[this.currentIndex++] = vertex + 1;
indices[this.currentIndex++] = vertex + 2;
indices[this.currentIndex++] = vertex + 5;
indices[this.currentIndex++] = vertex + 1;
indices[this.currentIndex++] = vertex + 5;
indices[this.currentIndex++] = vertex + 4;
indices[this.currentIndex++] = vertex + 0;
indices[this.currentIndex++] = vertex + 1;
indices[this.currentIndex++] = vertex + 4;
indices[this.currentIndex++] = vertex + 0;
indices[this.currentIndex++] = vertex + 4;
indices[this.currentIndex++] = vertex + 3;
indices[this.currentIndex++] = vertex + 2;
indices[this.currentIndex++] = vertex + 0;
indices[this.currentIndex++] = vertex + 3;
indices[this.currentIndex++] = vertex + 2;
indices[this.currentIndex++] = vertex + 3;
indices[this.currentIndex++] = vertex + 5;
}
createDefaultSubrayCreationCallbacks() {
const random1 = this.randomGenerator.random;
this.onDecideSubrayCreation = function(segment, lightningStrike) {
const subray = lightningStrike.currentSubray;
const period = lightningStrike.rayParameters.subrayPeriod;
const dutyCycle = lightningStrike.rayParameters.subrayDutyCycle;
const phase0 = lightningStrike.rayParameters.isEternal && subray.recursion == 0 ? -random1() * period : THREE.MathUtils.lerp(subray.birthTime, subray.endPropagationTime, segment.fraction0) - random1() * period;
const phase = lightningStrike.time - phase0;
const currentCycle = Math.floor(phase / period);
const childSubraySeed = random1() * (currentCycle + 1);
const isActive = phase % period <= dutyCycle * period;
let probability = 0;
if (isActive) {
probability = lightningStrike.subrayProbability;
}
if (subray.recursion < lightningStrike.maxSubrayRecursion && lightningStrike.numSubrays < lightningStrike.maxSubrays && random1() < probability) {
const childSubray = lightningStrike.addNewSubray();
const parentSeed = lightningStrike.randomGenerator.getSeed();
childSubray.seed = childSubraySeed;
lightningStrike.randomGenerator.setSeed(childSubraySeed);
childSubray.recursion = subray.recursion + 1;
childSubray.maxIterations = Math.max(1, subray.maxIterations - 1);
childSubray.linPos0.set(random1(), random1(), random1()).multiplyScalar(1e3);
childSubray.linPos1.set(random1(), random1(), random1()).multiplyScalar(1e3);
childSubray.up0.copy(subray.up0);
childSubray.up1.copy(subray.up1);
childSubray.radius0 = segment.radius0 * lightningStrike.rayParameters.radius0Factor;
childSubray.radius1 = Math.min(
lightningStrike.rayParameters.minRadius,
segment.radius1 * lightningStrike.rayParameters.radius1Factor
);
childSubray.birthTime = phase0 + currentCycle * period;
childSubray.deathTime = childSubray.birthTime + period * dutyCycle;
if (!lightningStrike.rayParameters.isEternal && subray.recursion == 0) {
childSubray.birthTime = Math.max(childSubray.birthTime, subray.birthTime);
childSubray.deathTime = Math.min(childSubray.deathTime, subray.deathTime);
}
childSubray.timeScale = subray.timeScale * 2;
childSubray.roughness = subray.roughness;
childSubray.straightness = subray.straightness;
childSubray.propagationTimeFactor = subray.propagationTimeFactor;
childSubray.vanishingTimeFactor = subray.vanishingTimeFactor;
lightningStrike.onSubrayCreation(segment, subray, childSubray, lightningStrike);
lightningStrike.randomGenerator.setSeed(parentSeed);
}
};
const vec1Pos = new THREE.Vector3();
const vec2Forward = new THREE.Vector3();
const vec3Side = new THREE.Vector3();
const vec4Up = new THREE.Vector3();
this.onSubrayCreation = function(segment, parentSubray, childSubray, lightningStrike) {
lightningStrike.subrayCylinderPosition(segment, parentSubray, childSubray, 0.5, 0.6, 0.2);
};
this.subrayConePosition = function(segment, parentSubray, childSubray, heightFactor, sideWidthFactor, minSideWidthFactor) {
childSubray.pos0.copy(segment.pos0);
vec1Pos.subVectors(parentSubray.pos1, parentSubray.pos0);
vec2Forward.copy(vec1Pos).normalize();
vec1Pos.multiplyScalar(segment.fraction0 + (1 - segment.fraction0) * (random1() * heightFactor));
const length = vec1Pos.length();
vec3Side.crossVectors(parentSubray.up0, vec2Forward);
const angle = 2 * Math.PI * random1();
vec3Side.multiplyScalar(Math.cos(angle));
vec4Up.copy(parentSubray.up0).multiplyScalar(Math.sin(angle));
childSubray.pos1.copy(vec3Side).add(vec4Up).multiplyScalar(length * sideWidthFactor * (minSideWidthFactor + random1() * (1 - minSideWidthFactor))).add(vec1Pos).add(parentSubray.pos0);
};
this.subrayCylinderPosition = function(segment, parentSubray, childSubray, heightFactor, sideWidthFactor, minSideWidthFactor) {
childSubray.pos0.copy(segment.pos0);
vec1Pos.subVectors(parentSubray.pos1, parentSubray.pos0);
vec2Forward.copy(vec1Pos).normalize();
vec1Pos.multiplyScalar(segment.fraction0 + (1 - segment.fraction0) * ((2 * random1() - 1) * heightFactor));
const length = vec1Pos.length();
vec3Side.crossVectors(parentSubray.up0, vec2Forward);
const angle = 2 * Math.PI * random1();
vec3Side.multiplyScalar(Math.cos(angle));
vec4Up.copy(parentSubray.up0).multiplyScalar(Math.sin(angle));
childSubray.pos1.copy(vec3Side).add(vec4Up).multiplyScalar(length * sideWidthFactor * (minSideWidthFactor + random1() * (1 - minSideWidthFactor))).add(vec1Pos).add(parentSubray.pos0);
};
}
createSubray() {
return {
seed: 0,
maxIterations: 0,
recursion: 0,
pos0: new THREE.Vector3(),
pos1: new THREE.Vector3(),
linPos0: new THREE.Vector3(),
linPos1: new THREE.Vector3(),
up0: new THREE.Vector3(),
up1: new THREE.Vector3(),
radius0: 0,
radius1: 0,
birthTime: 0,
deathTime: 0,
timeScale: 0,
roughness: 0,
straightness: 0,
propagationTimeFactor: 0,
vanishingTimeFactor: 0,
endPropagationTime: 0,
beginVanishingTime: 0
};
}
createSegment() {
return {
iteration: 0,
pos0: new THREE.Vector3(),
pos1: new THREE.Vector3(),
linPos0: new THREE.Vector3(),
linPos1: new THREE.Vector3(),
up0: new THREE.Vector3(),
up1: new THREE.Vector3(),
radius0: 0,
radius1: 0,
fraction0: 0,
fraction1: 0,
positionVariationFactor: 0
};
}
getNewSegment() {
return this.raySegments[this.currentSegmentIndex++];
}
copy(source) {
super.copy(source);
this.init(_LightningStrike.copyParameters({}, source.rayParameters));
return this;
}
clone() {
return new this.constructor(_LightningStrike.copyParameters({}, this.rayParameters));
}
};
let LightningStrike2 = _LightningStrike;
// Ray states
__publicField(LightningStrike2, "RAY_INITIALIZED", 0);
__publicField(LightningStrike2, "RAY_UNBORN", 1);
__publicField(LightningStrike2, "RAY_PROPAGATING", 2);
__publicField(LightningStrike2, "RAY_STEADY", 3);
__publicField(LightningStrike2, "RAY_VANISHING", 4);
__publicField(LightningStrike2, "RAY_EXTINGUISHED", 5);
__publicField(LightningStrike2, "COS30DEG", Math.cos(30 * Math.PI / 180));
__publicField(LightningStrike2, "SIN30DEG", Math.sin(30 * Math.PI / 180));
return LightningStrike2;
})();
exports.LightningStrike = LightningStrike;
//# sourceMappingURL=LightningStrike.cjs.map
File diff suppressed because one or more lines are too long
+108
View File
@@ -0,0 +1,108 @@
import { BufferGeometry, Vector3 } from 'three'
export interface RandomGenerator {
random(): number
getSeed(): number
setSeed(seed: number): void
}
export interface LightningSegment {
iteration: number
pos0: Vector3
pos1: Vector3
linPos0: Vector3
linPos1: Vector3
up0: Vector3
up1: Vector3
radius0: number
radius1: number
fraction0: number
fraction1: number
positionVariationFactor: number
}
export interface LightningSubray {
seed: number
maxIterations: number
recursion: number
pos0: Vector3
pos1: Vector3
linPos0: Vector3
linPos1: Vector3
up0: Vector3
up1: Vector3
radius0: number
radius1: number
birthTime: number
deathTime: number
timeScale: number
roughness: number
straightness: number
propagationTimeFactor: number
vanishingTimeFactor: number
endPropagationTime: number
beginVanishingTime: number
}
export interface RayParameters {
sourceOffset?: Vector3
destOffset?: Vector3
timeScale?: number
roughness?: number
straightness?: number
up0?: Vector3
up1?: Vector3
radius0?: number
radius1?: number
radius0Factor?: number
radius1Factor?: number
minRadius?: number
isEternal?: boolean
birthTime?: number
deathTime?: number
propagationTimeFactor?: number
vanishingTimeFactor?: number
subrayPeriod?: number
subrayDutyCycle?: number
maxIterations?: number
isStatic?: boolean
ramification?: number
maxSubrayRecursion?: number
recursionProbability?: number
generateUVs?: boolean
randomGenerator?: RandomGenerator
noiseSeed?: number
onDecideSubrayCreation?: (segment: LightningSegment, lightningStrike: LightningStrike) => void
onSubrayCreation?: (
segment: LightningSegment,
parentSubray: LightningSubray,
childSubray: LightningSubray,
lightningStrike: LightningStrike,
) => void
}
export class LightningStrike extends BufferGeometry {
constructor(rayParameters?: RayParameters)
copyParameters(dest?: RayParameters, source?: RayParameters): RayParameters
// Ray states
static readonly RAY_INITIALIZED: number
static readonly RAY_UNBORN: number
static readonly RAY_PROPAGATING: number
static readonly RAY_STEADY: number
static readonly RAY_VANISHING: number
static readonly RAY_EXTINGUISHED: number
state: number
update(time: number): void
copy(source: LightningStrike): this
clone(): this
}
+563
View File
@@ -0,0 +1,563 @@
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
import { BufferGeometry, Vector3, Uint32BufferAttribute, Float32BufferAttribute, DynamicDrawUsage, MathUtils } from "three";
import { SimplexNoise } from "../math/SimplexNoise.js";
const LightningStrike = /* @__PURE__ */ (() => {
const _LightningStrike = class extends BufferGeometry {
constructor(rayParameters = {}) {
super();
this.isLightningStrike = true;
this.type = "LightningStrike";
this.init(_LightningStrike.copyParameters(rayParameters, rayParameters));
this.createMesh();
}
static createRandomGenerator() {
const numSeeds = 2053;
const seeds = [];
for (let i = 0; i < numSeeds; i++) {
seeds.push(Math.random());
}
const generator = {
currentSeed: 0,
random: function() {
const value = seeds[generator.currentSeed];
generator.currentSeed = (generator.currentSeed + 1) % numSeeds;
return value;
},
getSeed: function() {
return generator.currentSeed / numSeeds;
},
setSeed: function(seed) {
generator.currentSeed = Math.floor(seed * numSeeds) % numSeeds;
}
};
return generator;
}
static copyParameters(dest = {}, source = {}) {
const vecCopy = function(v) {
if (source === dest) {
return v;
} else {
return v.clone();
}
};
dest.sourceOffset = source.sourceOffset !== void 0 ? vecCopy(source.sourceOffset) : new Vector3(0, 100, 0), dest.destOffset = source.destOffset !== void 0 ? vecCopy(source.destOffset) : new Vector3(0, 0, 0), dest.timeScale = source.timeScale !== void 0 ? source.timeScale : 1, dest.roughness = source.roughness !== void 0 ? source.roughness : 0.9, dest.straightness = source.straightness !== void 0 ? source.straightness : 0.7, dest.up0 = source.up0 !== void 0 ? vecCopy(source.up0) : new Vector3(0, 0, 1);
dest.up1 = source.up1 !== void 0 ? vecCopy(source.up1) : new Vector3(0, 0, 1), dest.radius0 = source.radius0 !== void 0 ? source.radius0 : 1, dest.radius1 = source.radius1 !== void 0 ? source.radius1 : 1, dest.radius0Factor = source.radius0Factor !== void 0 ? source.radius0Factor : 0.5, dest.radius1Factor = source.radius1Factor !== void 0 ? source.radius1Factor : 0.2, dest.minRadius = source.minRadius !== void 0 ? source.minRadius : 0.2, // These parameters should not be changed after lightning creation. They can be changed but the ray will change its form abruptly:
dest.isEternal = source.isEternal !== void 0 ? source.isEternal : source.birthTime === void 0 || source.deathTime === void 0, dest.birthTime = source.birthTime, dest.deathTime = source.deathTime, dest.propagationTimeFactor = source.propagationTimeFactor !== void 0 ? source.propagationTimeFactor : 0.1, dest.vanishingTimeFactor = source.vanishingTimeFactor !== void 0 ? source.vanishingTimeFactor : 0.9, dest.subrayPeriod = source.subrayPeriod !== void 0 ? source.subrayPeriod : 4, dest.subrayDutyCycle = source.subrayDutyCycle !== void 0 ? source.subrayDutyCycle : 0.6;
dest.maxIterations = source.maxIterations !== void 0 ? source.maxIterations : 9;
dest.isStatic = source.isStatic !== void 0 ? source.isStatic : false;
dest.ramification = source.ramification !== void 0 ? source.ramification : 5;
dest.maxSubrayRecursion = source.maxSubrayRecursion !== void 0 ? source.maxSubrayRecursion : 3;
dest.recursionProbability = source.recursionProbability !== void 0 ? source.recursionProbability : 0.6;
dest.generateUVs = source.generateUVs !== void 0 ? source.generateUVs : false;
dest.randomGenerator = source.randomGenerator, dest.noiseSeed = source.noiseSeed, dest.onDecideSubrayCreation = source.onDecideSubrayCreation, dest.onSubrayCreation = source.onSubrayCreation;
return dest;
}
update(time) {
if (this.isStatic)
return;
if (this.rayParameters.isEternal || this.rayParameters.birthTime <= time && time <= this.rayParameters.deathTime) {
this.updateMesh(time);
if (time < this.subrays[0].endPropagationTime) {
this.state = _LightningStrike.RAY_PROPAGATING;
} else if (time > this.subrays[0].beginVanishingTime) {
this.state = _LightningStrike.RAY_VANISHING;
} else {
this.state = _LightningStrike.RAY_STEADY;
}
this.visible = true;
} else {
this.visible = false;
if (time < this.rayParameters.birthTime) {
this.state = _LightningStrike.RAY_UNBORN;
} else {
this.state = _LightningStrike.RAY_EXTINGUISHED;
}
}
}
init(rayParameters) {
this.rayParameters = rayParameters;
this.maxIterations = rayParameters.maxIterations !== void 0 ? Math.floor(rayParameters.maxIterations) : 9;
rayParameters.maxIterations = this.maxIterations;
this.isStatic = rayParameters.isStatic !== void 0 ? rayParameters.isStatic : false;
rayParameters.isStatic = this.isStatic;
this.ramification = rayParameters.ramification !== void 0 ? Math.floor(rayParameters.ramification) : 5;
rayParameters.ramification = this.ramification;
this.maxSubrayRecursion = rayParameters.maxSubrayRecursion !== void 0 ? Math.floor(rayParameters.maxSubrayRecursion) : 3;
rayParameters.maxSubrayRecursion = this.maxSubrayRecursion;
this.recursionProbability = rayParameters.recursionProbability !== void 0 ? rayParameters.recursionProbability : 0.6;
rayParameters.recursionProbability = this.recursionProbability;
this.generateUVs = rayParameters.generateUVs !== void 0 ? rayParameters.generateUVs : false;
rayParameters.generateUVs = this.generateUVs;
if (rayParameters.randomGenerator !== void 0) {
this.randomGenerator = rayParameters.randomGenerator;
this.seedGenerator = rayParameters.randomGenerator;
if (rayParameters.noiseSeed !== void 0) {
this.seedGenerator.setSeed(rayParameters.noiseSeed);
}
} else {
this.randomGenerator = _LightningStrike.createRandomGenerator();
this.seedGenerator = Math;
}
if (rayParameters.onDecideSubrayCreation !== void 0) {
this.onDecideSubrayCreation = rayParameters.onDecideSubrayCreation;
} else {
this.createDefaultSubrayCreationCallbacks();
if (rayParameters.onSubrayCreation !== void 0) {
this.onSubrayCreation = rayParameters.onSubrayCreation;
}
}
this.state = _LightningStrike.RAY_INITIALIZED;
this.maxSubrays = Math.ceil(1 + Math.pow(this.ramification, Math.max(0, this.maxSubrayRecursion - 1)));
rayParameters.maxSubrays = this.maxSubrays;
this.maxRaySegments = 2 * (1 << this.maxIterations);
this.subrays = [];
for (let i = 0; i < this.maxSubrays; i++) {
this.subrays.push(this.createSubray());
}
this.raySegments = [];
for (let i = 0; i < this.maxRaySegments; i++) {
this.raySegments.push(this.createSegment());
}
this.time = 0;
this.timeFraction = 0;
this.currentSegmentCallback = null;
this.currentCreateTriangleVertices = this.generateUVs ? this.createTriangleVerticesWithUVs : this.createTriangleVerticesWithoutUVs;
this.numSubrays = 0;
this.currentSubray = null;
this.currentSegmentIndex = 0;
this.isInitialSegment = false;
this.subrayProbability = 0;
this.currentVertex = 0;
this.currentIndex = 0;
this.currentCoordinate = 0;
this.currentUVCoordinate = 0;
this.vertices = null;
this.uvs = null;
this.indices = null;
this.positionAttribute = null;
this.uvsAttribute = null;
this.simplexX = new SimplexNoise(this.seedGenerator);
this.simplexY = new SimplexNoise(this.seedGenerator);
this.simplexZ = new SimplexNoise(this.seedGenerator);
this.forwards = new Vector3();
this.forwardsFill = new Vector3();
this.side = new Vector3();
this.down = new Vector3();
this.middlePos = new Vector3();
this.middleLinPos = new Vector3();
this.newPos = new Vector3();
this.vPos = new Vector3();
this.cross1 = new Vector3();
}
createMesh() {
const maxDrawableSegmentsPerSubRay = 1 << this.maxIterations;
const maxVerts = 3 * (maxDrawableSegmentsPerSubRay + 1) * this.maxSubrays;
const maxIndices = 18 * maxDrawableSegmentsPerSubRay * this.maxSubrays;
this.vertices = new Float32Array(maxVerts * 3);
this.indices = new Uint32Array(maxIndices);
if (this.generateUVs) {
this.uvs = new Float32Array(maxVerts * 2);
}
this.fillMesh(0);
this.setIndex(new Uint32BufferAttribute(this.indices, 1));
this.positionAttribute = new Float32BufferAttribute(this.vertices, 3);
this.setAttribute("position", this.positionAttribute);
if (this.generateUVs) {
this.uvsAttribute = new Float32BufferAttribute(new Float32Array(this.uvs), 2);
this.setAttribute("uv", this.uvsAttribute);
}
if (!this.isStatic) {
this.index.usage = DynamicDrawUsage;
this.positionAttribute.usage = DynamicDrawUsage;
if (this.generateUVs) {
this.uvsAttribute.usage = DynamicDrawUsage;
}
}
this.vertices = this.positionAttribute.array;
this.indices = this.index.array;
if (this.generateUVs) {
this.uvs = this.uvsAttribute.array;
}
}
updateMesh(time) {
this.fillMesh(time);
this.drawRange.count = this.currentIndex;
this.index.needsUpdate = true;
this.positionAttribute.needsUpdate = true;
if (this.generateUVs) {
this.uvsAttribute.needsUpdate = true;
}
}
fillMesh(time) {
const scope = this;
this.currentVertex = 0;
this.currentIndex = 0;
this.currentCoordinate = 0;
this.currentUVCoordinate = 0;
this.fractalRay(time, function fillVertices(segment) {
const subray = scope.currentSubray;
if (time < subray.birthTime) {
return;
} else if (this.rayParameters.isEternal && scope.currentSubray.recursion == 0) {
scope.createPrism(segment);
scope.onDecideSubrayCreation(segment, scope);
} else if (time < subray.endPropagationTime) {
if (scope.timeFraction >= segment.fraction0 * subray.propagationTimeFactor) {
scope.createPrism(segment);
scope.onDecideSubrayCreation(segment, scope);
}
} else if (time < subray.beginVanishingTime) {
scope.createPrism(segment);
scope.onDecideSubrayCreation(segment, scope);
} else {
if (scope.timeFraction <= subray.vanishingTimeFactor + segment.fraction1 * (1 - subray.vanishingTimeFactor)) {
scope.createPrism(segment);
}
scope.onDecideSubrayCreation(segment, scope);
}
});
}
addNewSubray() {
return this.subrays[this.numSubrays++];
}
initSubray(subray, rayParameters) {
subray.pos0.copy(rayParameters.sourceOffset);
subray.pos1.copy(rayParameters.destOffset);
subray.up0.copy(rayParameters.up0);
subray.up1.copy(rayParameters.up1);
subray.radius0 = rayParameters.radius0;
subray.radius1 = rayParameters.radius1;
subray.birthTime = rayParameters.birthTime;
subray.deathTime = rayParameters.deathTime;
subray.timeScale = rayParameters.timeScale;
subray.roughness = rayParameters.roughness;
subray.straightness = rayParameters.straightness;
subray.propagationTimeFactor = rayParameters.propagationTimeFactor;
subray.vanishingTimeFactor = rayParameters.vanishingTimeFactor;
subray.maxIterations = this.maxIterations;
subray.seed = rayParameters.noiseSeed !== void 0 ? rayParameters.noiseSeed : 0;
subray.recursion = 0;
}
fractalRay(time, segmentCallback) {
this.time = time;
this.currentSegmentCallback = segmentCallback;
this.numSubrays = 0;
this.initSubray(this.addNewSubray(), this.rayParameters);
for (let subrayIndex = 0; subrayIndex < this.numSubrays; subrayIndex++) {
const subray = this.subrays[subrayIndex];
this.currentSubray = subray;
this.randomGenerator.setSeed(subray.seed);
subray.endPropagationTime = MathUtils.lerp(subray.birthTime, subray.deathTime, subray.propagationTimeFactor);
subray.beginVanishingTime = MathUtils.lerp(subray.deathTime, subray.birthTime, 1 - subray.vanishingTimeFactor);
const random1 = this.randomGenerator.random;
subray.linPos0.set(random1(), random1(), random1()).multiplyScalar(1e3);
subray.linPos1.set(random1(), random1(), random1()).multiplyScalar(1e3);
this.timeFraction = (time - subray.birthTime) / (subray.deathTime - subray.birthTime);
this.currentSegmentIndex = 0;
this.isInitialSegment = true;
const segment = this.getNewSegment();
segment.iteration = 0;
segment.pos0.copy(subray.pos0);
segment.pos1.copy(subray.pos1);
segment.linPos0.copy(subray.linPos0);
segment.linPos1.copy(subray.linPos1);
segment.up0.copy(subray.up0);
segment.up1.copy(subray.up1);
segment.radius0 = subray.radius0;
segment.radius1 = subray.radius1;
segment.fraction0 = 0;
segment.fraction1 = 1;
segment.positionVariationFactor = 1 - subray.straightness;
this.subrayProbability = this.ramification * Math.pow(this.recursionProbability, subray.recursion) / (1 << subray.maxIterations);
this.fractalRayRecursive(segment);
}
this.currentSegmentCallback = null;
this.currentSubray = null;
}
fractalRayRecursive(segment) {
if (segment.iteration >= this.currentSubray.maxIterations) {
this.currentSegmentCallback(segment);
return;
}
this.forwards.subVectors(segment.pos1, segment.pos0);
let lForwards = this.forwards.length();
if (lForwards < 1e-6) {
this.forwards.set(0, 0, 0.01);
lForwards = this.forwards.length();
}
const middleRadius = (segment.radius0 + segment.radius1) * 0.5;
const middleFraction = (segment.fraction0 + segment.fraction1) * 0.5;
const timeDimension = this.time * this.currentSubray.timeScale * Math.pow(2, segment.iteration);
this.middlePos.lerpVectors(segment.pos0, segment.pos1, 0.5);
this.middleLinPos.lerpVectors(segment.linPos0, segment.linPos1, 0.5);
const p = this.middleLinPos;
this.newPos.set(
this.simplexX.noise4d(p.x, p.y, p.z, timeDimension),
this.simplexY.noise4d(p.x, p.y, p.z, timeDimension),
this.simplexZ.noise4d(p.x, p.y, p.z, timeDimension)
);
this.newPos.multiplyScalar(segment.positionVariationFactor * lForwards);
this.newPos.add(this.middlePos);
const newSegment1 = this.getNewSegment();
newSegment1.pos0.copy(segment.pos0);
newSegment1.pos1.copy(this.newPos);
newSegment1.linPos0.copy(segment.linPos0);
newSegment1.linPos1.copy(this.middleLinPos);
newSegment1.up0.copy(segment.up0);
newSegment1.up1.copy(segment.up1);
newSegment1.radius0 = segment.radius0;
newSegment1.radius1 = middleRadius;
newSegment1.fraction0 = segment.fraction0;
newSegment1.fraction1 = middleFraction;
newSegment1.positionVariationFactor = segment.positionVariationFactor * this.currentSubray.roughness;
newSegment1.iteration = segment.iteration + 1;
const newSegment2 = this.getNewSegment();
newSegment2.pos0.copy(this.newPos);
newSegment2.pos1.copy(segment.pos1);
newSegment2.linPos0.copy(this.middleLinPos);
newSegment2.linPos1.copy(segment.linPos1);
this.cross1.crossVectors(segment.up0, this.forwards.normalize());
newSegment2.up0.crossVectors(this.forwards, this.cross1).normalize();
newSegment2.up1.copy(segment.up1);
newSegment2.radius0 = middleRadius;
newSegment2.radius1 = segment.radius1;
newSegment2.fraction0 = middleFraction;
newSegment2.fraction1 = segment.fraction1;
newSegment2.positionVariationFactor = segment.positionVariationFactor * this.currentSubray.roughness;
newSegment2.iteration = segment.iteration + 1;
this.fractalRayRecursive(newSegment1);
this.fractalRayRecursive(newSegment2);
}
createPrism(segment) {
this.forwardsFill.subVectors(segment.pos1, segment.pos0).normalize();
if (this.isInitialSegment) {
this.currentCreateTriangleVertices(segment.pos0, segment.up0, this.forwardsFill, segment.radius0, 0);
this.isInitialSegment = false;
}
this.currentCreateTriangleVertices(
segment.pos1,
segment.up0,
this.forwardsFill,
segment.radius1,
segment.fraction1
);
this.createPrismFaces();
}
createTriangleVerticesWithoutUVs(pos, up, forwards, radius) {
this.side.crossVectors(up, forwards).multiplyScalar(radius * _LightningStrike.COS30DEG);
this.down.copy(up).multiplyScalar(-radius * _LightningStrike.SIN30DEG);
const p = this.vPos;
const v = this.vertices;
p.copy(pos).sub(this.side).add(this.down);
v[this.currentCoordinate++] = p.x;
v[this.currentCoordinate++] = p.y;
v[this.currentCoordinate++] = p.z;
p.copy(pos).add(this.side).add(this.down);
v[this.currentCoordinate++] = p.x;
v[this.currentCoordinate++] = p.y;
v[this.currentCoordinate++] = p.z;
p.copy(up).multiplyScalar(radius).add(pos);
v[this.currentCoordinate++] = p.x;
v[this.currentCoordinate++] = p.y;
v[this.currentCoordinate++] = p.z;
this.currentVertex += 3;
}
createTriangleVerticesWithUVs(pos, up, forwards, radius, u) {
this.side.crossVectors(up, forwards).multiplyScalar(radius * _LightningStrike.COS30DEG);
this.down.copy(up).multiplyScalar(-radius * _LightningStrike.SIN30DEG);
const p = this.vPos;
const v = this.vertices;
const uv = this.uvs;
p.copy(pos).sub(this.side).add(this.down);
v[this.currentCoordinate++] = p.x;
v[this.currentCoordinate++] = p.y;
v[this.currentCoordinate++] = p.z;
uv[this.currentUVCoordinate++] = u;
uv[this.currentUVCoordinate++] = 0;
p.copy(pos).add(this.side).add(this.down);
v[this.currentCoordinate++] = p.x;
v[this.currentCoordinate++] = p.y;
v[this.currentCoordinate++] = p.z;
uv[this.currentUVCoordinate++] = u;
uv[this.currentUVCoordinate++] = 0.5;
p.copy(up).multiplyScalar(radius).add(pos);
v[this.currentCoordinate++] = p.x;
v[this.currentCoordinate++] = p.y;
v[this.currentCoordinate++] = p.z;
uv[this.currentUVCoordinate++] = u;
uv[this.currentUVCoordinate++] = 1;
this.currentVertex += 3;
}
createPrismFaces(vertex) {
const indices = this.indices;
vertex = this.currentVertex - 6;
indices[this.currentIndex++] = vertex + 1;
indices[this.currentIndex++] = vertex + 2;
indices[this.currentIndex++] = vertex + 5;
indices[this.currentIndex++] = vertex + 1;
indices[this.currentIndex++] = vertex + 5;
indices[this.currentIndex++] = vertex + 4;
indices[this.currentIndex++] = vertex + 0;
indices[this.currentIndex++] = vertex + 1;
indices[this.currentIndex++] = vertex + 4;
indices[this.currentIndex++] = vertex + 0;
indices[this.currentIndex++] = vertex + 4;
indices[this.currentIndex++] = vertex + 3;
indices[this.currentIndex++] = vertex + 2;
indices[this.currentIndex++] = vertex + 0;
indices[this.currentIndex++] = vertex + 3;
indices[this.currentIndex++] = vertex + 2;
indices[this.currentIndex++] = vertex + 3;
indices[this.currentIndex++] = vertex + 5;
}
createDefaultSubrayCreationCallbacks() {
const random1 = this.randomGenerator.random;
this.onDecideSubrayCreation = function(segment, lightningStrike) {
const subray = lightningStrike.currentSubray;
const period = lightningStrike.rayParameters.subrayPeriod;
const dutyCycle = lightningStrike.rayParameters.subrayDutyCycle;
const phase0 = lightningStrike.rayParameters.isEternal && subray.recursion == 0 ? -random1() * period : MathUtils.lerp(subray.birthTime, subray.endPropagationTime, segment.fraction0) - random1() * period;
const phase = lightningStrike.time - phase0;
const currentCycle = Math.floor(phase / period);
const childSubraySeed = random1() * (currentCycle + 1);
const isActive = phase % period <= dutyCycle * period;
let probability = 0;
if (isActive) {
probability = lightningStrike.subrayProbability;
}
if (subray.recursion < lightningStrike.maxSubrayRecursion && lightningStrike.numSubrays < lightningStrike.maxSubrays && random1() < probability) {
const childSubray = lightningStrike.addNewSubray();
const parentSeed = lightningStrike.randomGenerator.getSeed();
childSubray.seed = childSubraySeed;
lightningStrike.randomGenerator.setSeed(childSubraySeed);
childSubray.recursion = subray.recursion + 1;
childSubray.maxIterations = Math.max(1, subray.maxIterations - 1);
childSubray.linPos0.set(random1(), random1(), random1()).multiplyScalar(1e3);
childSubray.linPos1.set(random1(), random1(), random1()).multiplyScalar(1e3);
childSubray.up0.copy(subray.up0);
childSubray.up1.copy(subray.up1);
childSubray.radius0 = segment.radius0 * lightningStrike.rayParameters.radius0Factor;
childSubray.radius1 = Math.min(
lightningStrike.rayParameters.minRadius,
segment.radius1 * lightningStrike.rayParameters.radius1Factor
);
childSubray.birthTime = phase0 + currentCycle * period;
childSubray.deathTime = childSubray.birthTime + period * dutyCycle;
if (!lightningStrike.rayParameters.isEternal && subray.recursion == 0) {
childSubray.birthTime = Math.max(childSubray.birthTime, subray.birthTime);
childSubray.deathTime = Math.min(childSubray.deathTime, subray.deathTime);
}
childSubray.timeScale = subray.timeScale * 2;
childSubray.roughness = subray.roughness;
childSubray.straightness = subray.straightness;
childSubray.propagationTimeFactor = subray.propagationTimeFactor;
childSubray.vanishingTimeFactor = subray.vanishingTimeFactor;
lightningStrike.onSubrayCreation(segment, subray, childSubray, lightningStrike);
lightningStrike.randomGenerator.setSeed(parentSeed);
}
};
const vec1Pos = new Vector3();
const vec2Forward = new Vector3();
const vec3Side = new Vector3();
const vec4Up = new Vector3();
this.onSubrayCreation = function(segment, parentSubray, childSubray, lightningStrike) {
lightningStrike.subrayCylinderPosition(segment, parentSubray, childSubray, 0.5, 0.6, 0.2);
};
this.subrayConePosition = function(segment, parentSubray, childSubray, heightFactor, sideWidthFactor, minSideWidthFactor) {
childSubray.pos0.copy(segment.pos0);
vec1Pos.subVectors(parentSubray.pos1, parentSubray.pos0);
vec2Forward.copy(vec1Pos).normalize();
vec1Pos.multiplyScalar(segment.fraction0 + (1 - segment.fraction0) * (random1() * heightFactor));
const length = vec1Pos.length();
vec3Side.crossVectors(parentSubray.up0, vec2Forward);
const angle = 2 * Math.PI * random1();
vec3Side.multiplyScalar(Math.cos(angle));
vec4Up.copy(parentSubray.up0).multiplyScalar(Math.sin(angle));
childSubray.pos1.copy(vec3Side).add(vec4Up).multiplyScalar(length * sideWidthFactor * (minSideWidthFactor + random1() * (1 - minSideWidthFactor))).add(vec1Pos).add(parentSubray.pos0);
};
this.subrayCylinderPosition = function(segment, parentSubray, childSubray, heightFactor, sideWidthFactor, minSideWidthFactor) {
childSubray.pos0.copy(segment.pos0);
vec1Pos.subVectors(parentSubray.pos1, parentSubray.pos0);
vec2Forward.copy(vec1Pos).normalize();
vec1Pos.multiplyScalar(segment.fraction0 + (1 - segment.fraction0) * ((2 * random1() - 1) * heightFactor));
const length = vec1Pos.length();
vec3Side.crossVectors(parentSubray.up0, vec2Forward);
const angle = 2 * Math.PI * random1();
vec3Side.multiplyScalar(Math.cos(angle));
vec4Up.copy(parentSubray.up0).multiplyScalar(Math.sin(angle));
childSubray.pos1.copy(vec3Side).add(vec4Up).multiplyScalar(length * sideWidthFactor * (minSideWidthFactor + random1() * (1 - minSideWidthFactor))).add(vec1Pos).add(parentSubray.pos0);
};
}
createSubray() {
return {
seed: 0,
maxIterations: 0,
recursion: 0,
pos0: new Vector3(),
pos1: new Vector3(),
linPos0: new Vector3(),
linPos1: new Vector3(),
up0: new Vector3(),
up1: new Vector3(),
radius0: 0,
radius1: 0,
birthTime: 0,
deathTime: 0,
timeScale: 0,
roughness: 0,
straightness: 0,
propagationTimeFactor: 0,
vanishingTimeFactor: 0,
endPropagationTime: 0,
beginVanishingTime: 0
};
}
createSegment() {
return {
iteration: 0,
pos0: new Vector3(),
pos1: new Vector3(),
linPos0: new Vector3(),
linPos1: new Vector3(),
up0: new Vector3(),
up1: new Vector3(),
radius0: 0,
radius1: 0,
fraction0: 0,
fraction1: 0,
positionVariationFactor: 0
};
}
getNewSegment() {
return this.raySegments[this.currentSegmentIndex++];
}
copy(source) {
super.copy(source);
this.init(_LightningStrike.copyParameters({}, source.rayParameters));
return this;
}
clone() {
return new this.constructor(_LightningStrike.copyParameters({}, this.rayParameters));
}
};
let LightningStrike2 = _LightningStrike;
// Ray states
__publicField(LightningStrike2, "RAY_INITIALIZED", 0);
__publicField(LightningStrike2, "RAY_UNBORN", 1);
__publicField(LightningStrike2, "RAY_PROPAGATING", 2);
__publicField(LightningStrike2, "RAY_STEADY", 3);
__publicField(LightningStrike2, "RAY_VANISHING", 4);
__publicField(LightningStrike2, "RAY_EXTINGUISHED", 5);
__publicField(LightningStrike2, "COS30DEG", Math.cos(30 * Math.PI / 180));
__publicField(LightningStrike2, "SIN30DEG", Math.sin(30 * Math.PI / 180));
return LightningStrike2;
})();
export {
LightningStrike
};
//# sourceMappingURL=LightningStrike.js.map
File diff suppressed because one or more lines are too long
+131
View File
@@ -0,0 +1,131 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const ParametricGeometry = require("./ParametricGeometry.cjs");
class TubeGeometry extends ParametricGeometry.ParametricGeometry {
constructor(path, segments = 64, radius = 1, segmentsRadius = 8, closed = false) {
const numpoints = segments + 1;
const frames = path.computeFrenetFrames(segments, closed), tangents = frames.tangents, normals = frames.normals, binormals = frames.binormals;
const position = new THREE.Vector3();
function ParametricTube(u, v, target) {
v *= 2 * Math.PI;
const i = Math.floor(u * (numpoints - 1));
path.getPointAt(u, position);
const normal = normals[i];
const binormal = binormals[i];
const cx = -radius * Math.cos(v);
const cy = radius * Math.sin(v);
position.x += cx * normal.x + cy * binormal.x;
position.y += cx * normal.y + cy * binormal.y;
position.z += cx * normal.z + cy * binormal.z;
target.copy(position);
}
super(ParametricTube, segments, segmentsRadius);
this.tangents = tangents;
this.normals = normals;
this.binormals = binormals;
this.path = path;
this.segments = segments;
this.radius = radius;
this.segmentsRadius = segmentsRadius;
this.closed = closed;
}
}
const ParametricGeometries = {
klein: function(v, u, target) {
u *= Math.PI;
v *= 2 * Math.PI;
u = u * 2;
let x, z;
if (u < Math.PI) {
x = 3 * Math.cos(u) * (1 + Math.sin(u)) + 2 * (1 - Math.cos(u) / 2) * Math.cos(u) * Math.cos(v);
z = -8 * Math.sin(u) - 2 * (1 - Math.cos(u) / 2) * Math.sin(u) * Math.cos(v);
} else {
x = 3 * Math.cos(u) * (1 + Math.sin(u)) + 2 * (1 - Math.cos(u) / 2) * Math.cos(v + Math.PI);
z = -8 * Math.sin(u);
}
const y = -2 * (1 - Math.cos(u) / 2) * Math.sin(v);
target.set(x, y, z);
},
plane: function(width, height) {
return function(u, v, target) {
const x = u * width;
const y = 0;
const z = v * height;
target.set(x, y, z);
};
},
mobius: function(u, t, target) {
u = u - 0.5;
const v = 2 * Math.PI * t;
const a = 2;
const x = Math.cos(v) * (a + u * Math.cos(v / 2));
const y = Math.sin(v) * (a + u * Math.cos(v / 2));
const z = u * Math.sin(v / 2);
target.set(x, y, z);
},
mobius3d: function(u, t, target) {
u *= Math.PI;
t *= 2 * Math.PI;
u = u * 2;
const phi = u / 2;
const major = 2.25, a = 0.125, b = 0.65;
let x = a * Math.cos(t) * Math.cos(phi) - b * Math.sin(t) * Math.sin(phi);
const z = a * Math.cos(t) * Math.sin(phi) + b * Math.sin(t) * Math.cos(phi);
const y = (major + x) * Math.sin(u);
x = (major + x) * Math.cos(u);
target.set(x, y, z);
},
TubeGeometry,
TorusKnotGeometry: class TorusKnotGeometry extends TubeGeometry {
constructor(radius = 200, tube = 40, segmentsT = 64, segmentsR = 8, p = 2, q = 3) {
class TorusKnotCurve extends THREE.Curve {
getPoint(t, optionalTarget = new THREE.Vector3()) {
const point = optionalTarget;
t *= Math.PI * 2;
const r = 0.5;
const x = (1 + r * Math.cos(q * t)) * Math.cos(p * t);
const y = (1 + r * Math.cos(q * t)) * Math.sin(p * t);
const z = r * Math.sin(q * t);
return point.set(x, y, z).multiplyScalar(radius);
}
}
const segments = segmentsT;
const radiusSegments = segmentsR;
const extrudePath = new TorusKnotCurve();
super(extrudePath, segments, tube, radiusSegments, true, false);
this.radius = radius;
this.tube = tube;
this.segmentsT = segmentsT;
this.segmentsR = segmentsR;
this.p = p;
this.q = q;
}
},
SphereGeometry: class SphereGeometry extends ParametricGeometry.ParametricGeometry {
constructor(size, u, v) {
function sphere(u2, v2, target) {
u2 *= Math.PI;
v2 *= 2 * Math.PI;
const x = size * Math.sin(u2) * Math.cos(v2);
const y = size * Math.sin(u2) * Math.sin(v2);
const z = size * Math.cos(u2);
target.set(x, y, z);
}
super(sphere, u, v);
}
},
PlaneGeometry: class PlaneGeometry extends ParametricGeometry.ParametricGeometry {
constructor(width, depth, segmentsWidth, segmentsDepth) {
function plane(u, v, target) {
const x = u * width;
const y = 0;
const z = v * depth;
target.set(x, y, z);
}
super(plane, segmentsWidth, segmentsDepth);
}
}
};
exports.ParametricGeometries = ParametricGeometries;
//# sourceMappingURL=ParametricGeometries.cjs.map
File diff suppressed because one or more lines are too long
+26
View File
@@ -0,0 +1,26 @@
import { Curve, Vector3 } from 'three'
import { ParametricGeometry } from './ParametricGeometry'
export namespace ParametricGeometries {
function klein(v: number, u: number, target: Vector3): Vector3
function plane(width: number, height: number): (u: number, v: number, target: Vector3) => Vector3
function mobius(u: number, t: number, target: Vector3): Vector3
function mobius3d(u: number, t: number, target: Vector3): Vector3
class TubeGeometry extends ParametricGeometry {
constructor(path: Curve<Vector3>, segments?: number, radius?: number, segmentsRadius?: number, closed?: boolean)
}
class TorusKnotGeometry extends TubeGeometry {
constructor(radius?: number, tube?: number, segmentsT?: number, segmentsR?: number, p?: number, q?: number)
}
class SphereGeometry extends ParametricGeometry {
constructor(size: number, u: number, v: number)
}
class PlaneGeometry extends ParametricGeometry {
constructor(width: number, depth: number, segmentsWidth: number, segmentsDepth: number)
}
}
+131
View File
@@ -0,0 +1,131 @@
import { Vector3, Curve } from "three";
import { ParametricGeometry } from "./ParametricGeometry.js";
class TubeGeometry extends ParametricGeometry {
constructor(path, segments = 64, radius = 1, segmentsRadius = 8, closed = false) {
const numpoints = segments + 1;
const frames = path.computeFrenetFrames(segments, closed), tangents = frames.tangents, normals = frames.normals, binormals = frames.binormals;
const position = new Vector3();
function ParametricTube(u, v, target) {
v *= 2 * Math.PI;
const i = Math.floor(u * (numpoints - 1));
path.getPointAt(u, position);
const normal = normals[i];
const binormal = binormals[i];
const cx = -radius * Math.cos(v);
const cy = radius * Math.sin(v);
position.x += cx * normal.x + cy * binormal.x;
position.y += cx * normal.y + cy * binormal.y;
position.z += cx * normal.z + cy * binormal.z;
target.copy(position);
}
super(ParametricTube, segments, segmentsRadius);
this.tangents = tangents;
this.normals = normals;
this.binormals = binormals;
this.path = path;
this.segments = segments;
this.radius = radius;
this.segmentsRadius = segmentsRadius;
this.closed = closed;
}
}
const ParametricGeometries = {
klein: function(v, u, target) {
u *= Math.PI;
v *= 2 * Math.PI;
u = u * 2;
let x, z;
if (u < Math.PI) {
x = 3 * Math.cos(u) * (1 + Math.sin(u)) + 2 * (1 - Math.cos(u) / 2) * Math.cos(u) * Math.cos(v);
z = -8 * Math.sin(u) - 2 * (1 - Math.cos(u) / 2) * Math.sin(u) * Math.cos(v);
} else {
x = 3 * Math.cos(u) * (1 + Math.sin(u)) + 2 * (1 - Math.cos(u) / 2) * Math.cos(v + Math.PI);
z = -8 * Math.sin(u);
}
const y = -2 * (1 - Math.cos(u) / 2) * Math.sin(v);
target.set(x, y, z);
},
plane: function(width, height) {
return function(u, v, target) {
const x = u * width;
const y = 0;
const z = v * height;
target.set(x, y, z);
};
},
mobius: function(u, t, target) {
u = u - 0.5;
const v = 2 * Math.PI * t;
const a = 2;
const x = Math.cos(v) * (a + u * Math.cos(v / 2));
const y = Math.sin(v) * (a + u * Math.cos(v / 2));
const z = u * Math.sin(v / 2);
target.set(x, y, z);
},
mobius3d: function(u, t, target) {
u *= Math.PI;
t *= 2 * Math.PI;
u = u * 2;
const phi = u / 2;
const major = 2.25, a = 0.125, b = 0.65;
let x = a * Math.cos(t) * Math.cos(phi) - b * Math.sin(t) * Math.sin(phi);
const z = a * Math.cos(t) * Math.sin(phi) + b * Math.sin(t) * Math.cos(phi);
const y = (major + x) * Math.sin(u);
x = (major + x) * Math.cos(u);
target.set(x, y, z);
},
TubeGeometry,
TorusKnotGeometry: class TorusKnotGeometry extends TubeGeometry {
constructor(radius = 200, tube = 40, segmentsT = 64, segmentsR = 8, p = 2, q = 3) {
class TorusKnotCurve extends Curve {
getPoint(t, optionalTarget = new Vector3()) {
const point = optionalTarget;
t *= Math.PI * 2;
const r = 0.5;
const x = (1 + r * Math.cos(q * t)) * Math.cos(p * t);
const y = (1 + r * Math.cos(q * t)) * Math.sin(p * t);
const z = r * Math.sin(q * t);
return point.set(x, y, z).multiplyScalar(radius);
}
}
const segments = segmentsT;
const radiusSegments = segmentsR;
const extrudePath = new TorusKnotCurve();
super(extrudePath, segments, tube, radiusSegments, true, false);
this.radius = radius;
this.tube = tube;
this.segmentsT = segmentsT;
this.segmentsR = segmentsR;
this.p = p;
this.q = q;
}
},
SphereGeometry: class SphereGeometry extends ParametricGeometry {
constructor(size, u, v) {
function sphere(u2, v2, target) {
u2 *= Math.PI;
v2 *= 2 * Math.PI;
const x = size * Math.sin(u2) * Math.cos(v2);
const y = size * Math.sin(u2) * Math.sin(v2);
const z = size * Math.cos(u2);
target.set(x, y, z);
}
super(sphere, u, v);
}
},
PlaneGeometry: class PlaneGeometry extends ParametricGeometry {
constructor(width, depth, segmentsWidth, segmentsDepth) {
function plane(u, v, target) {
const x = u * width;
const y = 0;
const z = v * depth;
target.set(x, y, z);
}
super(plane, segmentsWidth, segmentsDepth);
}
}
};
export {
ParametricGeometries
};
//# sourceMappingURL=ParametricGeometries.js.map
File diff suppressed because one or more lines are too long
+64
View File
@@ -0,0 +1,64 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
class ParametricGeometry extends THREE.BufferGeometry {
constructor(func = (u, v, target) => target.set(u, v, Math.cos(u) * Math.sin(v)), slices = 8, stacks = 8) {
super();
this.type = "ParametricGeometry";
this.parameters = {
func,
slices,
stacks
};
const indices = [];
const vertices = [];
const normals = [];
const uvs = [];
const EPS = 1e-5;
const normal = new THREE.Vector3();
const p0 = new THREE.Vector3(), p1 = new THREE.Vector3();
const pu = new THREE.Vector3(), pv = new THREE.Vector3();
const sliceCount = slices + 1;
for (let i = 0; i <= stacks; i++) {
const v = i / stacks;
for (let j = 0; j <= slices; j++) {
const u = j / slices;
func(u, v, p0);
vertices.push(p0.x, p0.y, p0.z);
if (u - EPS >= 0) {
func(u - EPS, v, p1);
pu.subVectors(p0, p1);
} else {
func(u + EPS, v, p1);
pu.subVectors(p1, p0);
}
if (v - EPS >= 0) {
func(u, v - EPS, p1);
pv.subVectors(p0, p1);
} else {
func(u, v + EPS, p1);
pv.subVectors(p1, p0);
}
normal.crossVectors(pu, pv).normalize();
normals.push(normal.x, normal.y, normal.z);
uvs.push(u, v);
}
}
for (let i = 0; i < stacks; i++) {
for (let j = 0; j < slices; j++) {
const a = i * sliceCount + j;
const b = i * sliceCount + j + 1;
const c = (i + 1) * sliceCount + j + 1;
const d = (i + 1) * sliceCount + j;
indices.push(a, b, d);
indices.push(b, c, d);
}
}
this.setIndex(indices);
this.setAttribute("position", new THREE.Float32BufferAttribute(vertices, 3));
this.setAttribute("normal", new THREE.Float32BufferAttribute(normals, 3));
this.setAttribute("uv", new THREE.Float32BufferAttribute(uvs, 2));
}
}
exports.ParametricGeometry = ParametricGeometry;
//# sourceMappingURL=ParametricGeometry.cjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"ParametricGeometry.cjs","sources":["../../src/geometries/ParametricGeometry.js"],"sourcesContent":["import { BufferGeometry, Float32BufferAttribute, Vector3 } from 'three'\n\n/**\n * Parametric Surfaces Geometry\n * based on the brilliant article by @prideout https://prideout.net/blog/old/blog/index.html@p=44.html\n */\nclass ParametricGeometry extends BufferGeometry {\n constructor(func = (u, v, target) => target.set(u, v, Math.cos(u) * Math.sin(v)), slices = 8, stacks = 8) {\n super()\n\n this.type = 'ParametricGeometry'\n\n this.parameters = {\n func: func,\n slices: slices,\n stacks: stacks,\n }\n\n // buffers\n\n const indices = []\n const vertices = []\n const normals = []\n const uvs = []\n\n const EPS = 0.00001\n\n const normal = new Vector3()\n\n const p0 = new Vector3(),\n p1 = new Vector3()\n const pu = new Vector3(),\n pv = new Vector3()\n\n // generate vertices, normals and uvs\n\n const sliceCount = slices + 1\n\n for (let i = 0; i <= stacks; i++) {\n const v = i / stacks\n\n for (let j = 0; j <= slices; j++) {\n const u = j / slices\n\n // vertex\n\n func(u, v, p0)\n vertices.push(p0.x, p0.y, p0.z)\n\n // normal\n\n // approximate tangent vectors via finite differences\n\n if (u - EPS >= 0) {\n func(u - EPS, v, p1)\n pu.subVectors(p0, p1)\n } else {\n func(u + EPS, v, p1)\n pu.subVectors(p1, p0)\n }\n\n if (v - EPS >= 0) {\n func(u, v - EPS, p1)\n pv.subVectors(p0, p1)\n } else {\n func(u, v + EPS, p1)\n pv.subVectors(p1, p0)\n }\n\n // cross product of tangent vectors returns surface normal\n\n normal.crossVectors(pu, pv).normalize()\n normals.push(normal.x, normal.y, normal.z)\n\n // uv\n\n uvs.push(u, v)\n }\n }\n\n // generate indices\n\n for (let i = 0; i < stacks; i++) {\n for (let j = 0; j < slices; j++) {\n const a = i * sliceCount + j\n const b = i * sliceCount + j + 1\n const c = (i + 1) * sliceCount + j + 1\n const d = (i + 1) * sliceCount + j\n\n // faces one and two\n\n indices.push(a, b, d)\n indices.push(b, c, d)\n }\n }\n\n // build geometry\n\n this.setIndex(indices)\n this.setAttribute('position', new Float32BufferAttribute(vertices, 3))\n this.setAttribute('normal', new Float32BufferAttribute(normals, 3))\n this.setAttribute('uv', new Float32BufferAttribute(uvs, 2))\n }\n}\n\nexport { ParametricGeometry }\n"],"names":["BufferGeometry","Vector3","Float32BufferAttribute"],"mappings":";;;AAMA,MAAM,2BAA2BA,MAAAA,eAAe;AAAA,EAC9C,YAAY,OAAO,CAAC,GAAG,GAAG,WAAW,OAAO,IAAI,GAAG,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,GAAG,SAAS,GAAG,SAAS,GAAG;AACxG,UAAO;AAEP,SAAK,OAAO;AAEZ,SAAK,aAAa;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAID,UAAM,UAAU,CAAE;AAClB,UAAM,WAAW,CAAE;AACnB,UAAM,UAAU,CAAE;AAClB,UAAM,MAAM,CAAE;AAEd,UAAM,MAAM;AAEZ,UAAM,SAAS,IAAIC,cAAS;AAE5B,UAAM,KAAK,IAAIA,cAAS,GACtB,KAAK,IAAIA,MAAAA,QAAS;AACpB,UAAM,KAAK,IAAIA,cAAS,GACtB,KAAK,IAAIA,MAAAA,QAAS;AAIpB,UAAM,aAAa,SAAS;AAE5B,aAAS,IAAI,GAAG,KAAK,QAAQ,KAAK;AAChC,YAAM,IAAI,IAAI;AAEd,eAAS,IAAI,GAAG,KAAK,QAAQ,KAAK;AAChC,cAAM,IAAI,IAAI;AAId,aAAK,GAAG,GAAG,EAAE;AACb,iBAAS,KAAK,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAM9B,YAAI,IAAI,OAAO,GAAG;AAChB,eAAK,IAAI,KAAK,GAAG,EAAE;AACnB,aAAG,WAAW,IAAI,EAAE;AAAA,QAC9B,OAAe;AACL,eAAK,IAAI,KAAK,GAAG,EAAE;AACnB,aAAG,WAAW,IAAI,EAAE;AAAA,QACrB;AAED,YAAI,IAAI,OAAO,GAAG;AAChB,eAAK,GAAG,IAAI,KAAK,EAAE;AACnB,aAAG,WAAW,IAAI,EAAE;AAAA,QAC9B,OAAe;AACL,eAAK,GAAG,IAAI,KAAK,EAAE;AACnB,aAAG,WAAW,IAAI,EAAE;AAAA,QACrB;AAID,eAAO,aAAa,IAAI,EAAE,EAAE,UAAW;AACvC,gBAAQ,KAAK,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAIzC,YAAI,KAAK,GAAG,CAAC;AAAA,MACd;AAAA,IACF;AAID,aAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,eAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,cAAM,IAAI,IAAI,aAAa;AAC3B,cAAM,IAAI,IAAI,aAAa,IAAI;AAC/B,cAAM,KAAK,IAAI,KAAK,aAAa,IAAI;AACrC,cAAM,KAAK,IAAI,KAAK,aAAa;AAIjC,gBAAQ,KAAK,GAAG,GAAG,CAAC;AACpB,gBAAQ,KAAK,GAAG,GAAG,CAAC;AAAA,MACrB;AAAA,IACF;AAID,SAAK,SAAS,OAAO;AACrB,SAAK,aAAa,YAAY,IAAIC,MAAAA,uBAAuB,UAAU,CAAC,CAAC;AACrE,SAAK,aAAa,UAAU,IAAIA,MAAAA,uBAAuB,SAAS,CAAC,CAAC;AAClE,SAAK,aAAa,MAAM,IAAIA,MAAAA,uBAAuB,KAAK,CAAC,CAAC;AAAA,EAC3D;AACH;;"}
+18
View File
@@ -0,0 +1,18 @@
import { Vector3, BufferGeometry } from 'three'
export class ParametricGeometry extends BufferGeometry {
constructor(func?: (u: number, v: number, target: Vector3) => void, slices?: number, stacks?: number)
/**
* @default 'ParametricGeometry'
*/
type: string
parameters: {
func: (u: number, v: number, dest: Vector3) => void
slices: number
stacks: number
}
}
export { ParametricGeometry as ParametricBufferGeometry }
+64
View File
@@ -0,0 +1,64 @@
import { BufferGeometry, Vector3, Float32BufferAttribute } from "three";
class ParametricGeometry extends BufferGeometry {
constructor(func = (u, v, target) => target.set(u, v, Math.cos(u) * Math.sin(v)), slices = 8, stacks = 8) {
super();
this.type = "ParametricGeometry";
this.parameters = {
func,
slices,
stacks
};
const indices = [];
const vertices = [];
const normals = [];
const uvs = [];
const EPS = 1e-5;
const normal = new Vector3();
const p0 = new Vector3(), p1 = new Vector3();
const pu = new Vector3(), pv = new Vector3();
const sliceCount = slices + 1;
for (let i = 0; i <= stacks; i++) {
const v = i / stacks;
for (let j = 0; j <= slices; j++) {
const u = j / slices;
func(u, v, p0);
vertices.push(p0.x, p0.y, p0.z);
if (u - EPS >= 0) {
func(u - EPS, v, p1);
pu.subVectors(p0, p1);
} else {
func(u + EPS, v, p1);
pu.subVectors(p1, p0);
}
if (v - EPS >= 0) {
func(u, v - EPS, p1);
pv.subVectors(p0, p1);
} else {
func(u, v + EPS, p1);
pv.subVectors(p1, p0);
}
normal.crossVectors(pu, pv).normalize();
normals.push(normal.x, normal.y, normal.z);
uvs.push(u, v);
}
}
for (let i = 0; i < stacks; i++) {
for (let j = 0; j < slices; j++) {
const a = i * sliceCount + j;
const b = i * sliceCount + j + 1;
const c = (i + 1) * sliceCount + j + 1;
const d = (i + 1) * sliceCount + j;
indices.push(a, b, d);
indices.push(b, c, d);
}
}
this.setIndex(indices);
this.setAttribute("position", new Float32BufferAttribute(vertices, 3));
this.setAttribute("normal", new Float32BufferAttribute(normals, 3));
this.setAttribute("uv", new Float32BufferAttribute(uvs, 2));
}
}
export {
ParametricGeometry
};
//# sourceMappingURL=ParametricGeometry.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"ParametricGeometry.js","sources":["../../src/geometries/ParametricGeometry.js"],"sourcesContent":["import { BufferGeometry, Float32BufferAttribute, Vector3 } from 'three'\n\n/**\n * Parametric Surfaces Geometry\n * based on the brilliant article by @prideout https://prideout.net/blog/old/blog/index.html@p=44.html\n */\nclass ParametricGeometry extends BufferGeometry {\n constructor(func = (u, v, target) => target.set(u, v, Math.cos(u) * Math.sin(v)), slices = 8, stacks = 8) {\n super()\n\n this.type = 'ParametricGeometry'\n\n this.parameters = {\n func: func,\n slices: slices,\n stacks: stacks,\n }\n\n // buffers\n\n const indices = []\n const vertices = []\n const normals = []\n const uvs = []\n\n const EPS = 0.00001\n\n const normal = new Vector3()\n\n const p0 = new Vector3(),\n p1 = new Vector3()\n const pu = new Vector3(),\n pv = new Vector3()\n\n // generate vertices, normals and uvs\n\n const sliceCount = slices + 1\n\n for (let i = 0; i <= stacks; i++) {\n const v = i / stacks\n\n for (let j = 0; j <= slices; j++) {\n const u = j / slices\n\n // vertex\n\n func(u, v, p0)\n vertices.push(p0.x, p0.y, p0.z)\n\n // normal\n\n // approximate tangent vectors via finite differences\n\n if (u - EPS >= 0) {\n func(u - EPS, v, p1)\n pu.subVectors(p0, p1)\n } else {\n func(u + EPS, v, p1)\n pu.subVectors(p1, p0)\n }\n\n if (v - EPS >= 0) {\n func(u, v - EPS, p1)\n pv.subVectors(p0, p1)\n } else {\n func(u, v + EPS, p1)\n pv.subVectors(p1, p0)\n }\n\n // cross product of tangent vectors returns surface normal\n\n normal.crossVectors(pu, pv).normalize()\n normals.push(normal.x, normal.y, normal.z)\n\n // uv\n\n uvs.push(u, v)\n }\n }\n\n // generate indices\n\n for (let i = 0; i < stacks; i++) {\n for (let j = 0; j < slices; j++) {\n const a = i * sliceCount + j\n const b = i * sliceCount + j + 1\n const c = (i + 1) * sliceCount + j + 1\n const d = (i + 1) * sliceCount + j\n\n // faces one and two\n\n indices.push(a, b, d)\n indices.push(b, c, d)\n }\n }\n\n // build geometry\n\n this.setIndex(indices)\n this.setAttribute('position', new Float32BufferAttribute(vertices, 3))\n this.setAttribute('normal', new Float32BufferAttribute(normals, 3))\n this.setAttribute('uv', new Float32BufferAttribute(uvs, 2))\n }\n}\n\nexport { ParametricGeometry }\n"],"names":[],"mappings":";AAMA,MAAM,2BAA2B,eAAe;AAAA,EAC9C,YAAY,OAAO,CAAC,GAAG,GAAG,WAAW,OAAO,IAAI,GAAG,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,GAAG,SAAS,GAAG,SAAS,GAAG;AACxG,UAAO;AAEP,SAAK,OAAO;AAEZ,SAAK,aAAa;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAID,UAAM,UAAU,CAAE;AAClB,UAAM,WAAW,CAAE;AACnB,UAAM,UAAU,CAAE;AAClB,UAAM,MAAM,CAAE;AAEd,UAAM,MAAM;AAEZ,UAAM,SAAS,IAAI,QAAS;AAE5B,UAAM,KAAK,IAAI,QAAS,GACtB,KAAK,IAAI,QAAS;AACpB,UAAM,KAAK,IAAI,QAAS,GACtB,KAAK,IAAI,QAAS;AAIpB,UAAM,aAAa,SAAS;AAE5B,aAAS,IAAI,GAAG,KAAK,QAAQ,KAAK;AAChC,YAAM,IAAI,IAAI;AAEd,eAAS,IAAI,GAAG,KAAK,QAAQ,KAAK;AAChC,cAAM,IAAI,IAAI;AAId,aAAK,GAAG,GAAG,EAAE;AACb,iBAAS,KAAK,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAM9B,YAAI,IAAI,OAAO,GAAG;AAChB,eAAK,IAAI,KAAK,GAAG,EAAE;AACnB,aAAG,WAAW,IAAI,EAAE;AAAA,QAC9B,OAAe;AACL,eAAK,IAAI,KAAK,GAAG,EAAE;AACnB,aAAG,WAAW,IAAI,EAAE;AAAA,QACrB;AAED,YAAI,IAAI,OAAO,GAAG;AAChB,eAAK,GAAG,IAAI,KAAK,EAAE;AACnB,aAAG,WAAW,IAAI,EAAE;AAAA,QAC9B,OAAe;AACL,eAAK,GAAG,IAAI,KAAK,EAAE;AACnB,aAAG,WAAW,IAAI,EAAE;AAAA,QACrB;AAID,eAAO,aAAa,IAAI,EAAE,EAAE,UAAW;AACvC,gBAAQ,KAAK,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAIzC,YAAI,KAAK,GAAG,CAAC;AAAA,MACd;AAAA,IACF;AAID,aAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,eAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,cAAM,IAAI,IAAI,aAAa;AAC3B,cAAM,IAAI,IAAI,aAAa,IAAI;AAC/B,cAAM,KAAK,IAAI,KAAK,aAAa,IAAI;AACrC,cAAM,KAAK,IAAI,KAAK,aAAa;AAIjC,gBAAQ,KAAK,GAAG,GAAG,CAAC;AACpB,gBAAQ,KAAK,GAAG,GAAG,CAAC;AAAA,MACrB;AAAA,IACF;AAID,SAAK,SAAS,OAAO;AACrB,SAAK,aAAa,YAAY,IAAI,uBAAuB,UAAU,CAAC,CAAC;AACrE,SAAK,aAAa,UAAU,IAAI,uBAAuB,SAAS,CAAC,CAAC;AAClE,SAAK,aAAa,MAAM,IAAI,uBAAuB,KAAK,CAAC,CAAC;AAAA,EAC3D;AACH;"}
+92
View File
@@ -0,0 +1,92 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const tempNormal = /* @__PURE__ */ new THREE.Vector3();
function getUv(faceDirVector, normal, uvAxis, projectionAxis, radius, sideLength) {
const totArcLength = 2 * Math.PI * radius / 4;
const centerLength = Math.max(sideLength - 2 * radius, 0);
const halfArc = Math.PI / 4;
tempNormal.copy(normal);
tempNormal[projectionAxis] = 0;
tempNormal.normalize();
const arcUvRatio = 0.5 * totArcLength / (totArcLength + centerLength);
const arcAngleRatio = 1 - tempNormal.angleTo(faceDirVector) / halfArc;
if (Math.sign(tempNormal[uvAxis]) === 1) {
return arcAngleRatio * arcUvRatio;
} else {
const lenUv = centerLength / (totArcLength + centerLength);
return lenUv + arcUvRatio + arcUvRatio * (1 - arcAngleRatio);
}
}
class RoundedBoxGeometry extends THREE.BoxGeometry {
constructor(width = 1, height = 1, depth = 1, segments = 2, radius = 0.1) {
segments = segments * 2 + 1;
radius = Math.min(width / 2, height / 2, depth / 2, radius);
super(1, 1, 1, segments, segments, segments);
if (segments === 1)
return;
const geometry2 = this.toNonIndexed();
this.index = null;
this.attributes.position = geometry2.attributes.position;
this.attributes.normal = geometry2.attributes.normal;
this.attributes.uv = geometry2.attributes.uv;
const position = new THREE.Vector3();
const normal = new THREE.Vector3();
const box = new THREE.Vector3(width, height, depth).divideScalar(2).subScalar(radius);
const positions = this.attributes.position.array;
const normals = this.attributes.normal.array;
const uvs = this.attributes.uv.array;
const faceTris = positions.length / 6;
const faceDirVector = new THREE.Vector3();
const halfSegmentSize = 0.5 / segments;
for (let i = 0, j = 0; i < positions.length; i += 3, j += 2) {
position.fromArray(positions, i);
normal.copy(position);
normal.x -= Math.sign(normal.x) * halfSegmentSize;
normal.y -= Math.sign(normal.y) * halfSegmentSize;
normal.z -= Math.sign(normal.z) * halfSegmentSize;
normal.normalize();
positions[i + 0] = box.x * Math.sign(position.x) + normal.x * radius;
positions[i + 1] = box.y * Math.sign(position.y) + normal.y * radius;
positions[i + 2] = box.z * Math.sign(position.z) + normal.z * radius;
normals[i + 0] = normal.x;
normals[i + 1] = normal.y;
normals[i + 2] = normal.z;
const side = Math.floor(i / faceTris);
switch (side) {
case 0:
faceDirVector.set(1, 0, 0);
uvs[j + 0] = getUv(faceDirVector, normal, "z", "y", radius, depth);
uvs[j + 1] = 1 - getUv(faceDirVector, normal, "y", "z", radius, height);
break;
case 1:
faceDirVector.set(-1, 0, 0);
uvs[j + 0] = 1 - getUv(faceDirVector, normal, "z", "y", radius, depth);
uvs[j + 1] = 1 - getUv(faceDirVector, normal, "y", "z", radius, height);
break;
case 2:
faceDirVector.set(0, 1, 0);
uvs[j + 0] = 1 - getUv(faceDirVector, normal, "x", "z", radius, width);
uvs[j + 1] = getUv(faceDirVector, normal, "z", "x", radius, depth);
break;
case 3:
faceDirVector.set(0, -1, 0);
uvs[j + 0] = 1 - getUv(faceDirVector, normal, "x", "z", radius, width);
uvs[j + 1] = 1 - getUv(faceDirVector, normal, "z", "x", radius, depth);
break;
case 4:
faceDirVector.set(0, 0, 1);
uvs[j + 0] = 1 - getUv(faceDirVector, normal, "x", "y", radius, width);
uvs[j + 1] = 1 - getUv(faceDirVector, normal, "y", "x", radius, height);
break;
case 5:
faceDirVector.set(0, 0, -1);
uvs[j + 0] = getUv(faceDirVector, normal, "x", "y", radius, width);
uvs[j + 1] = 1 - getUv(faceDirVector, normal, "y", "x", radius, height);
break;
}
}
}
}
exports.RoundedBoxGeometry = RoundedBoxGeometry;
//# sourceMappingURL=RoundedBoxGeometry.cjs.map
File diff suppressed because one or more lines are too long
+5
View File
@@ -0,0 +1,5 @@
import { BoxGeometry } from 'three'
export class RoundedBoxGeometry extends BoxGeometry {
constructor(width?: number, height?: number, depth?: number, segments?: number, radius?: number)
}
+92
View File
@@ -0,0 +1,92 @@
import { BoxGeometry, Vector3 } from "three";
const tempNormal = /* @__PURE__ */ new Vector3();
function getUv(faceDirVector, normal, uvAxis, projectionAxis, radius, sideLength) {
const totArcLength = 2 * Math.PI * radius / 4;
const centerLength = Math.max(sideLength - 2 * radius, 0);
const halfArc = Math.PI / 4;
tempNormal.copy(normal);
tempNormal[projectionAxis] = 0;
tempNormal.normalize();
const arcUvRatio = 0.5 * totArcLength / (totArcLength + centerLength);
const arcAngleRatio = 1 - tempNormal.angleTo(faceDirVector) / halfArc;
if (Math.sign(tempNormal[uvAxis]) === 1) {
return arcAngleRatio * arcUvRatio;
} else {
const lenUv = centerLength / (totArcLength + centerLength);
return lenUv + arcUvRatio + arcUvRatio * (1 - arcAngleRatio);
}
}
class RoundedBoxGeometry extends BoxGeometry {
constructor(width = 1, height = 1, depth = 1, segments = 2, radius = 0.1) {
segments = segments * 2 + 1;
radius = Math.min(width / 2, height / 2, depth / 2, radius);
super(1, 1, 1, segments, segments, segments);
if (segments === 1)
return;
const geometry2 = this.toNonIndexed();
this.index = null;
this.attributes.position = geometry2.attributes.position;
this.attributes.normal = geometry2.attributes.normal;
this.attributes.uv = geometry2.attributes.uv;
const position = new Vector3();
const normal = new Vector3();
const box = new Vector3(width, height, depth).divideScalar(2).subScalar(radius);
const positions = this.attributes.position.array;
const normals = this.attributes.normal.array;
const uvs = this.attributes.uv.array;
const faceTris = positions.length / 6;
const faceDirVector = new Vector3();
const halfSegmentSize = 0.5 / segments;
for (let i = 0, j = 0; i < positions.length; i += 3, j += 2) {
position.fromArray(positions, i);
normal.copy(position);
normal.x -= Math.sign(normal.x) * halfSegmentSize;
normal.y -= Math.sign(normal.y) * halfSegmentSize;
normal.z -= Math.sign(normal.z) * halfSegmentSize;
normal.normalize();
positions[i + 0] = box.x * Math.sign(position.x) + normal.x * radius;
positions[i + 1] = box.y * Math.sign(position.y) + normal.y * radius;
positions[i + 2] = box.z * Math.sign(position.z) + normal.z * radius;
normals[i + 0] = normal.x;
normals[i + 1] = normal.y;
normals[i + 2] = normal.z;
const side = Math.floor(i / faceTris);
switch (side) {
case 0:
faceDirVector.set(1, 0, 0);
uvs[j + 0] = getUv(faceDirVector, normal, "z", "y", radius, depth);
uvs[j + 1] = 1 - getUv(faceDirVector, normal, "y", "z", radius, height);
break;
case 1:
faceDirVector.set(-1, 0, 0);
uvs[j + 0] = 1 - getUv(faceDirVector, normal, "z", "y", radius, depth);
uvs[j + 1] = 1 - getUv(faceDirVector, normal, "y", "z", radius, height);
break;
case 2:
faceDirVector.set(0, 1, 0);
uvs[j + 0] = 1 - getUv(faceDirVector, normal, "x", "z", radius, width);
uvs[j + 1] = getUv(faceDirVector, normal, "z", "x", radius, depth);
break;
case 3:
faceDirVector.set(0, -1, 0);
uvs[j + 0] = 1 - getUv(faceDirVector, normal, "x", "z", radius, width);
uvs[j + 1] = 1 - getUv(faceDirVector, normal, "z", "x", radius, depth);
break;
case 4:
faceDirVector.set(0, 0, 1);
uvs[j + 0] = 1 - getUv(faceDirVector, normal, "x", "y", radius, width);
uvs[j + 1] = 1 - getUv(faceDirVector, normal, "y", "x", radius, height);
break;
case 5:
faceDirVector.set(0, 0, -1);
uvs[j + 0] = getUv(faceDirVector, normal, "x", "y", radius, width);
uvs[j + 1] = 1 - getUv(faceDirVector, normal, "y", "x", radius, height);
break;
}
}
}
}
export {
RoundedBoxGeometry
};
//# sourceMappingURL=RoundedBoxGeometry.js.map
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+13
View File
@@ -0,0 +1,13 @@
import { BufferGeometry } from 'three'
export class TeapotGeometry extends BufferGeometry {
constructor(
size?: number,
segments?: number,
bottom?: boolean,
lid?: boolean,
body?: boolean,
fitLid?: boolean,
blinn?: number,
)
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+28
View File
@@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
class TextGeometry extends THREE.ExtrudeGeometry {
constructor(text, parameters = {}) {
const {
bevelEnabled = false,
bevelSize = 8,
bevelThickness = 10,
font,
height = 50,
size = 100,
lineHeight = 1,
letterSpacing = 0,
...rest
} = parameters;
if (font === void 0) {
super();
} else {
const shapes = font.generateShapes(text, size, { lineHeight, letterSpacing });
super(shapes, { ...rest, bevelEnabled, bevelSize, bevelThickness, depth: height });
}
this.type = "TextGeometry";
}
}
exports.TextBufferGeometry = TextGeometry;
exports.TextGeometry = TextGeometry;
//# sourceMappingURL=TextGeometry.cjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"TextGeometry.cjs","sources":["../../src/geometries/TextGeometry.ts"],"sourcesContent":["import { ExtrudeGeometry } from 'three'\n\nimport type { Font } from '../loaders/FontLoader'\n\nexport type TextGeometryParameters = {\n bevelEnabled?: boolean\n bevelOffset?: number\n bevelSize?: number\n bevelThickness?: number\n curveSegments?: number\n font: Font\n height?: number\n size?: number\n lineHeight?: number\n letterSpacing?: number\n}\n\nexport class TextGeometry extends ExtrudeGeometry {\n constructor(text: string, parameters: TextGeometryParameters = {} as TextGeometryParameters) {\n const {\n bevelEnabled = false,\n bevelSize = 8,\n bevelThickness = 10,\n font,\n height = 50,\n size = 100,\n lineHeight = 1,\n letterSpacing = 0,\n ...rest\n } = parameters\n\n if (font === undefined) {\n // @ts-ignore\n super() // generate default extrude geometry\n } else {\n const shapes = font.generateShapes(text, size, { lineHeight, letterSpacing })\n super(shapes, { ...rest, bevelEnabled, bevelSize, bevelThickness, depth: height })\n }\n // @ts-ignore\n this.type = 'TextGeometry'\n }\n}\n\nexport { TextGeometry as TextBufferGeometry }\n"],"names":["ExtrudeGeometry"],"mappings":";;;AAiBO,MAAM,qBAAqBA,MAAAA,gBAAgB;AAAA,EAChD,YAAY,MAAc,aAAqC,IAA8B;AACrF,UAAA;AAAA,MACJ,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,iBAAiB;AAAA,MACjB;AAAA,MACA,SAAS;AAAA,MACT,OAAO;AAAA,MACP,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,GAAG;AAAA,IACD,IAAA;AAEJ,QAAI,SAAS,QAAW;AAEhB;IAAA,OACD;AACC,YAAA,SAAS,KAAK,eAAe,MAAM,MAAM,EAAE,YAAY,eAAe;AACtE,YAAA,QAAQ,EAAE,GAAG,MAAM,cAAc,WAAW,gBAAgB,OAAO,OAAA,CAAQ;AAAA,IACnF;AAEA,SAAK,OAAO;AAAA,EACd;AACF;;;"}
+18
View File
@@ -0,0 +1,18 @@
import { ExtrudeGeometry } from 'three';
import type { Font } from '../loaders/FontLoader';
export type TextGeometryParameters = {
bevelEnabled?: boolean;
bevelOffset?: number;
bevelSize?: number;
bevelThickness?: number;
curveSegments?: number;
font: Font;
height?: number;
size?: number;
lineHeight?: number;
letterSpacing?: number;
};
export declare class TextGeometry extends ExtrudeGeometry {
constructor(text: string, parameters?: TextGeometryParameters);
}
export { TextGeometry as TextBufferGeometry };
+28
View File
@@ -0,0 +1,28 @@
import { ExtrudeGeometry } from "three";
class TextGeometry extends ExtrudeGeometry {
constructor(text, parameters = {}) {
const {
bevelEnabled = false,
bevelSize = 8,
bevelThickness = 10,
font,
height = 50,
size = 100,
lineHeight = 1,
letterSpacing = 0,
...rest
} = parameters;
if (font === void 0) {
super();
} else {
const shapes = font.generateShapes(text, size, { lineHeight, letterSpacing });
super(shapes, { ...rest, bevelEnabled, bevelSize, bevelThickness, depth: height });
}
this.type = "TextGeometry";
}
}
export {
TextGeometry as TextBufferGeometry,
TextGeometry
};
//# sourceMappingURL=TextGeometry.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"TextGeometry.js","sources":["../../src/geometries/TextGeometry.ts"],"sourcesContent":["import { ExtrudeGeometry } from 'three'\n\nimport type { Font } from '../loaders/FontLoader'\n\nexport type TextGeometryParameters = {\n bevelEnabled?: boolean\n bevelOffset?: number\n bevelSize?: number\n bevelThickness?: number\n curveSegments?: number\n font: Font\n height?: number\n size?: number\n lineHeight?: number\n letterSpacing?: number\n}\n\nexport class TextGeometry extends ExtrudeGeometry {\n constructor(text: string, parameters: TextGeometryParameters = {} as TextGeometryParameters) {\n const {\n bevelEnabled = false,\n bevelSize = 8,\n bevelThickness = 10,\n font,\n height = 50,\n size = 100,\n lineHeight = 1,\n letterSpacing = 0,\n ...rest\n } = parameters\n\n if (font === undefined) {\n // @ts-ignore\n super() // generate default extrude geometry\n } else {\n const shapes = font.generateShapes(text, size, { lineHeight, letterSpacing })\n super(shapes, { ...rest, bevelEnabled, bevelSize, bevelThickness, depth: height })\n }\n // @ts-ignore\n this.type = 'TextGeometry'\n }\n}\n\nexport { TextGeometry as TextBufferGeometry }\n"],"names":[],"mappings":";AAiBO,MAAM,qBAAqB,gBAAgB;AAAA,EAChD,YAAY,MAAc,aAAqC,IAA8B;AACrF,UAAA;AAAA,MACJ,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,iBAAiB;AAAA,MACjB;AAAA,MACA,SAAS;AAAA,MACT,OAAO;AAAA,MACP,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,GAAG;AAAA,IACD,IAAA;AAEJ,QAAI,SAAS,QAAW;AAEhB;IAAA,OACD;AACC,YAAA,SAAS,KAAK,eAAe,MAAM,MAAM,EAAE,YAAY,eAAe;AACtE,YAAA,QAAQ,EAAE,GAAG,MAAM,cAAc,WAAW,gBAAgB,OAAO,OAAA,CAAQ;AAAA,IACnF;AAEA,SAAK,OAAO;AAAA,EACd;AACF;"}