three-zoo 0.4.3 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BiFovCamera.d.ts +6 -2
- package/dist/Bounds.d.ts +2 -1
- package/dist/SceneTraversal.d.ts +1 -1
- package/dist/index.js +106 -7
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +1 -1
package/dist/BiFovCamera.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Box3, SkinnedMesh } from "three";
|
|
2
|
+
import { PerspectiveCamera, Vector3 } from "three";
|
|
2
3
|
/**
|
|
3
4
|
* A camera that supports independent horizontal and vertical FOV settings.
|
|
4
5
|
* Extends Three.js PerspectiveCamera to allow separate control over horizontal
|
|
@@ -44,6 +45,9 @@ export declare class BiFovCamera extends PerspectiveCamera {
|
|
|
44
45
|
getEffectiveHorizontalFov(): number;
|
|
45
46
|
/** Get actual vertical FOV after aspect ratio adjustments */
|
|
46
47
|
getEffectiveVerticalFov(): number;
|
|
47
|
-
|
|
48
|
+
fitPointsVerticalFov(vertices: Vector3[]): void;
|
|
49
|
+
fitBoxVerticalFov(box: Box3): void;
|
|
50
|
+
fitSkinnedMeshVerticalFov(skinnedMesh: SkinnedMesh): void;
|
|
51
|
+
lookAtCenterOfMass(skinnedMesh: SkinnedMesh): void;
|
|
48
52
|
clone(): this;
|
|
49
53
|
}
|
package/dist/Bounds.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Object3D } from "three";
|
|
1
|
+
import type { Object3D, SkinnedMesh } from "three";
|
|
2
2
|
import { Box3 } from "three";
|
|
3
3
|
/**
|
|
4
4
|
* Box3 with additional convenience methods for width, height, depth, etc.
|
|
@@ -15,6 +15,7 @@ export declare class Bounds extends Box3 {
|
|
|
15
15
|
get depth(): number;
|
|
16
16
|
/** Length of the box's diagonal */
|
|
17
17
|
get diagonal(): number;
|
|
18
|
+
setFromSkinnedMesh(skinnedMesh: SkinnedMesh): Bounds;
|
|
18
19
|
/** Volume (width * height * depth) */
|
|
19
20
|
getVolume(): number;
|
|
20
21
|
/** Surface area (sum of all six faces) */
|
package/dist/SceneTraversal.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export declare class SceneTraversal {
|
|
|
12
12
|
/** Process all materials in meshes */
|
|
13
13
|
static enumerateMaterials(object: Object3D, callback: (material: Material) => void): void;
|
|
14
14
|
/** Find all objects whose names match a pattern */
|
|
15
|
-
static filterObjects(object: Object3D,
|
|
15
|
+
static filterObjects(object: Object3D, filter: RegExp | ((object: Object3D) => boolean)): Object3D[];
|
|
16
16
|
/** Find all materials whose names match a pattern */
|
|
17
17
|
static filterMaterials(object: Object3D, name: RegExp): Material[];
|
|
18
18
|
/** Set shadow properties on meshes */
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PerspectiveCamera, MathUtils,
|
|
1
|
+
import { PerspectiveCamera, MathUtils, Vector3, Box3, Mesh, InstancedMesh, FrontSide, BufferAttribute, AnimationMixer, DirectionalLight, Spherical, RGBAFormat } from 'three';
|
|
2
2
|
|
|
3
3
|
const DEFAULT_HORIZONTAL_FOV = 90;
|
|
4
4
|
const DEFAULT_VERTICAL_FOV = 90;
|
|
@@ -69,7 +69,7 @@ class BiFovCamera extends PerspectiveCamera {
|
|
|
69
69
|
* In portrait: preserves vertical FOV
|
|
70
70
|
*/
|
|
71
71
|
updateProjectionMatrix() {
|
|
72
|
-
if (this.aspect
|
|
72
|
+
if (this.aspect > 1) {
|
|
73
73
|
// Landscape orientation: preserve horizontal FOV
|
|
74
74
|
const radians = MathUtils.degToRad(this.horizontalFovInternal);
|
|
75
75
|
this.fov = MathUtils.radToDeg(Math.atan(Math.tan(radians / 2) / this.aspect) * 2);
|
|
@@ -96,7 +96,84 @@ class BiFovCamera extends PerspectiveCamera {
|
|
|
96
96
|
const horizontalRadians = MathUtils.degToRad(this.horizontalFovInternal);
|
|
97
97
|
return MathUtils.radToDeg(Math.atan(Math.tan(horizontalRadians / 2) / this.aspect) * 2);
|
|
98
98
|
}
|
|
99
|
-
|
|
99
|
+
fitPointsVerticalFov(vertices) {
|
|
100
|
+
const up = new Vector3(0, 1, 0).applyQuaternion(this.quaternion);
|
|
101
|
+
let maxVerticalAngle = 0;
|
|
102
|
+
for (const vertex of vertices) {
|
|
103
|
+
const vertexToCam = this.position.clone().sub(vertex);
|
|
104
|
+
const vertexDirection = vertexToCam.normalize();
|
|
105
|
+
const verticalAngle = Math.asin(Math.abs(vertexDirection.dot(up))) *
|
|
106
|
+
Math.sign(vertexDirection.dot(up));
|
|
107
|
+
if (Math.abs(verticalAngle) > maxVerticalAngle) {
|
|
108
|
+
maxVerticalAngle = Math.abs(verticalAngle);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const requiredFov = MathUtils.radToDeg(2 * maxVerticalAngle);
|
|
112
|
+
this.verticalFovInternal = MathUtils.clamp(requiredFov, MIN_FOV, MAX_FOV);
|
|
113
|
+
this.updateProjectionMatrix();
|
|
114
|
+
}
|
|
115
|
+
fitBoxVerticalFov(box) {
|
|
116
|
+
this.fitPointsVerticalFov([
|
|
117
|
+
new Vector3(box.min.x, box.min.y, box.min.z),
|
|
118
|
+
new Vector3(box.min.x, box.min.y, box.max.z),
|
|
119
|
+
new Vector3(box.min.x, box.max.y, box.min.z),
|
|
120
|
+
new Vector3(box.min.x, box.max.y, box.max.z),
|
|
121
|
+
new Vector3(box.max.x, box.min.y, box.min.z),
|
|
122
|
+
new Vector3(box.max.x, box.min.y, box.max.z),
|
|
123
|
+
new Vector3(box.max.x, box.max.y, box.min.z),
|
|
124
|
+
new Vector3(box.max.x, box.max.y, box.max.z),
|
|
125
|
+
]);
|
|
126
|
+
}
|
|
127
|
+
fitSkinnedMeshVerticalFov(skinnedMesh) {
|
|
128
|
+
skinnedMesh.updateWorldMatrix(true, true);
|
|
129
|
+
skinnedMesh.skeleton.update();
|
|
130
|
+
const bakedGeometry = skinnedMesh.geometry;
|
|
131
|
+
const position = bakedGeometry.attributes["position"];
|
|
132
|
+
const target = new Vector3();
|
|
133
|
+
const points = [];
|
|
134
|
+
for (let i = 0; i < position.count; i++) {
|
|
135
|
+
target.fromBufferAttribute(position, i);
|
|
136
|
+
skinnedMesh.applyBoneTransform(i, target);
|
|
137
|
+
points.push(target.clone());
|
|
138
|
+
}
|
|
139
|
+
this.fitPointsVerticalFov(points);
|
|
140
|
+
}
|
|
141
|
+
lookAtCenterOfMass(skinnedMesh) {
|
|
142
|
+
skinnedMesh.updateWorldMatrix(true, true);
|
|
143
|
+
skinnedMesh.skeleton.update();
|
|
144
|
+
const bakedGeometry = skinnedMesh.geometry;
|
|
145
|
+
const position = bakedGeometry.attributes.position;
|
|
146
|
+
const target = new Vector3();
|
|
147
|
+
const points = [];
|
|
148
|
+
for (let i = 0; i < position.count; i++) {
|
|
149
|
+
target.fromBufferAttribute(position, i);
|
|
150
|
+
skinnedMesh.applyBoneTransform(i, target);
|
|
151
|
+
points.push(target.clone());
|
|
152
|
+
}
|
|
153
|
+
const findMainCluster = (points, iterations = 3) => {
|
|
154
|
+
if (points.length === 0) {
|
|
155
|
+
return new Vector3();
|
|
156
|
+
}
|
|
157
|
+
let center = points[Math.floor(points.length / 2)].clone();
|
|
158
|
+
for (let i = 0; i < iterations; i++) {
|
|
159
|
+
let total = new Vector3();
|
|
160
|
+
let count = 0;
|
|
161
|
+
for (const point of points) {
|
|
162
|
+
if (point.distanceTo(center) < point.distanceTo(total) ||
|
|
163
|
+
count === 0) {
|
|
164
|
+
total.add(point);
|
|
165
|
+
count++;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (count > 0) {
|
|
169
|
+
center = total.divideScalar(count);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return center;
|
|
173
|
+
};
|
|
174
|
+
const centerOfMass = findMainCluster(points);
|
|
175
|
+
this.lookAt(centerOfMass);
|
|
176
|
+
}
|
|
100
177
|
clone() {
|
|
101
178
|
const camera = new BiFovCamera(this.horizontalFovInternal, this.verticalFovInternal, this.aspect, this.near, this.far);
|
|
102
179
|
camera.copy(this, true);
|
|
@@ -132,6 +209,21 @@ class Bounds extends Box3 {
|
|
|
132
209
|
get diagonal() {
|
|
133
210
|
return this.tempVector3A.subVectors(this.max, this.min).length();
|
|
134
211
|
}
|
|
212
|
+
setFromSkinnedMesh(skinnedMesh) {
|
|
213
|
+
skinnedMesh.updateWorldMatrix(true, true);
|
|
214
|
+
skinnedMesh.skeleton.update();
|
|
215
|
+
const geometry = skinnedMesh.geometry;
|
|
216
|
+
const position = geometry.attributes["position"];
|
|
217
|
+
const target = new Vector3();
|
|
218
|
+
const points = [];
|
|
219
|
+
for (let i = 0; i < position.count; i++) {
|
|
220
|
+
target.fromBufferAttribute(position, i);
|
|
221
|
+
skinnedMesh.applyBoneTransform(i, target);
|
|
222
|
+
points.push(target.clone());
|
|
223
|
+
}
|
|
224
|
+
this.setFromPoints(points);
|
|
225
|
+
return this;
|
|
226
|
+
}
|
|
135
227
|
/** Volume (width * height * depth) */
|
|
136
228
|
getVolume() {
|
|
137
229
|
return this.width * this.height * this.depth;
|
|
@@ -252,13 +344,20 @@ class SceneTraversal {
|
|
|
252
344
|
}
|
|
253
345
|
}
|
|
254
346
|
/** Find all objects whose names match a pattern */
|
|
255
|
-
static filterObjects(object,
|
|
347
|
+
static filterObjects(object, filter) {
|
|
256
348
|
let result = [];
|
|
257
|
-
if (
|
|
258
|
-
|
|
349
|
+
if (typeof filter === "function") {
|
|
350
|
+
if (filter(object)) {
|
|
351
|
+
result.push(object);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
if (object.name && filter.test(object.name)) {
|
|
356
|
+
result.push(object);
|
|
357
|
+
}
|
|
259
358
|
}
|
|
260
359
|
for (const child of object.children) {
|
|
261
|
-
result = result.concat(SceneTraversal.filterObjects(child,
|
|
360
|
+
result = result.concat(SceneTraversal.filterObjects(child, filter));
|
|
262
361
|
}
|
|
263
362
|
return result;
|
|
264
363
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/BiFovCamera.ts","../src/Bounds.ts","../src/GeometryHasher.ts","../src/SceneTraversal.ts","../src/InstanceAssembler.ts","../src/SceneProcessor.ts","../src/SkinnedMeshBaker.ts","../src/Sun.ts"],"sourcesContent":["import { MathUtils, PerspectiveCamera } from \"three\";\n\nconst DEFAULT_HORIZONTAL_FOV = 90;\nconst DEFAULT_VERTICAL_FOV = 90;\nconst DEFAULT_ASPECT = 1;\nconst DEFAULT_NEAR = 1;\nconst DEFAULT_FAR = 1000;\n\nconst MIN_FOV = 1;\nconst MAX_FOV = 179;\n\n/**\n * A camera that supports independent horizontal and vertical FOV settings.\n * Extends Three.js PerspectiveCamera to allow separate control over horizontal\n * and vertical fields of view.\n */\nexport class BiFovCamera extends PerspectiveCamera {\n private horizontalFovInternal: number;\n private verticalFovInternal: number;\n\n /**\n * @param horizontalFov - Horizontal FOV in degrees (90° default)\n * @param verticalFov - Vertical FOV in degrees (90° default)\n * @param aspect - Width/height ratio (1 default)\n * @param near - Near clipping plane (1 default)\n * @param far - Far clipping plane (1000 default)\n */\n constructor(\n horizontalFov = DEFAULT_HORIZONTAL_FOV,\n verticalFov = DEFAULT_VERTICAL_FOV,\n aspect = DEFAULT_ASPECT,\n near = DEFAULT_NEAR,\n far = DEFAULT_FAR,\n ) {\n super(verticalFov, aspect, near, far);\n this.horizontalFovInternal = horizontalFov;\n this.verticalFovInternal = verticalFov;\n this.updateProjectionMatrix();\n }\n\n /** Current horizontal FOV in degrees */\n public get horizontalFov(): number {\n return this.horizontalFovInternal;\n }\n\n /** Current vertical FOV in degrees */\n public get verticalFov(): number {\n return this.verticalFovInternal;\n }\n\n /** Set horizontal FOV in degrees (clamped between 1° and 179°) */\n public set horizontalFov(value: number) {\n this.horizontalFovInternal = MathUtils.clamp(value, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /** Set vertical FOV in degrees (clamped between 1° and 179°) */\n public set verticalFov(value: number) {\n this.verticalFovInternal = MathUtils.clamp(value, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /**\n * Update both horizontal and vertical FOV\n * @param horizontal - Horizontal FOV in degrees\n * @param vertical - Vertical FOV in degrees\n */\n public setFov(horizontal: number, vertical: number): void {\n this.horizontalFovInternal = MathUtils.clamp(horizontal, MIN_FOV, MAX_FOV);\n this.verticalFovInternal = MathUtils.clamp(vertical, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /**\n * Copy FOV settings from another BiFovCamera\n * @param source - Camera to copy from\n */\n public copyFovSettings(source: BiFovCamera): void {\n this.horizontalFovInternal = source.horizontalFov;\n this.verticalFovInternal = source.verticalFov;\n this.updateProjectionMatrix();\n }\n\n /**\n * Updates the projection matrix based on FOV settings and aspect ratio.\n * In landscape: preserves horizontal FOV\n * In portrait: preserves vertical FOV\n */\n public override updateProjectionMatrix(): void {\n if (this.aspect >= 1) {\n // Landscape orientation: preserve horizontal FOV\n const radians = MathUtils.degToRad(this.horizontalFovInternal);\n this.fov = MathUtils.radToDeg(\n Math.atan(Math.tan(radians / 2) / this.aspect) * 2,\n );\n } else {\n // Portrait orientation: preserve vertical FOV\n this.fov = this.verticalFovInternal;\n }\n\n super.updateProjectionMatrix();\n }\n\n /** Get actual horizontal FOV after aspect ratio adjustments */\n public getEffectiveHorizontalFov(): number {\n if (this.aspect >= 1) {\n return this.horizontalFovInternal;\n }\n const verticalRadians = MathUtils.degToRad(this.verticalFovInternal);\n return MathUtils.radToDeg(\n Math.atan(Math.tan(verticalRadians / 2) * this.aspect) * 2,\n );\n }\n\n /** Get actual vertical FOV after aspect ratio adjustments */\n public getEffectiveVerticalFov(): number {\n if (this.aspect < 1) {\n return this.verticalFovInternal;\n }\n const horizontalRadians = MathUtils.degToRad(this.horizontalFovInternal);\n return MathUtils.radToDeg(\n Math.atan(Math.tan(horizontalRadians / 2) / this.aspect) * 2,\n );\n }\n\n /** Create a clone of this camera */\n public override clone(): this {\n const camera = new BiFovCamera(\n this.horizontalFovInternal,\n this.verticalFovInternal,\n this.aspect,\n this.near,\n this.far,\n ) as this;\n\n camera.copy(this, true);\n return camera;\n }\n}\n","import type { Object3D } from \"three\";\nimport { Box3, Vector3 } from \"three\";\n\n/**\n * Box3 with additional convenience methods for width, height, depth, etc.\n */\nexport class Bounds extends Box3 {\n /** Temporary vector for calculations */\n private readonly tempVector3A: Vector3 = new Vector3();\n\n constructor(object?: Object3D) {\n super();\n if (object) {\n this.setFromObject(object);\n }\n }\n\n /** Width (x-axis length) */\n public get width(): number {\n return this.max.x - this.min.x;\n }\n\n /** Height (y-axis length) */\n public get height(): number {\n return this.max.y - this.min.y;\n }\n\n /** Depth (z-axis length) */\n public get depth(): number {\n return this.max.z - this.min.z;\n }\n\n /** Length of the box's diagonal */\n public get diagonal(): number {\n return this.tempVector3A.subVectors(this.max, this.min).length();\n }\n\n /** Volume (width * height * depth) */\n public getVolume(): number {\n return this.width * this.height * this.depth;\n }\n\n /** Surface area (sum of all six faces) */\n public getSurfaceArea(): number {\n const w = this.width;\n const h = this.height;\n const d = this.depth;\n return 2 * (w * h + h * d + d * w);\n }\n}\n","import type { BufferGeometry } from \"three\";\n\nconst POSITION_COMPONENT_COUNT = 3;\nconst NORMAL_COMPONENT_COUNT = 3;\n\n/**\n * Internal utility to identify identical geometries.\n * @internal\n */\nexport class GeometryHasher {\n /**\n * Creates a hash for a geometry based on its vertex data.\n * Vertices that differ by less than tolerance are considered the same.\n *\n * @param geometry - Geometry to hash\n * @param tolerance - How close vertices need to be to count as identical\n * @returns Hash string that's the same for matching geometries\n * @internal\n */\n public static getGeometryHash(\n geometry: BufferGeometry,\n tolerance: number,\n ): string {\n const position = geometry.attributes[\"position\"];\n\n const positionArray = position.array;\n const positionHashParts: string[] = [];\n\n // Sample vertex positions with tolerance\n for (let i = 0; i < positionArray.length; i += POSITION_COMPONENT_COUNT) {\n const x = Math.round(positionArray[i] / tolerance);\n const y = Math.round(positionArray[i + 1] / tolerance);\n const z = Math.round(positionArray[i + 2] / tolerance);\n positionHashParts.push(`${x},${y},${z}`);\n }\n\n // Hash normal data if available\n const normal = geometry.attributes[\"normal\"];\n const normalHashParts: string[] = [];\n\n const normalArray = normal.array;\n for (let i = 0; i < normalArray.length; i += NORMAL_COMPONENT_COUNT) {\n const x = Math.round(normalArray[i] / tolerance);\n const y = Math.round(normalArray[i + 1] / tolerance);\n const z = Math.round(normalArray[i + 2] / tolerance);\n normalHashParts.push(`${x},${y},${z}`);\n }\n\n // Combine position and normal hashes\n const positionHash = positionHashParts.join(\"|\");\n const normalHash = normalHashParts.join(\"|\");\n\n return `${positionHash}#${normalHash}`;\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { Mesh } from \"three\";\n\n/** Constructor type for type-safe scene traversal */\nexport type Constructor<T> = abstract new (...args: never[]) => T;\n\n/** Find and modify objects in a Three.js scene */\nexport class SceneTraversal {\n /** Find first object with exact name match */\n public static getObjectByName(\n object: Object3D,\n name: string,\n ): Object3D | null {\n if (object.name === name) {\n return object;\n }\n\n for (const child of object.children) {\n const result = SceneTraversal.getObjectByName(child, name);\n if (result) {\n return result;\n }\n }\n\n return null;\n }\n\n /** Find first material with exact name match */\n public static getMaterialByName(\n object: Object3D,\n name: string,\n ): Material | null {\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n if (material.name === name) {\n return material;\n }\n }\n } else if (object.material.name === name) {\n return object.material;\n }\n }\n\n for (const child of object.children) {\n const material = SceneTraversal.getMaterialByName(child, name);\n if (material) {\n return material;\n }\n }\n\n return null;\n }\n\n /** Process all objects of a specific type */\n public static enumerateObjectsByType<T>(\n object: Object3D,\n type: Constructor<T>,\n callback: (instance: T) => void,\n ): void {\n if (object instanceof type) {\n callback(object);\n }\n\n for (const child of object.children) {\n SceneTraversal.enumerateObjectsByType(child, type, callback);\n }\n }\n\n /** Process all materials in meshes */\n public static enumerateMaterials(\n object: Object3D,\n callback: (material: Material) => void,\n ): void {\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n callback(material);\n }\n } else {\n callback(object.material);\n }\n }\n\n for (const child of object.children) {\n SceneTraversal.enumerateMaterials(child, callback);\n }\n }\n\n /** Find all objects whose names match a pattern */\n public static filterObjects(object: Object3D, name: RegExp): Object3D[] {\n let result: Object3D[] = [];\n\n if (object.name && name.test(object.name)) {\n result.push(object);\n }\n\n for (const child of object.children) {\n result = result.concat(SceneTraversal.filterObjects(child, name));\n }\n\n return result;\n }\n\n /** Find all materials whose names match a pattern */\n public static filterMaterials(object: Object3D, name: RegExp): Material[] {\n let result: Material[] = [];\n\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n if (material.name && name.test(material.name)) {\n result.push(material);\n }\n }\n } else {\n if (object.material.name && name.test(object.material.name)) {\n result.push(object.material);\n }\n }\n }\n\n for (const child of object.children) {\n result = result.concat(SceneTraversal.filterMaterials(child, name));\n }\n\n return result;\n }\n\n /** Set shadow properties on meshes */\n public static setShadowRecursive(\n object: Object3D,\n castShadow = true,\n receiveShadow = true,\n filter?: (object: Object3D) => boolean,\n ): void {\n if (object instanceof Mesh || \"isMesh\" in object) {\n (object as Mesh).castShadow = castShadow;\n (object as Mesh).receiveShadow = receiveShadow;\n }\n\n for (const child of object.children) {\n SceneTraversal.setShadowRecursive(\n child,\n castShadow,\n receiveShadow,\n filter,\n );\n }\n }\n}","import type { Material, Object3D } from \"three\";\nimport { InstancedMesh, Mesh } from \"three\";\nimport { GeometryHasher } from \"./GeometryHasher\";\nimport { SceneTraversal } from \"./SceneTraversal\";\n\nconst MIN_INSTANCE_COUNT = 2;\nconst DEFAULT_TOLERANCE = 1e-6;\n\n/** A group of meshes that can be instanced together */\ninterface MeshDescription {\n /** List of meshes */\n meshes: Mesh[];\n /** Materials to use */\n materials: Material[];\n /** Should cast shadows */\n castShadow: boolean;\n /** Should receive shadows */\n receiveShadow: boolean;\n}\n\n/** Configuration for instance assembly */\nexport interface InstanceAssemblerOptions {\n /** Filter which meshes to include */\n filter: (child: Mesh) => boolean;\n\n /** How close vertices need to be to count as identical */\n geometryTolerance: number;\n}\n\n/**\n * Combines identical meshes into instanced versions for better performance.\n * Meshes are considered identical if they share the same geometry and materials.\n */\nexport class InstanceAssembler {\n /**\n * Find meshes that can be instanced and combine them.\n * Only processes meshes that:\n * - Have no children\n * - Pass the filter function (if any)\n * - Share geometry with at least one other mesh\n *\n * @param container - Object containing meshes to process\n * @param options - Optional settings\n */\n public static assemble(\n container: Object3D,\n options: Partial<InstanceAssemblerOptions> = {},\n ): void {\n const dictionary = new Map<string, MeshDescription>();\n const instances: InstancedMesh[] = [];\n\n const tolerance = options.geometryTolerance ?? DEFAULT_TOLERANCE;\n const geometryHashes = new Map<string, string>();\n\n SceneTraversal.enumerateObjectsByType(container, Mesh, (child: Mesh) => {\n if (\n child.children.length === 0 &&\n (!options.filter || options.filter(child))\n ) {\n const materials = Array.isArray(child.material)\n ? child.material\n : [child.material];\n\n let geometryHash = geometryHashes.get(child.geometry.uuid);\n if (!geometryHash) {\n geometryHash = GeometryHasher.getGeometryHash(\n child.geometry,\n tolerance,\n );\n geometryHashes.set(child.geometry.uuid, geometryHash);\n }\n\n const materialKey = materials.map((m) => m.uuid).join(\",\");\n const compositeKey = `${geometryHash}|${materialKey}`;\n\n const entry = dictionary.get(compositeKey) ?? {\n meshes: [],\n materials,\n castShadow: false,\n receiveShadow: false,\n };\n\n if (child.castShadow) {\n entry.castShadow = true;\n }\n\n if (child.receiveShadow) {\n entry.receiveShadow = true;\n }\n\n entry.meshes.push(child);\n dictionary.set(compositeKey, entry);\n }\n });\n\n for (const descriptor of dictionary.values()) {\n if (descriptor.meshes.length < MIN_INSTANCE_COUNT) {\n continue;\n }\n const { meshes, materials, castShadow, receiveShadow } = descriptor;\n\n const sortedMeshes = meshes.sort((a, b) => a.name.localeCompare(b.name));\n const defaultMesh = sortedMeshes[0];\n\n const instancedMesh = new InstancedMesh(\n defaultMesh.geometry,\n materials.length === 1 ? materials[0] : materials,\n sortedMeshes.length,\n );\n\n instancedMesh.name = defaultMesh.name;\n instancedMesh.castShadow = castShadow;\n instancedMesh.receiveShadow = receiveShadow;\n\n for (let i = 0; i < sortedMeshes.length; i++) {\n const mesh = sortedMeshes[i];\n mesh.updateWorldMatrix(true, false);\n instancedMesh.setMatrixAt(i, mesh.matrixWorld);\n instancedMesh.userData[mesh.uuid] = mesh.userData;\n }\n\n instancedMesh.instanceMatrix.needsUpdate = true;\n instances.push(instancedMesh);\n\n for (const mesh of sortedMeshes) {\n mesh.parent?.remove(mesh);\n }\n }\n\n if (instances.length > 0) {\n container.add(...instances);\n }\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { FrontSide, Mesh } from \"three\";\nimport { InstanceAssembler } from \"./InstanceAssembler\";\nimport { SceneTraversal } from \"./SceneTraversal\";\n\n/** Options for scene post-processing */\nexport interface SceneProcessorOptions {\n /** Clone the input asset before processing? */\n cloneAsset: boolean;\n\n /** Combine identical meshes into instances? */\n assembleInstances: boolean;\n\n /** Names matching these patterns will cast shadows */\n castShadowExpressions: RegExp[];\n\n /** Names matching these patterns will receive shadows */\n receiveShadwoExpressions: RegExp[];\n\n /** Names matching these patterns will be transparent */\n transparentMaterialExpressions: RegExp[];\n\n /** Names matching these patterns won't write to depth buffer */\n noDepthWriteMaterialExpressions: RegExp[];\n}\n\n/** Post-processes a scene based on name patterns */\nexport class SceneProcessor {\n /**\n * Process a scene to set up materials and shadows.\n * \n * @param asset - Scene to process\n * @param options - How to process the scene\n * @returns Processed scene root objects\n */\n public static process(\n asset: Object3D,\n options: Partial<SceneProcessorOptions>,\n ): Object3D[] {\n const container = options.cloneAsset !== false ? asset.clone() : asset;\n\n if (options.assembleInstances !== false) {\n InstanceAssembler.assemble(container);\n }\n\n SceneTraversal.enumerateMaterials(container, (material: Material) => {\n material.transparent = SceneProcessor.matchesAny(\n material.name,\n options.transparentMaterialExpressions,\n );\n material.depthWrite = !SceneProcessor.matchesAny(\n material.name,\n options.noDepthWriteMaterialExpressions,\n );\n material.side = FrontSide;\n material.forceSinglePass = true;\n material.depthTest = true;\n });\n\n SceneTraversal.enumerateObjectsByType(container, Mesh, (child: Mesh) => {\n child.castShadow = SceneProcessor.matchesAny(\n child.name,\n options.castShadowExpressions,\n );\n child.receiveShadow = SceneProcessor.matchesAny(\n child.name,\n options.receiveShadwoExpressions,\n );\n });\n\n return container.children;\n }\n\n /** Does the string match any of the patterns? */\n private static matchesAny(\n value: string,\n expressions: RegExp[] = [],\n ): boolean {\n return expressions.some((p) => p.test(value));\n }\n}","import type { AnimationClip, Object3D, SkinnedMesh } from \"three\";\nimport { AnimationMixer, BufferAttribute, Mesh, Vector3 } from \"three\";\n\n/** Number of components per vertex */\nconst COMPONENT_COUNT = 3;\n\n/** Convert skinned meshes to regular static meshes */\nexport class SkinnedMeshBaker {\n /**\n * Convert a skinned mesh to a regular mesh in its current pose.\n * The resulting mesh will have no bones but look identical.\n * \n * @param skinnedMesh - Mesh to convert\n * @returns Static mesh with baked vertex positions\n */\n public static bakePose(skinnedMesh: SkinnedMesh): Mesh {\n const bakedGeometry = skinnedMesh.geometry.clone();\n const position = bakedGeometry.attributes[\"position\"] as BufferAttribute;\n const newPositions = new Float32Array(position.count * COMPONENT_COUNT);\n const target = new Vector3();\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n newPositions[i * COMPONENT_COUNT + 0] = target.x;\n newPositions[i * COMPONENT_COUNT + 1] = target.y;\n newPositions[i * COMPONENT_COUNT + 2] = target.z;\n }\n\n bakedGeometry.setAttribute(\n \"position\",\n new BufferAttribute(newPositions, COMPONENT_COUNT),\n );\n bakedGeometry.computeVertexNormals();\n bakedGeometry.deleteAttribute(\"skinIndex\");\n bakedGeometry.deleteAttribute(\"skinWeight\");\n\n const mesh = new Mesh(bakedGeometry, skinnedMesh.material);\n mesh.name = skinnedMesh.name;\n return mesh;\n }\n\n /**\n * Bake a single frame from an animation into a static mesh.\n * \n * @param armature - Root object with bones (usually from GLTF)\n * @param skinnedMesh - Mesh to convert\n * @param timeOffset - Time in seconds within the animation\n * @param clip - Animation to get the pose from\n * @returns Static mesh with baked vertex positions\n */\n public static bakeAnimationFrame(\n armature: Object3D,\n skinnedMesh: SkinnedMesh,\n timeOffset: number,\n clip: AnimationClip,\n ): Mesh {\n const mixer = new AnimationMixer(armature);\n const action = mixer.clipAction(clip);\n action.play();\n mixer.setTime(timeOffset);\n\n armature.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n return this.bakePose(skinnedMesh);\n }\n}","import type { Texture } from \"three\";\nimport { Box3, DirectionalLight, RGBAFormat, Spherical, Vector3 } from \"three\";\n\nconst RGBA_CHANNEL_COUNT = 4;\nconst RGB_CHANNEL_COUNT = 3;\n\nconst LUMINANCE_R = 0.2126;\nconst LUMINANCE_G = 0.7152;\nconst LUMINANCE_B = 0.0722;\n\n/** A directional light with spherical positioning controls */\nexport class Sun extends DirectionalLight {\n /** Internal vectors to avoid garbage collection */\n private readonly tempVector3D0 = new Vector3();\n private readonly tempVector3D1 = new Vector3();\n private readonly tempVector3D2 = new Vector3();\n private readonly tempVector3D3 = new Vector3();\n private readonly tempVector3D4 = new Vector3();\n private readonly tempVector3D5 = new Vector3();\n private readonly tempVector3D6 = new Vector3();\n private readonly tempVector3D7 = new Vector3();\n private readonly tempBox3 = new Box3();\n private readonly tempSpherical = new Spherical();\n\n /** Distance from the light to its target */\n public get distance(): number {\n return this.position.length();\n }\n\n /** Vertical angle from the ground in radians */\n public get elevation(): number {\n return this.tempSpherical.setFromVector3(this.position).phi;\n }\n\n /** Horizontal angle around the target in radians */\n public get azimuth(): number {\n return this.tempSpherical.setFromVector3(this.position).theta;\n }\n\n /** Set distance while keeping current angles */\n public set distance(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n value,\n this.tempSpherical.phi,\n this.tempSpherical.theta,\n );\n }\n\n /** Set elevation while keeping current distance and azimuth */\n public set elevation(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n this.tempSpherical.radius,\n value,\n this.tempSpherical.theta,\n );\n }\n\n /** Set azimuth while keeping current distance and elevation */\n public set azimuth(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n this.tempSpherical.radius,\n this.tempSpherical.phi,\n value,\n );\n }\n\n /** Configure shadows to cover all corners of a bounding box */\n public setShadowMapFromBox3(box3: Box3): void {\n const camera = this.shadow.camera;\n\n this.target.updateWorldMatrix(true, false);\n this.lookAt(this.target.getWorldPosition(this.tempVector3D0));\n\n this.updateWorldMatrix(true, false);\n\n const points: Vector3[] = [\n this.tempVector3D0.set(box3.min.x, box3.min.y, box3.min.z),\n this.tempVector3D1.set(box3.min.x, box3.min.y, box3.max.z),\n this.tempVector3D2.set(box3.min.x, box3.max.y, box3.min.z),\n this.tempVector3D3.set(box3.min.x, box3.max.y, box3.max.z),\n this.tempVector3D4.set(box3.max.x, box3.min.y, box3.min.z),\n this.tempVector3D5.set(box3.max.x, box3.min.y, box3.max.z),\n this.tempVector3D6.set(box3.max.x, box3.max.y, box3.min.z),\n this.tempVector3D7.set(box3.max.x, box3.max.y, box3.max.z),\n ];\n\n const inverseMatrix = this.matrixWorld.clone().invert();\n\n for (const point of points) {\n point.applyMatrix4(inverseMatrix);\n }\n\n const newBox3 = this.tempBox3.setFromPoints(points);\n\n camera.left = newBox3.min.x;\n camera.bottom = newBox3.min.y;\n camera.near = -newBox3.max.z;\n\n camera.right = newBox3.max.x;\n camera.top = newBox3.max.y;\n camera.far = -newBox3.min.z;\n\n camera.updateWorldMatrix(true, false);\n camera.updateProjectionMatrix();\n }\n\n /** Set light direction based on brightest point in an HDR texture */\n public setDirectionFromHDR(texture: Texture, distance = 1): void {\n const data = texture.image.data;\n const width = texture.image.width;\n const height = texture.image.height;\n\n let maxLuminance = 0;\n let maxIndex = 0;\n\n // Find brightest pixel\n\n const step =\n texture.format === RGBAFormat ? RGBA_CHANNEL_COUNT : RGB_CHANNEL_COUNT;\n for (let i = 0; i < data.length; i += step) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n const luminance = LUMINANCE_R * r + LUMINANCE_G * g + LUMINANCE_B * b;\n if (luminance > maxLuminance) {\n maxLuminance = luminance;\n maxIndex = i;\n }\n }\n\n // Convert to spherical coordinates\n const pixelIndex = maxIndex / step;\n const x = pixelIndex % width;\n const y = Math.floor(pixelIndex / width);\n\n const u = x / width;\n const v = y / height;\n\n const elevation = v * Math.PI;\n const azimuth = u * -Math.PI * 2 - Math.PI / 2;\n\n this.position.setFromSphericalCoords(distance, elevation, azimuth);\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/BiFovCamera.ts","../src/Bounds.ts","../src/GeometryHasher.ts","../src/SceneTraversal.ts","../src/InstanceAssembler.ts","../src/SceneProcessor.ts","../src/SkinnedMeshBaker.ts","../src/Sun.ts"],"sourcesContent":["import type { Box3, BufferAttribute, SkinnedMesh } from \"three\";\nimport { MathUtils, PerspectiveCamera, Vector3 } from \"three\";\n\nconst DEFAULT_HORIZONTAL_FOV = 90;\nconst DEFAULT_VERTICAL_FOV = 90;\nconst DEFAULT_ASPECT = 1;\nconst DEFAULT_NEAR = 1;\nconst DEFAULT_FAR = 1000;\n\nconst MIN_FOV = 1;\nconst MAX_FOV = 179;\n\n/**\n * A camera that supports independent horizontal and vertical FOV settings.\n * Extends Three.js PerspectiveCamera to allow separate control over horizontal\n * and vertical fields of view.\n */\nexport class BiFovCamera extends PerspectiveCamera {\n private horizontalFovInternal: number;\n private verticalFovInternal: number;\n\n /**\n * @param horizontalFov - Horizontal FOV in degrees (90° default)\n * @param verticalFov - Vertical FOV in degrees (90° default)\n * @param aspect - Width/height ratio (1 default)\n * @param near - Near clipping plane (1 default)\n * @param far - Far clipping plane (1000 default)\n */\n constructor(\n horizontalFov = DEFAULT_HORIZONTAL_FOV,\n verticalFov = DEFAULT_VERTICAL_FOV,\n aspect = DEFAULT_ASPECT,\n near = DEFAULT_NEAR,\n far = DEFAULT_FAR,\n ) {\n super(verticalFov, aspect, near, far);\n this.horizontalFovInternal = horizontalFov;\n this.verticalFovInternal = verticalFov;\n this.updateProjectionMatrix();\n }\n\n /** Current horizontal FOV in degrees */\n public get horizontalFov(): number {\n return this.horizontalFovInternal;\n }\n\n /** Current vertical FOV in degrees */\n public get verticalFov(): number {\n return this.verticalFovInternal;\n }\n\n /** Set horizontal FOV in degrees (clamped between 1° and 179°) */\n public set horizontalFov(value: number) {\n this.horizontalFovInternal = MathUtils.clamp(value, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /** Set vertical FOV in degrees (clamped between 1° and 179°) */\n public set verticalFov(value: number) {\n this.verticalFovInternal = MathUtils.clamp(value, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /**\n * Update both horizontal and vertical FOV\n * @param horizontal - Horizontal FOV in degrees\n * @param vertical - Vertical FOV in degrees\n */\n public setFov(horizontal: number, vertical: number): void {\n this.horizontalFovInternal = MathUtils.clamp(horizontal, MIN_FOV, MAX_FOV);\n this.verticalFovInternal = MathUtils.clamp(vertical, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /**\n * Copy FOV settings from another BiFovCamera\n * @param source - Camera to copy from\n */\n public copyFovSettings(source: BiFovCamera): void {\n this.horizontalFovInternal = source.horizontalFov;\n this.verticalFovInternal = source.verticalFov;\n this.updateProjectionMatrix();\n }\n\n /**\n * Updates the projection matrix based on FOV settings and aspect ratio.\n * In landscape: preserves horizontal FOV\n * In portrait: preserves vertical FOV\n */\n public override updateProjectionMatrix(): void {\n if (this.aspect > 1) {\n // Landscape orientation: preserve horizontal FOV\n const radians = MathUtils.degToRad(this.horizontalFovInternal);\n this.fov = MathUtils.radToDeg(\n Math.atan(Math.tan(radians / 2) / this.aspect) * 2,\n );\n } else {\n // Portrait orientation: preserve vertical FOV\n this.fov = this.verticalFovInternal;\n }\n\n super.updateProjectionMatrix();\n }\n\n /** Get actual horizontal FOV after aspect ratio adjustments */\n public getEffectiveHorizontalFov(): number {\n if (this.aspect >= 1) {\n return this.horizontalFovInternal;\n }\n const verticalRadians = MathUtils.degToRad(this.verticalFovInternal);\n return MathUtils.radToDeg(\n Math.atan(Math.tan(verticalRadians / 2) * this.aspect) * 2,\n );\n }\n\n /** Get actual vertical FOV after aspect ratio adjustments */\n public getEffectiveVerticalFov(): number {\n if (this.aspect < 1) {\n return this.verticalFovInternal;\n }\n const horizontalRadians = MathUtils.degToRad(this.horizontalFovInternal);\n return MathUtils.radToDeg(\n Math.atan(Math.tan(horizontalRadians / 2) / this.aspect) * 2,\n );\n }\n\n public fitPointsVerticalFov(vertices: Vector3[]): void {\n const up = new Vector3(0, 1, 0).applyQuaternion(this.quaternion);\n\n let maxVerticalAngle = 0;\n\n for (const vertex of vertices) {\n const vertexToCam = this.position.clone().sub(vertex);\n const vertexDirection = vertexToCam.normalize();\n\n const verticalAngle =\n Math.asin(Math.abs(vertexDirection.dot(up))) *\n Math.sign(vertexDirection.dot(up));\n\n if (Math.abs(verticalAngle) > maxVerticalAngle) {\n maxVerticalAngle = Math.abs(verticalAngle);\n }\n }\n\n const requiredFov = MathUtils.radToDeg(2 * maxVerticalAngle);\n\n this.verticalFovInternal = MathUtils.clamp(requiredFov, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n public fitBoxVerticalFov(box: Box3): void {\n this.fitPointsVerticalFov([\n new Vector3(box.min.x, box.min.y, box.min.z),\n new Vector3(box.min.x, box.min.y, box.max.z),\n new Vector3(box.min.x, box.max.y, box.min.z),\n new Vector3(box.min.x, box.max.y, box.max.z),\n new Vector3(box.max.x, box.min.y, box.min.z),\n new Vector3(box.max.x, box.min.y, box.max.z),\n new Vector3(box.max.x, box.max.y, box.min.z),\n new Vector3(box.max.x, box.max.y, box.max.z),\n ]);\n }\n\n public fitSkinnedMeshVerticalFov(skinnedMesh: SkinnedMesh): void {\n skinnedMesh.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n const bakedGeometry = skinnedMesh.geometry;\n const position = bakedGeometry.attributes[\"position\"] as BufferAttribute;\n const target = new Vector3();\n\n const points = [];\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n points.push(target.clone());\n }\n\n this.fitPointsVerticalFov(points);\n }\n\n public lookAtCenterOfMass(skinnedMesh: SkinnedMesh): void {\n skinnedMesh.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n const bakedGeometry = skinnedMesh.geometry;\n const position = bakedGeometry.attributes.position as BufferAttribute;\n const target = new Vector3();\n const points: Vector3[] = [];\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n points.push(target.clone());\n }\n\n const findMainCluster = (points: Vector3[], iterations = 3): Vector3 => {\n if (points.length === 0) {\n return new Vector3();\n }\n\n let center = points[Math.floor(points.length / 2)].clone();\n\n for (let i = 0; i < iterations; i++) {\n let total = new Vector3();\n let count = 0;\n\n for (const point of points) {\n if (\n point.distanceTo(center) < point.distanceTo(total) ||\n count === 0\n ) {\n total.add(point);\n count++;\n }\n }\n\n if (count > 0) {\n center = total.divideScalar(count);\n }\n }\n\n return center;\n };\n\n const centerOfMass = findMainCluster(points);\n this.lookAt(centerOfMass);\n }\n\n public override clone(): this {\n const camera = new BiFovCamera(\n this.horizontalFovInternal,\n this.verticalFovInternal,\n this.aspect,\n this.near,\n this.far,\n ) as this;\n\n camera.copy(this, true);\n return camera;\n }\n}\n","import type { BufferAttribute, Object3D, SkinnedMesh } from \"three\";\nimport { Box3, Vector3 } from \"three\";\n\n/**\n * Box3 with additional convenience methods for width, height, depth, etc.\n */\nexport class Bounds extends Box3 {\n /** Temporary vector for calculations */\n private readonly tempVector3A: Vector3 = new Vector3();\n\n constructor(object?: Object3D) {\n super();\n if (object) {\n this.setFromObject(object);\n }\n }\n\n /** Width (x-axis length) */\n public get width(): number {\n return this.max.x - this.min.x;\n }\n\n /** Height (y-axis length) */\n public get height(): number {\n return this.max.y - this.min.y;\n }\n\n /** Depth (z-axis length) */\n public get depth(): number {\n return this.max.z - this.min.z;\n }\n\n /** Length of the box's diagonal */\n public get diagonal(): number {\n return this.tempVector3A.subVectors(this.max, this.min).length();\n }\n\n public setFromSkinnedMesh(skinnedMesh: SkinnedMesh): Bounds {\n skinnedMesh.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n const geometry = skinnedMesh.geometry;\n const position = geometry.attributes[\"position\"] as BufferAttribute;\n const target = new Vector3();\n\n const points = [];\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n points.push(target.clone());\n }\n\n this.setFromPoints(points);\n return this;\n }\n\n /** Volume (width * height * depth) */\n public getVolume(): number {\n return this.width * this.height * this.depth;\n }\n\n /** Surface area (sum of all six faces) */\n public getSurfaceArea(): number {\n const w = this.width;\n const h = this.height;\n const d = this.depth;\n return 2 * (w * h + h * d + d * w);\n }\n}\n","import type { BufferGeometry } from \"three\";\n\nconst POSITION_COMPONENT_COUNT = 3;\nconst NORMAL_COMPONENT_COUNT = 3;\n\n/**\n * Internal utility to identify identical geometries.\n * @internal\n */\nexport class GeometryHasher {\n /**\n * Creates a hash for a geometry based on its vertex data.\n * Vertices that differ by less than tolerance are considered the same.\n *\n * @param geometry - Geometry to hash\n * @param tolerance - How close vertices need to be to count as identical\n * @returns Hash string that's the same for matching geometries\n * @internal\n */\n public static getGeometryHash(\n geometry: BufferGeometry,\n tolerance: number,\n ): string {\n const position = geometry.attributes[\"position\"];\n\n const positionArray = position.array;\n const positionHashParts: string[] = [];\n\n // Sample vertex positions with tolerance\n for (let i = 0; i < positionArray.length; i += POSITION_COMPONENT_COUNT) {\n const x = Math.round(positionArray[i] / tolerance);\n const y = Math.round(positionArray[i + 1] / tolerance);\n const z = Math.round(positionArray[i + 2] / tolerance);\n positionHashParts.push(`${x},${y},${z}`);\n }\n\n // Hash normal data if available\n const normal = geometry.attributes[\"normal\"];\n const normalHashParts: string[] = [];\n\n const normalArray = normal.array;\n for (let i = 0; i < normalArray.length; i += NORMAL_COMPONENT_COUNT) {\n const x = Math.round(normalArray[i] / tolerance);\n const y = Math.round(normalArray[i + 1] / tolerance);\n const z = Math.round(normalArray[i + 2] / tolerance);\n normalHashParts.push(`${x},${y},${z}`);\n }\n\n // Combine position and normal hashes\n const positionHash = positionHashParts.join(\"|\");\n const normalHash = normalHashParts.join(\"|\");\n\n return `${positionHash}#${normalHash}`;\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { Mesh } from \"three\";\n\n/** Constructor type for type-safe scene traversal */\nexport type Constructor<T> = abstract new (...args: never[]) => T;\n\n/** Find and modify objects in a Three.js scene */\nexport class SceneTraversal {\n /** Find first object with exact name match */\n public static getObjectByName(\n object: Object3D,\n name: string,\n ): Object3D | null {\n if (object.name === name) {\n return object;\n }\n\n for (const child of object.children) {\n const result = SceneTraversal.getObjectByName(child, name);\n if (result) {\n return result;\n }\n }\n\n return null;\n }\n\n /** Find first material with exact name match */\n public static getMaterialByName(\n object: Object3D,\n name: string,\n ): Material | null {\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n if (material.name === name) {\n return material;\n }\n }\n } else if (object.material.name === name) {\n return object.material;\n }\n }\n\n for (const child of object.children) {\n const material = SceneTraversal.getMaterialByName(child, name);\n if (material) {\n return material;\n }\n }\n\n return null;\n }\n\n /** Process all objects of a specific type */\n public static enumerateObjectsByType<T>(\n object: Object3D,\n type: Constructor<T>,\n callback: (instance: T) => void,\n ): void {\n if (object instanceof type) {\n callback(object);\n }\n\n for (const child of object.children) {\n SceneTraversal.enumerateObjectsByType(child, type, callback);\n }\n }\n\n /** Process all materials in meshes */\n public static enumerateMaterials(\n object: Object3D,\n callback: (material: Material) => void,\n ): void {\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n callback(material);\n }\n } else {\n callback(object.material);\n }\n }\n\n for (const child of object.children) {\n SceneTraversal.enumerateMaterials(child, callback);\n }\n }\n\n /** Find all objects whose names match a pattern */\n public static filterObjects(\n object: Object3D,\n filter: RegExp | ((object: Object3D) => boolean),\n ): Object3D[] {\n let result: Object3D[] = [];\n\n if (typeof filter === \"function\") {\n if (filter(object)) {\n result.push(object);\n }\n } else {\n if (object.name && filter.test(object.name)) {\n result.push(object);\n }\n }\n\n for (const child of object.children) {\n result = result.concat(SceneTraversal.filterObjects(child, filter));\n }\n\n return result;\n }\n\n /** Find all materials whose names match a pattern */\n public static filterMaterials(object: Object3D, name: RegExp): Material[] {\n let result: Material[] = [];\n\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n if (material.name && name.test(material.name)) {\n result.push(material);\n }\n }\n } else {\n if (object.material.name && name.test(object.material.name)) {\n result.push(object.material);\n }\n }\n }\n\n for (const child of object.children) {\n result = result.concat(SceneTraversal.filterMaterials(child, name));\n }\n\n return result;\n }\n\n /** Set shadow properties on meshes */\n public static setShadowRecursive(\n object: Object3D,\n castShadow = true,\n receiveShadow = true,\n filter?: (object: Object3D) => boolean,\n ): void {\n if (object instanceof Mesh || \"isMesh\" in object) {\n (object as Mesh).castShadow = castShadow;\n (object as Mesh).receiveShadow = receiveShadow;\n }\n\n for (const child of object.children) {\n SceneTraversal.setShadowRecursive(\n child,\n castShadow,\n receiveShadow,\n filter,\n );\n }\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { InstancedMesh, Mesh } from \"three\";\nimport { GeometryHasher } from \"./GeometryHasher\";\nimport { SceneTraversal } from \"./SceneTraversal\";\n\nconst MIN_INSTANCE_COUNT = 2;\nconst DEFAULT_TOLERANCE = 1e-6;\n\n/** A group of meshes that can be instanced together */\ninterface MeshDescription {\n /** List of meshes */\n meshes: Mesh[];\n /** Materials to use */\n materials: Material[];\n /** Should cast shadows */\n castShadow: boolean;\n /** Should receive shadows */\n receiveShadow: boolean;\n}\n\n/** Configuration for instance assembly */\nexport interface InstanceAssemblerOptions {\n /** Filter which meshes to include */\n filter: (child: Mesh) => boolean;\n\n /** How close vertices need to be to count as identical */\n geometryTolerance: number;\n}\n\n/**\n * Combines identical meshes into instanced versions for better performance.\n * Meshes are considered identical if they share the same geometry and materials.\n */\nexport class InstanceAssembler {\n /**\n * Find meshes that can be instanced and combine them.\n * Only processes meshes that:\n * - Have no children\n * - Pass the filter function (if any)\n * - Share geometry with at least one other mesh\n *\n * @param container - Object containing meshes to process\n * @param options - Optional settings\n */\n public static assemble(\n container: Object3D,\n options: Partial<InstanceAssemblerOptions> = {},\n ): void {\n const dictionary = new Map<string, MeshDescription>();\n const instances: InstancedMesh[] = [];\n\n const tolerance = options.geometryTolerance ?? DEFAULT_TOLERANCE;\n const geometryHashes = new Map<string, string>();\n\n SceneTraversal.enumerateObjectsByType(container, Mesh, (child: Mesh) => {\n if (\n child.children.length === 0 &&\n (!options.filter || options.filter(child))\n ) {\n const materials = Array.isArray(child.material)\n ? child.material\n : [child.material];\n\n let geometryHash = geometryHashes.get(child.geometry.uuid);\n if (!geometryHash) {\n geometryHash = GeometryHasher.getGeometryHash(\n child.geometry,\n tolerance,\n );\n geometryHashes.set(child.geometry.uuid, geometryHash);\n }\n\n const materialKey = materials.map((m) => m.uuid).join(\",\");\n const compositeKey = `${geometryHash}|${materialKey}`;\n\n const entry = dictionary.get(compositeKey) ?? {\n meshes: [],\n materials,\n castShadow: false,\n receiveShadow: false,\n };\n\n if (child.castShadow) {\n entry.castShadow = true;\n }\n\n if (child.receiveShadow) {\n entry.receiveShadow = true;\n }\n\n entry.meshes.push(child);\n dictionary.set(compositeKey, entry);\n }\n });\n\n for (const descriptor of dictionary.values()) {\n if (descriptor.meshes.length < MIN_INSTANCE_COUNT) {\n continue;\n }\n const { meshes, materials, castShadow, receiveShadow } = descriptor;\n\n const sortedMeshes = meshes.sort((a, b) => a.name.localeCompare(b.name));\n const defaultMesh = sortedMeshes[0];\n\n const instancedMesh = new InstancedMesh(\n defaultMesh.geometry,\n materials.length === 1 ? materials[0] : materials,\n sortedMeshes.length,\n );\n\n instancedMesh.name = defaultMesh.name;\n instancedMesh.castShadow = castShadow;\n instancedMesh.receiveShadow = receiveShadow;\n\n for (let i = 0; i < sortedMeshes.length; i++) {\n const mesh = sortedMeshes[i];\n mesh.updateWorldMatrix(true, false);\n instancedMesh.setMatrixAt(i, mesh.matrixWorld);\n instancedMesh.userData[mesh.uuid] = mesh.userData;\n }\n\n instancedMesh.instanceMatrix.needsUpdate = true;\n instances.push(instancedMesh);\n\n for (const mesh of sortedMeshes) {\n mesh.parent?.remove(mesh);\n }\n }\n\n if (instances.length > 0) {\n container.add(...instances);\n }\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { FrontSide, Mesh } from \"three\";\nimport { InstanceAssembler } from \"./InstanceAssembler\";\nimport { SceneTraversal } from \"./SceneTraversal\";\n\n/** Options for scene post-processing */\nexport interface SceneProcessorOptions {\n /** Clone the input asset before processing? */\n cloneAsset: boolean;\n\n /** Combine identical meshes into instances? */\n assembleInstances: boolean;\n\n /** Names matching these patterns will cast shadows */\n castShadowExpressions: RegExp[];\n\n /** Names matching these patterns will receive shadows */\n receiveShadwoExpressions: RegExp[];\n\n /** Names matching these patterns will be transparent */\n transparentMaterialExpressions: RegExp[];\n\n /** Names matching these patterns won't write to depth buffer */\n noDepthWriteMaterialExpressions: RegExp[];\n}\n\n/** Post-processes a scene based on name patterns */\nexport class SceneProcessor {\n /**\n * Process a scene to set up materials and shadows.\n * \n * @param asset - Scene to process\n * @param options - How to process the scene\n * @returns Processed scene root objects\n */\n public static process(\n asset: Object3D,\n options: Partial<SceneProcessorOptions>,\n ): Object3D[] {\n const container = options.cloneAsset !== false ? asset.clone() : asset;\n\n if (options.assembleInstances !== false) {\n InstanceAssembler.assemble(container);\n }\n\n SceneTraversal.enumerateMaterials(container, (material: Material) => {\n material.transparent = SceneProcessor.matchesAny(\n material.name,\n options.transparentMaterialExpressions,\n );\n material.depthWrite = !SceneProcessor.matchesAny(\n material.name,\n options.noDepthWriteMaterialExpressions,\n );\n material.side = FrontSide;\n material.forceSinglePass = true;\n material.depthTest = true;\n });\n\n SceneTraversal.enumerateObjectsByType(container, Mesh, (child: Mesh) => {\n child.castShadow = SceneProcessor.matchesAny(\n child.name,\n options.castShadowExpressions,\n );\n child.receiveShadow = SceneProcessor.matchesAny(\n child.name,\n options.receiveShadwoExpressions,\n );\n });\n\n return container.children;\n }\n\n /** Does the string match any of the patterns? */\n private static matchesAny(\n value: string,\n expressions: RegExp[] = [],\n ): boolean {\n return expressions.some((p) => p.test(value));\n }\n}","import type { AnimationClip, Object3D, SkinnedMesh } from \"three\";\nimport { AnimationMixer, BufferAttribute, Mesh, Vector3 } from \"three\";\n\n/** Number of components per vertex */\nconst COMPONENT_COUNT = 3;\n\n/** Convert skinned meshes to regular static meshes */\nexport class SkinnedMeshBaker {\n /**\n * Convert a skinned mesh to a regular mesh in its current pose.\n * The resulting mesh will have no bones but look identical.\n * \n * @param skinnedMesh - Mesh to convert\n * @returns Static mesh with baked vertex positions\n */\n public static bakePose(skinnedMesh: SkinnedMesh): Mesh {\n const bakedGeometry = skinnedMesh.geometry.clone();\n const position = bakedGeometry.attributes[\"position\"] as BufferAttribute;\n const newPositions = new Float32Array(position.count * COMPONENT_COUNT);\n const target = new Vector3();\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n newPositions[i * COMPONENT_COUNT + 0] = target.x;\n newPositions[i * COMPONENT_COUNT + 1] = target.y;\n newPositions[i * COMPONENT_COUNT + 2] = target.z;\n }\n\n bakedGeometry.setAttribute(\n \"position\",\n new BufferAttribute(newPositions, COMPONENT_COUNT),\n );\n bakedGeometry.computeVertexNormals();\n bakedGeometry.deleteAttribute(\"skinIndex\");\n bakedGeometry.deleteAttribute(\"skinWeight\");\n\n const mesh = new Mesh(bakedGeometry, skinnedMesh.material);\n mesh.name = skinnedMesh.name;\n return mesh;\n }\n\n /**\n * Bake a single frame from an animation into a static mesh.\n * \n * @param armature - Root object with bones (usually from GLTF)\n * @param skinnedMesh - Mesh to convert\n * @param timeOffset - Time in seconds within the animation\n * @param clip - Animation to get the pose from\n * @returns Static mesh with baked vertex positions\n */\n public static bakeAnimationFrame(\n armature: Object3D,\n skinnedMesh: SkinnedMesh,\n timeOffset: number,\n clip: AnimationClip,\n ): Mesh {\n const mixer = new AnimationMixer(armature);\n const action = mixer.clipAction(clip);\n action.play();\n mixer.setTime(timeOffset);\n\n armature.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n return this.bakePose(skinnedMesh);\n }\n}","import type { Texture } from \"three\";\nimport { Box3, DirectionalLight, RGBAFormat, Spherical, Vector3 } from \"three\";\n\nconst RGBA_CHANNEL_COUNT = 4;\nconst RGB_CHANNEL_COUNT = 3;\n\nconst LUMINANCE_R = 0.2126;\nconst LUMINANCE_G = 0.7152;\nconst LUMINANCE_B = 0.0722;\n\n/** A directional light with spherical positioning controls */\nexport class Sun extends DirectionalLight {\n /** Internal vectors to avoid garbage collection */\n private readonly tempVector3D0 = new Vector3();\n private readonly tempVector3D1 = new Vector3();\n private readonly tempVector3D2 = new Vector3();\n private readonly tempVector3D3 = new Vector3();\n private readonly tempVector3D4 = new Vector3();\n private readonly tempVector3D5 = new Vector3();\n private readonly tempVector3D6 = new Vector3();\n private readonly tempVector3D7 = new Vector3();\n private readonly tempBox3 = new Box3();\n private readonly tempSpherical = new Spherical();\n\n /** Distance from the light to its target */\n public get distance(): number {\n return this.position.length();\n }\n\n /** Vertical angle from the ground in radians */\n public get elevation(): number {\n return this.tempSpherical.setFromVector3(this.position).phi;\n }\n\n /** Horizontal angle around the target in radians */\n public get azimuth(): number {\n return this.tempSpherical.setFromVector3(this.position).theta;\n }\n\n /** Set distance while keeping current angles */\n public set distance(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n value,\n this.tempSpherical.phi,\n this.tempSpherical.theta,\n );\n }\n\n /** Set elevation while keeping current distance and azimuth */\n public set elevation(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n this.tempSpherical.radius,\n value,\n this.tempSpherical.theta,\n );\n }\n\n /** Set azimuth while keeping current distance and elevation */\n public set azimuth(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n this.tempSpherical.radius,\n this.tempSpherical.phi,\n value,\n );\n }\n\n /** Configure shadows to cover all corners of a bounding box */\n public setShadowMapFromBox3(box3: Box3): void {\n const camera = this.shadow.camera;\n\n this.target.updateWorldMatrix(true, false);\n this.lookAt(this.target.getWorldPosition(this.tempVector3D0));\n\n this.updateWorldMatrix(true, false);\n\n const points: Vector3[] = [\n this.tempVector3D0.set(box3.min.x, box3.min.y, box3.min.z),\n this.tempVector3D1.set(box3.min.x, box3.min.y, box3.max.z),\n this.tempVector3D2.set(box3.min.x, box3.max.y, box3.min.z),\n this.tempVector3D3.set(box3.min.x, box3.max.y, box3.max.z),\n this.tempVector3D4.set(box3.max.x, box3.min.y, box3.min.z),\n this.tempVector3D5.set(box3.max.x, box3.min.y, box3.max.z),\n this.tempVector3D6.set(box3.max.x, box3.max.y, box3.min.z),\n this.tempVector3D7.set(box3.max.x, box3.max.y, box3.max.z),\n ];\n\n const inverseMatrix = this.matrixWorld.clone().invert();\n\n for (const point of points) {\n point.applyMatrix4(inverseMatrix);\n }\n\n const newBox3 = this.tempBox3.setFromPoints(points);\n\n camera.left = newBox3.min.x;\n camera.bottom = newBox3.min.y;\n camera.near = -newBox3.max.z;\n\n camera.right = newBox3.max.x;\n camera.top = newBox3.max.y;\n camera.far = -newBox3.min.z;\n\n camera.updateWorldMatrix(true, false);\n camera.updateProjectionMatrix();\n }\n\n /** Set light direction based on brightest point in an HDR texture */\n public setDirectionFromHDR(texture: Texture, distance = 1): void {\n const data = texture.image.data;\n const width = texture.image.width;\n const height = texture.image.height;\n\n let maxLuminance = 0;\n let maxIndex = 0;\n\n // Find brightest pixel\n\n const step =\n texture.format === RGBAFormat ? RGBA_CHANNEL_COUNT : RGB_CHANNEL_COUNT;\n for (let i = 0; i < data.length; i += step) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n const luminance = LUMINANCE_R * r + LUMINANCE_G * g + LUMINANCE_B * b;\n if (luminance > maxLuminance) {\n maxLuminance = luminance;\n maxIndex = i;\n }\n }\n\n // Convert to spherical coordinates\n const pixelIndex = maxIndex / step;\n const x = pixelIndex % width;\n const y = Math.floor(pixelIndex / width);\n\n const u = x / width;\n const v = y / height;\n\n const elevation = v * Math.PI;\n const azimuth = u * -Math.PI * 2 - Math.PI / 2;\n\n this.position.setFromSphericalCoords(distance, elevation, azimuth);\n }\n}\n"],"names":[],"mappings":"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"}
|
package/dist/index.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{PerspectiveCamera as t,MathUtils as s,
|
|
1
|
+
import{PerspectiveCamera as t,MathUtils as s,Vector3 as e,Box3 as i,Mesh as n,InstancedMesh as h,FrontSide as o,BufferAttribute as r,AnimationMixer as a,DirectionalLight as c,Spherical as f,RGBAFormat as l}from"three";const u=179;class w extends t{constructor(t=90,s=90,e=1,i=1,n=1e3){super(s,e,i,n),this.horizontalFovInternal=t,this.verticalFovInternal=s,this.updateProjectionMatrix()}get horizontalFov(){return this.horizontalFovInternal}get verticalFov(){return this.verticalFovInternal}set horizontalFov(t){this.horizontalFovInternal=s.clamp(t,1,u),this.updateProjectionMatrix()}set verticalFov(t){this.verticalFovInternal=s.clamp(t,1,u),this.updateProjectionMatrix()}setFov(t,e){this.horizontalFovInternal=s.clamp(t,1,u),this.verticalFovInternal=s.clamp(e,1,u),this.updateProjectionMatrix()}copyFovSettings(t){this.horizontalFovInternal=t.horizontalFov,this.verticalFovInternal=t.verticalFov,this.updateProjectionMatrix()}updateProjectionMatrix(){if(this.aspect>1){const t=s.degToRad(this.horizontalFovInternal);this.fov=s.radToDeg(2*Math.atan(Math.tan(t/2)/this.aspect))}else this.fov=this.verticalFovInternal;super.updateProjectionMatrix()}getEffectiveHorizontalFov(){if(this.aspect>=1)return this.horizontalFovInternal;const t=s.degToRad(this.verticalFovInternal);return s.radToDeg(2*Math.atan(Math.tan(t/2)*this.aspect))}getEffectiveVerticalFov(){if(this.aspect<1)return this.verticalFovInternal;const t=s.degToRad(this.horizontalFovInternal);return s.radToDeg(2*Math.atan(Math.tan(t/2)/this.aspect))}fitPointsVerticalFov(t){const i=new e(0,1,0).applyQuaternion(this.quaternion);let n=0;for(const s of t){const t=this.position.clone().sub(s).normalize(),e=Math.asin(Math.abs(t.dot(i)))*Math.sign(t.dot(i));Math.abs(e)>n&&(n=Math.abs(e))}const h=s.radToDeg(2*n);this.verticalFovInternal=s.clamp(h,1,u),this.updateProjectionMatrix()}fitBoxVerticalFov(t){this.fitPointsVerticalFov([new e(t.min.x,t.min.y,t.min.z),new e(t.min.x,t.min.y,t.max.z),new e(t.min.x,t.max.y,t.min.z),new e(t.min.x,t.max.y,t.max.z),new e(t.max.x,t.min.y,t.min.z),new e(t.max.x,t.min.y,t.max.z),new e(t.max.x,t.max.y,t.min.z),new e(t.max.x,t.max.y,t.max.z)])}fitSkinnedMeshVerticalFov(t){t.updateWorldMatrix(!0,!0),t.skeleton.update();const s=t.geometry.attributes.position,i=new e,n=[];for(let e=0;e<s.count;e++)i.fromBufferAttribute(s,e),t.applyBoneTransform(e,i),n.push(i.clone());this.fitPointsVerticalFov(n)}lookAtCenterOfMass(t){t.updateWorldMatrix(!0,!0),t.skeleton.update();const s=t.geometry.attributes.position,i=new e,n=[];for(let e=0;e<s.count;e++)i.fromBufferAttribute(s,e),t.applyBoneTransform(e,i),n.push(i.clone());const h=((t,s=3)=>{if(0===t.length)return new e;let i=t[Math.floor(t.length/2)].clone();for(let n=0;n<s;n++){let s=new e,n=0;for(const e of t)(e.distanceTo(i)<e.distanceTo(s)||0===n)&&(s.add(e),n++);n>0&&(i=s.divideScalar(n))}return i})(n);this.lookAt(h)}clone(){const t=new w(this.horizontalFovInternal,this.verticalFovInternal,this.aspect,this.near,this.far);return t.copy(this,!0),t}}class M extends i{constructor(t){super(),this.tempVector3A=new e,t&&this.setFromObject(t)}get width(){return this.max.x-this.min.x}get height(){return this.max.y-this.min.y}get depth(){return this.max.z-this.min.z}get diagonal(){return this.tempVector3A.subVectors(this.max,this.min).length()}setFromSkinnedMesh(t){t.updateWorldMatrix(!0,!0),t.skeleton.update();const s=t.geometry.attributes.position,i=new e,n=[];for(let e=0;e<s.count;e++)i.fromBufferAttribute(s,e),t.applyBoneTransform(e,i),n.push(i.clone());return this.setFromPoints(n),this}getVolume(){return this.width*this.height*this.depth}getSurfaceArea(){const t=this.width,s=this.height,e=this.depth;return 2*(t*s+s*e+e*t)}}class v{static getGeometryHash(t,s){const e=t.attributes.position.array,i=[];for(let t=0;t<e.length;t+=3)i.push(`${Math.round(e[t]/s)},${Math.round(e[t+1]/s)},${Math.round(e[t+2]/s)}`);const n=[],h=t.attributes.normal.array;for(let t=0;t<h.length;t+=3)n.push(`${Math.round(h[t]/s)},${Math.round(h[t+1]/s)},${Math.round(h[t+2]/s)}`);return`${i.join("|")}#${n.join("|")}`}}class d{static getObjectByName(t,s){if(t.name===s)return t;for(const e of t.children){const t=d.getObjectByName(e,s);if(t)return t}return null}static getMaterialByName(t,s){if(t instanceof n)if(Array.isArray(t.material)){for(const e of t.material)if(e.name===s)return e}else if(t.material.name===s)return t.material;for(const e of t.children){const t=d.getMaterialByName(e,s);if(t)return t}return null}static enumerateObjectsByType(t,s,e){t instanceof s&&e(t);for(const i of t.children)d.enumerateObjectsByType(i,s,e)}static enumerateMaterials(t,s){if(t instanceof n)if(Array.isArray(t.material))for(const e of t.material)s(e);else s(t.material);for(const e of t.children)d.enumerateMaterials(e,s)}static filterObjects(t,s){let e=[];"function"==typeof s?s(t)&&e.push(t):t.name&&s.test(t.name)&&e.push(t);for(const i of t.children)e=e.concat(d.filterObjects(i,s));return e}static filterMaterials(t,s){let e=[];if(t instanceof n)if(Array.isArray(t.material))for(const i of t.material)i.name&&s.test(i.name)&&e.push(i);else t.material.name&&s.test(t.material.name)&&e.push(t.material);for(const i of t.children)e=e.concat(d.filterMaterials(i,s));return e}static setShadowRecursive(t,s=!0,e=!0,i){(t instanceof n||"isMesh"in t)&&(t.castShadow=s,t.receiveShadow=e);for(const n of t.children)d.setShadowRecursive(n,s,e,i)}}class m{static assemble(t,s={}){var e,i;const o=new Map,r=[],a=null!==(e=s.geometryTolerance)&&void 0!==e?e:1e-6,c=new Map;d.enumerateObjectsByType(t,n,(t=>{var e;if(0===t.children.length&&(!s.filter||s.filter(t))){const s=Array.isArray(t.material)?t.material:[t.material];let i=c.get(t.geometry.uuid);i||(i=v.getGeometryHash(t.geometry,a),c.set(t.geometry.uuid,i));const n=`${i}|${s.map((t=>t.uuid)).join(",")}`,h=null!==(e=o.get(n))&&void 0!==e?e:{meshes:[],materials:s,castShadow:!1,receiveShadow:!1};t.castShadow&&(h.castShadow=!0),t.receiveShadow&&(h.receiveShadow=!0),h.meshes.push(t),o.set(n,h)}}));for(const t of o.values()){if(t.meshes.length<2)continue;const{meshes:s,materials:e,castShadow:n,receiveShadow:o}=t,a=s.sort(((t,s)=>t.name.localeCompare(s.name))),c=a[0],f=new h(c.geometry,1===e.length?e[0]:e,a.length);f.name=c.name,f.castShadow=n,f.receiveShadow=o;for(let t=0;t<a.length;t++){const s=a[t];s.updateWorldMatrix(!0,!1),f.setMatrixAt(t,s.matrixWorld),f.userData[s.uuid]=s.userData}f.instanceMatrix.needsUpdate=!0,r.push(f);for(const t of a)null===(i=t.parent)||void 0===i||i.remove(t)}r.length>0&&t.add(...r)}}class g{static process(t,s){const e=!1!==s.cloneAsset?t.clone():t;return!1!==s.assembleInstances&&m.assemble(e),d.enumerateMaterials(e,(t=>{t.transparent=g.matchesAny(t.name,s.transparentMaterialExpressions),t.depthWrite=!g.matchesAny(t.name,s.noDepthWriteMaterialExpressions),t.side=o,t.forceSinglePass=!0,t.depthTest=!0})),d.enumerateObjectsByType(e,n,(t=>{t.castShadow=g.matchesAny(t.name,s.castShadowExpressions),t.receiveShadow=g.matchesAny(t.name,s.receiveShadwoExpressions)})),e.children}static matchesAny(t,s=[]){return s.some((s=>s.test(t)))}}class p{static bakePose(t){const s=t.geometry.clone(),i=s.attributes.position,h=new Float32Array(3*i.count),o=new e;for(let s=0;s<i.count;s++)o.fromBufferAttribute(i,s),t.applyBoneTransform(s,o),h[3*s+0]=o.x,h[3*s+1]=o.y,h[3*s+2]=o.z;s.setAttribute("position",new r(h,3)),s.computeVertexNormals(),s.deleteAttribute("skinIndex"),s.deleteAttribute("skinWeight");const a=new n(s,t.material);return a.name=t.name,a}static bakeAnimationFrame(t,s,e,i){const n=new a(t);return n.clipAction(i).play(),n.setTime(e),t.updateWorldMatrix(!0,!0),s.skeleton.update(),this.bakePose(s)}}class F extends c{constructor(){super(...arguments),this.tempVector3D0=new e,this.tempVector3D1=new e,this.tempVector3D2=new e,this.tempVector3D3=new e,this.tempVector3D4=new e,this.tempVector3D5=new e,this.tempVector3D6=new e,this.tempVector3D7=new e,this.tempBox3=new i,this.tempSpherical=new f}get distance(){return this.position.length()}get elevation(){return this.tempSpherical.setFromVector3(this.position).phi}get azimuth(){return this.tempSpherical.setFromVector3(this.position).theta}set distance(t){this.tempSpherical.setFromVector3(this.position),this.position.setFromSphericalCoords(t,this.tempSpherical.phi,this.tempSpherical.theta)}set elevation(t){this.tempSpherical.setFromVector3(this.position),this.position.setFromSphericalCoords(this.tempSpherical.radius,t,this.tempSpherical.theta)}set azimuth(t){this.tempSpherical.setFromVector3(this.position),this.position.setFromSphericalCoords(this.tempSpherical.radius,this.tempSpherical.phi,t)}setShadowMapFromBox3(t){const s=this.shadow.camera;this.target.updateWorldMatrix(!0,!1),this.lookAt(this.target.getWorldPosition(this.tempVector3D0)),this.updateWorldMatrix(!0,!1);const e=[this.tempVector3D0.set(t.min.x,t.min.y,t.min.z),this.tempVector3D1.set(t.min.x,t.min.y,t.max.z),this.tempVector3D2.set(t.min.x,t.max.y,t.min.z),this.tempVector3D3.set(t.min.x,t.max.y,t.max.z),this.tempVector3D4.set(t.max.x,t.min.y,t.min.z),this.tempVector3D5.set(t.max.x,t.min.y,t.max.z),this.tempVector3D6.set(t.max.x,t.max.y,t.min.z),this.tempVector3D7.set(t.max.x,t.max.y,t.max.z)],i=this.matrixWorld.clone().invert();for(const t of e)t.applyMatrix4(i);const n=this.tempBox3.setFromPoints(e);s.left=n.min.x,s.bottom=n.min.y,s.near=-n.max.z,s.right=n.max.x,s.top=n.max.y,s.far=-n.min.z,s.updateWorldMatrix(!0,!1),s.updateProjectionMatrix()}setDirectionFromHDR(t,s=1){const e=t.image.data,i=t.image.width,n=t.image.height;let h=0,o=0;const r=t.format===l?4:3;for(let t=0;t<e.length;t+=r){const s=.2126*e[t]+.7152*e[t+1]+.0722*e[t+2];s>h&&(h=s,o=t)}const a=o/r,c=a%i;this.position.setFromSphericalCoords(s,Math.floor(a/i)/n*Math.PI,c/i*-Math.PI*2-Math.PI/2)}}export{w as BiFovCamera,M as Bounds,m as InstanceAssembler,g as SceneProcessor,d as SceneTraversal,p as SkinnedMeshBaker,F as Sun};
|
|
2
2
|
//# sourceMappingURL=index.min.js.map
|
package/dist/index.min.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.min.js","sources":["../src/BiFovCamera.ts","../src/Bounds.ts","../src/GeometryHasher.ts","../src/SceneTraversal.ts","../src/InstanceAssembler.ts","../src/SceneProcessor.ts","../src/SkinnedMeshBaker.ts","../src/Sun.ts"],"sourcesContent":["import { MathUtils, PerspectiveCamera } from \"three\";\n\nconst DEFAULT_HORIZONTAL_FOV = 90;\nconst DEFAULT_VERTICAL_FOV = 90;\nconst DEFAULT_ASPECT = 1;\nconst DEFAULT_NEAR = 1;\nconst DEFAULT_FAR = 1000;\n\nconst MIN_FOV = 1;\nconst MAX_FOV = 179;\n\n/**\n * A camera that supports independent horizontal and vertical FOV settings.\n * Extends Three.js PerspectiveCamera to allow separate control over horizontal\n * and vertical fields of view.\n */\nexport class BiFovCamera extends PerspectiveCamera {\n private horizontalFovInternal: number;\n private verticalFovInternal: number;\n\n /**\n * @param horizontalFov - Horizontal FOV in degrees (90° default)\n * @param verticalFov - Vertical FOV in degrees (90° default)\n * @param aspect - Width/height ratio (1 default)\n * @param near - Near clipping plane (1 default)\n * @param far - Far clipping plane (1000 default)\n */\n constructor(\n horizontalFov = DEFAULT_HORIZONTAL_FOV,\n verticalFov = DEFAULT_VERTICAL_FOV,\n aspect = DEFAULT_ASPECT,\n near = DEFAULT_NEAR,\n far = DEFAULT_FAR,\n ) {\n super(verticalFov, aspect, near, far);\n this.horizontalFovInternal = horizontalFov;\n this.verticalFovInternal = verticalFov;\n this.updateProjectionMatrix();\n }\n\n /** Current horizontal FOV in degrees */\n public get horizontalFov(): number {\n return this.horizontalFovInternal;\n }\n\n /** Current vertical FOV in degrees */\n public get verticalFov(): number {\n return this.verticalFovInternal;\n }\n\n /** Set horizontal FOV in degrees (clamped between 1° and 179°) */\n public set horizontalFov(value: number) {\n this.horizontalFovInternal = MathUtils.clamp(value, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /** Set vertical FOV in degrees (clamped between 1° and 179°) */\n public set verticalFov(value: number) {\n this.verticalFovInternal = MathUtils.clamp(value, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /**\n * Update both horizontal and vertical FOV\n * @param horizontal - Horizontal FOV in degrees\n * @param vertical - Vertical FOV in degrees\n */\n public setFov(horizontal: number, vertical: number): void {\n this.horizontalFovInternal = MathUtils.clamp(horizontal, MIN_FOV, MAX_FOV);\n this.verticalFovInternal = MathUtils.clamp(vertical, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /**\n * Copy FOV settings from another BiFovCamera\n * @param source - Camera to copy from\n */\n public copyFovSettings(source: BiFovCamera): void {\n this.horizontalFovInternal = source.horizontalFov;\n this.verticalFovInternal = source.verticalFov;\n this.updateProjectionMatrix();\n }\n\n /**\n * Updates the projection matrix based on FOV settings and aspect ratio.\n * In landscape: preserves horizontal FOV\n * In portrait: preserves vertical FOV\n */\n public override updateProjectionMatrix(): void {\n if (this.aspect >= 1) {\n // Landscape orientation: preserve horizontal FOV\n const radians = MathUtils.degToRad(this.horizontalFovInternal);\n this.fov = MathUtils.radToDeg(\n Math.atan(Math.tan(radians / 2) / this.aspect) * 2,\n );\n } else {\n // Portrait orientation: preserve vertical FOV\n this.fov = this.verticalFovInternal;\n }\n\n super.updateProjectionMatrix();\n }\n\n /** Get actual horizontal FOV after aspect ratio adjustments */\n public getEffectiveHorizontalFov(): number {\n if (this.aspect >= 1) {\n return this.horizontalFovInternal;\n }\n const verticalRadians = MathUtils.degToRad(this.verticalFovInternal);\n return MathUtils.radToDeg(\n Math.atan(Math.tan(verticalRadians / 2) * this.aspect) * 2,\n );\n }\n\n /** Get actual vertical FOV after aspect ratio adjustments */\n public getEffectiveVerticalFov(): number {\n if (this.aspect < 1) {\n return this.verticalFovInternal;\n }\n const horizontalRadians = MathUtils.degToRad(this.horizontalFovInternal);\n return MathUtils.radToDeg(\n Math.atan(Math.tan(horizontalRadians / 2) / this.aspect) * 2,\n );\n }\n\n /** Create a clone of this camera */\n public override clone(): this {\n const camera = new BiFovCamera(\n this.horizontalFovInternal,\n this.verticalFovInternal,\n this.aspect,\n this.near,\n this.far,\n ) as this;\n\n camera.copy(this, true);\n return camera;\n }\n}\n","import type { Object3D } from \"three\";\nimport { Box3, Vector3 } from \"three\";\n\n/**\n * Box3 with additional convenience methods for width, height, depth, etc.\n */\nexport class Bounds extends Box3 {\n /** Temporary vector for calculations */\n private readonly tempVector3A: Vector3 = new Vector3();\n\n constructor(object?: Object3D) {\n super();\n if (object) {\n this.setFromObject(object);\n }\n }\n\n /** Width (x-axis length) */\n public get width(): number {\n return this.max.x - this.min.x;\n }\n\n /** Height (y-axis length) */\n public get height(): number {\n return this.max.y - this.min.y;\n }\n\n /** Depth (z-axis length) */\n public get depth(): number {\n return this.max.z - this.min.z;\n }\n\n /** Length of the box's diagonal */\n public get diagonal(): number {\n return this.tempVector3A.subVectors(this.max, this.min).length();\n }\n\n /** Volume (width * height * depth) */\n public getVolume(): number {\n return this.width * this.height * this.depth;\n }\n\n /** Surface area (sum of all six faces) */\n public getSurfaceArea(): number {\n const w = this.width;\n const h = this.height;\n const d = this.depth;\n return 2 * (w * h + h * d + d * w);\n }\n}\n","import type { BufferGeometry } from \"three\";\n\nconst POSITION_COMPONENT_COUNT = 3;\nconst NORMAL_COMPONENT_COUNT = 3;\n\n/**\n * Internal utility to identify identical geometries.\n * @internal\n */\nexport class GeometryHasher {\n /**\n * Creates a hash for a geometry based on its vertex data.\n * Vertices that differ by less than tolerance are considered the same.\n *\n * @param geometry - Geometry to hash\n * @param tolerance - How close vertices need to be to count as identical\n * @returns Hash string that's the same for matching geometries\n * @internal\n */\n public static getGeometryHash(\n geometry: BufferGeometry,\n tolerance: number,\n ): string {\n const position = geometry.attributes[\"position\"];\n\n const positionArray = position.array;\n const positionHashParts: string[] = [];\n\n // Sample vertex positions with tolerance\n for (let i = 0; i < positionArray.length; i += POSITION_COMPONENT_COUNT) {\n const x = Math.round(positionArray[i] / tolerance);\n const y = Math.round(positionArray[i + 1] / tolerance);\n const z = Math.round(positionArray[i + 2] / tolerance);\n positionHashParts.push(`${x},${y},${z}`);\n }\n\n // Hash normal data if available\n const normal = geometry.attributes[\"normal\"];\n const normalHashParts: string[] = [];\n\n const normalArray = normal.array;\n for (let i = 0; i < normalArray.length; i += NORMAL_COMPONENT_COUNT) {\n const x = Math.round(normalArray[i] / tolerance);\n const y = Math.round(normalArray[i + 1] / tolerance);\n const z = Math.round(normalArray[i + 2] / tolerance);\n normalHashParts.push(`${x},${y},${z}`);\n }\n\n // Combine position and normal hashes\n const positionHash = positionHashParts.join(\"|\");\n const normalHash = normalHashParts.join(\"|\");\n\n return `${positionHash}#${normalHash}`;\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { Mesh } from \"three\";\n\n/** Constructor type for type-safe scene traversal */\nexport type Constructor<T> = abstract new (...args: never[]) => T;\n\n/** Find and modify objects in a Three.js scene */\nexport class SceneTraversal {\n /** Find first object with exact name match */\n public static getObjectByName(\n object: Object3D,\n name: string,\n ): Object3D | null {\n if (object.name === name) {\n return object;\n }\n\n for (const child of object.children) {\n const result = SceneTraversal.getObjectByName(child, name);\n if (result) {\n return result;\n }\n }\n\n return null;\n }\n\n /** Find first material with exact name match */\n public static getMaterialByName(\n object: Object3D,\n name: string,\n ): Material | null {\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n if (material.name === name) {\n return material;\n }\n }\n } else if (object.material.name === name) {\n return object.material;\n }\n }\n\n for (const child of object.children) {\n const material = SceneTraversal.getMaterialByName(child, name);\n if (material) {\n return material;\n }\n }\n\n return null;\n }\n\n /** Process all objects of a specific type */\n public static enumerateObjectsByType<T>(\n object: Object3D,\n type: Constructor<T>,\n callback: (instance: T) => void,\n ): void {\n if (object instanceof type) {\n callback(object);\n }\n\n for (const child of object.children) {\n SceneTraversal.enumerateObjectsByType(child, type, callback);\n }\n }\n\n /** Process all materials in meshes */\n public static enumerateMaterials(\n object: Object3D,\n callback: (material: Material) => void,\n ): void {\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n callback(material);\n }\n } else {\n callback(object.material);\n }\n }\n\n for (const child of object.children) {\n SceneTraversal.enumerateMaterials(child, callback);\n }\n }\n\n /** Find all objects whose names match a pattern */\n public static filterObjects(object: Object3D, name: RegExp): Object3D[] {\n let result: Object3D[] = [];\n\n if (object.name && name.test(object.name)) {\n result.push(object);\n }\n\n for (const child of object.children) {\n result = result.concat(SceneTraversal.filterObjects(child, name));\n }\n\n return result;\n }\n\n /** Find all materials whose names match a pattern */\n public static filterMaterials(object: Object3D, name: RegExp): Material[] {\n let result: Material[] = [];\n\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n if (material.name && name.test(material.name)) {\n result.push(material);\n }\n }\n } else {\n if (object.material.name && name.test(object.material.name)) {\n result.push(object.material);\n }\n }\n }\n\n for (const child of object.children) {\n result = result.concat(SceneTraversal.filterMaterials(child, name));\n }\n\n return result;\n }\n\n /** Set shadow properties on meshes */\n public static setShadowRecursive(\n object: Object3D,\n castShadow = true,\n receiveShadow = true,\n filter?: (object: Object3D) => boolean,\n ): void {\n if (object instanceof Mesh || \"isMesh\" in object) {\n (object as Mesh).castShadow = castShadow;\n (object as Mesh).receiveShadow = receiveShadow;\n }\n\n for (const child of object.children) {\n SceneTraversal.setShadowRecursive(\n child,\n castShadow,\n receiveShadow,\n filter,\n );\n }\n }\n}","import type { Material, Object3D } from \"three\";\nimport { InstancedMesh, Mesh } from \"three\";\nimport { GeometryHasher } from \"./GeometryHasher\";\nimport { SceneTraversal } from \"./SceneTraversal\";\n\nconst MIN_INSTANCE_COUNT = 2;\nconst DEFAULT_TOLERANCE = 1e-6;\n\n/** A group of meshes that can be instanced together */\ninterface MeshDescription {\n /** List of meshes */\n meshes: Mesh[];\n /** Materials to use */\n materials: Material[];\n /** Should cast shadows */\n castShadow: boolean;\n /** Should receive shadows */\n receiveShadow: boolean;\n}\n\n/** Configuration for instance assembly */\nexport interface InstanceAssemblerOptions {\n /** Filter which meshes to include */\n filter: (child: Mesh) => boolean;\n\n /** How close vertices need to be to count as identical */\n geometryTolerance: number;\n}\n\n/**\n * Combines identical meshes into instanced versions for better performance.\n * Meshes are considered identical if they share the same geometry and materials.\n */\nexport class InstanceAssembler {\n /**\n * Find meshes that can be instanced and combine them.\n * Only processes meshes that:\n * - Have no children\n * - Pass the filter function (if any)\n * - Share geometry with at least one other mesh\n *\n * @param container - Object containing meshes to process\n * @param options - Optional settings\n */\n public static assemble(\n container: Object3D,\n options: Partial<InstanceAssemblerOptions> = {},\n ): void {\n const dictionary = new Map<string, MeshDescription>();\n const instances: InstancedMesh[] = [];\n\n const tolerance = options.geometryTolerance ?? DEFAULT_TOLERANCE;\n const geometryHashes = new Map<string, string>();\n\n SceneTraversal.enumerateObjectsByType(container, Mesh, (child: Mesh) => {\n if (\n child.children.length === 0 &&\n (!options.filter || options.filter(child))\n ) {\n const materials = Array.isArray(child.material)\n ? child.material\n : [child.material];\n\n let geometryHash = geometryHashes.get(child.geometry.uuid);\n if (!geometryHash) {\n geometryHash = GeometryHasher.getGeometryHash(\n child.geometry,\n tolerance,\n );\n geometryHashes.set(child.geometry.uuid, geometryHash);\n }\n\n const materialKey = materials.map((m) => m.uuid).join(\",\");\n const compositeKey = `${geometryHash}|${materialKey}`;\n\n const entry = dictionary.get(compositeKey) ?? {\n meshes: [],\n materials,\n castShadow: false,\n receiveShadow: false,\n };\n\n if (child.castShadow) {\n entry.castShadow = true;\n }\n\n if (child.receiveShadow) {\n entry.receiveShadow = true;\n }\n\n entry.meshes.push(child);\n dictionary.set(compositeKey, entry);\n }\n });\n\n for (const descriptor of dictionary.values()) {\n if (descriptor.meshes.length < MIN_INSTANCE_COUNT) {\n continue;\n }\n const { meshes, materials, castShadow, receiveShadow } = descriptor;\n\n const sortedMeshes = meshes.sort((a, b) => a.name.localeCompare(b.name));\n const defaultMesh = sortedMeshes[0];\n\n const instancedMesh = new InstancedMesh(\n defaultMesh.geometry,\n materials.length === 1 ? materials[0] : materials,\n sortedMeshes.length,\n );\n\n instancedMesh.name = defaultMesh.name;\n instancedMesh.castShadow = castShadow;\n instancedMesh.receiveShadow = receiveShadow;\n\n for (let i = 0; i < sortedMeshes.length; i++) {\n const mesh = sortedMeshes[i];\n mesh.updateWorldMatrix(true, false);\n instancedMesh.setMatrixAt(i, mesh.matrixWorld);\n instancedMesh.userData[mesh.uuid] = mesh.userData;\n }\n\n instancedMesh.instanceMatrix.needsUpdate = true;\n instances.push(instancedMesh);\n\n for (const mesh of sortedMeshes) {\n mesh.parent?.remove(mesh);\n }\n }\n\n if (instances.length > 0) {\n container.add(...instances);\n }\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { FrontSide, Mesh } from \"three\";\nimport { InstanceAssembler } from \"./InstanceAssembler\";\nimport { SceneTraversal } from \"./SceneTraversal\";\n\n/** Options for scene post-processing */\nexport interface SceneProcessorOptions {\n /** Clone the input asset before processing? */\n cloneAsset: boolean;\n\n /** Combine identical meshes into instances? */\n assembleInstances: boolean;\n\n /** Names matching these patterns will cast shadows */\n castShadowExpressions: RegExp[];\n\n /** Names matching these patterns will receive shadows */\n receiveShadwoExpressions: RegExp[];\n\n /** Names matching these patterns will be transparent */\n transparentMaterialExpressions: RegExp[];\n\n /** Names matching these patterns won't write to depth buffer */\n noDepthWriteMaterialExpressions: RegExp[];\n}\n\n/** Post-processes a scene based on name patterns */\nexport class SceneProcessor {\n /**\n * Process a scene to set up materials and shadows.\n * \n * @param asset - Scene to process\n * @param options - How to process the scene\n * @returns Processed scene root objects\n */\n public static process(\n asset: Object3D,\n options: Partial<SceneProcessorOptions>,\n ): Object3D[] {\n const container = options.cloneAsset !== false ? asset.clone() : asset;\n\n if (options.assembleInstances !== false) {\n InstanceAssembler.assemble(container);\n }\n\n SceneTraversal.enumerateMaterials(container, (material: Material) => {\n material.transparent = SceneProcessor.matchesAny(\n material.name,\n options.transparentMaterialExpressions,\n );\n material.depthWrite = !SceneProcessor.matchesAny(\n material.name,\n options.noDepthWriteMaterialExpressions,\n );\n material.side = FrontSide;\n material.forceSinglePass = true;\n material.depthTest = true;\n });\n\n SceneTraversal.enumerateObjectsByType(container, Mesh, (child: Mesh) => {\n child.castShadow = SceneProcessor.matchesAny(\n child.name,\n options.castShadowExpressions,\n );\n child.receiveShadow = SceneProcessor.matchesAny(\n child.name,\n options.receiveShadwoExpressions,\n );\n });\n\n return container.children;\n }\n\n /** Does the string match any of the patterns? */\n private static matchesAny(\n value: string,\n expressions: RegExp[] = [],\n ): boolean {\n return expressions.some((p) => p.test(value));\n }\n}","import type { AnimationClip, Object3D, SkinnedMesh } from \"three\";\nimport { AnimationMixer, BufferAttribute, Mesh, Vector3 } from \"three\";\n\n/** Number of components per vertex */\nconst COMPONENT_COUNT = 3;\n\n/** Convert skinned meshes to regular static meshes */\nexport class SkinnedMeshBaker {\n /**\n * Convert a skinned mesh to a regular mesh in its current pose.\n * The resulting mesh will have no bones but look identical.\n * \n * @param skinnedMesh - Mesh to convert\n * @returns Static mesh with baked vertex positions\n */\n public static bakePose(skinnedMesh: SkinnedMesh): Mesh {\n const bakedGeometry = skinnedMesh.geometry.clone();\n const position = bakedGeometry.attributes[\"position\"] as BufferAttribute;\n const newPositions = new Float32Array(position.count * COMPONENT_COUNT);\n const target = new Vector3();\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n newPositions[i * COMPONENT_COUNT + 0] = target.x;\n newPositions[i * COMPONENT_COUNT + 1] = target.y;\n newPositions[i * COMPONENT_COUNT + 2] = target.z;\n }\n\n bakedGeometry.setAttribute(\n \"position\",\n new BufferAttribute(newPositions, COMPONENT_COUNT),\n );\n bakedGeometry.computeVertexNormals();\n bakedGeometry.deleteAttribute(\"skinIndex\");\n bakedGeometry.deleteAttribute(\"skinWeight\");\n\n const mesh = new Mesh(bakedGeometry, skinnedMesh.material);\n mesh.name = skinnedMesh.name;\n return mesh;\n }\n\n /**\n * Bake a single frame from an animation into a static mesh.\n * \n * @param armature - Root object with bones (usually from GLTF)\n * @param skinnedMesh - Mesh to convert\n * @param timeOffset - Time in seconds within the animation\n * @param clip - Animation to get the pose from\n * @returns Static mesh with baked vertex positions\n */\n public static bakeAnimationFrame(\n armature: Object3D,\n skinnedMesh: SkinnedMesh,\n timeOffset: number,\n clip: AnimationClip,\n ): Mesh {\n const mixer = new AnimationMixer(armature);\n const action = mixer.clipAction(clip);\n action.play();\n mixer.setTime(timeOffset);\n\n armature.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n return this.bakePose(skinnedMesh);\n }\n}","import type { Texture } from \"three\";\nimport { Box3, DirectionalLight, RGBAFormat, Spherical, Vector3 } from \"three\";\n\nconst RGBA_CHANNEL_COUNT = 4;\nconst RGB_CHANNEL_COUNT = 3;\n\nconst LUMINANCE_R = 0.2126;\nconst LUMINANCE_G = 0.7152;\nconst LUMINANCE_B = 0.0722;\n\n/** A directional light with spherical positioning controls */\nexport class Sun extends DirectionalLight {\n /** Internal vectors to avoid garbage collection */\n private readonly tempVector3D0 = new Vector3();\n private readonly tempVector3D1 = new Vector3();\n private readonly tempVector3D2 = new Vector3();\n private readonly tempVector3D3 = new Vector3();\n private readonly tempVector3D4 = new Vector3();\n private readonly tempVector3D5 = new Vector3();\n private readonly tempVector3D6 = new Vector3();\n private readonly tempVector3D7 = new Vector3();\n private readonly tempBox3 = new Box3();\n private readonly tempSpherical = new Spherical();\n\n /** Distance from the light to its target */\n public get distance(): number {\n return this.position.length();\n }\n\n /** Vertical angle from the ground in radians */\n public get elevation(): number {\n return this.tempSpherical.setFromVector3(this.position).phi;\n }\n\n /** Horizontal angle around the target in radians */\n public get azimuth(): number {\n return this.tempSpherical.setFromVector3(this.position).theta;\n }\n\n /** Set distance while keeping current angles */\n public set distance(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n value,\n this.tempSpherical.phi,\n this.tempSpherical.theta,\n );\n }\n\n /** Set elevation while keeping current distance and azimuth */\n public set elevation(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n this.tempSpherical.radius,\n value,\n this.tempSpherical.theta,\n );\n }\n\n /** Set azimuth while keeping current distance and elevation */\n public set azimuth(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n this.tempSpherical.radius,\n this.tempSpherical.phi,\n value,\n );\n }\n\n /** Configure shadows to cover all corners of a bounding box */\n public setShadowMapFromBox3(box3: Box3): void {\n const camera = this.shadow.camera;\n\n this.target.updateWorldMatrix(true, false);\n this.lookAt(this.target.getWorldPosition(this.tempVector3D0));\n\n this.updateWorldMatrix(true, false);\n\n const points: Vector3[] = [\n this.tempVector3D0.set(box3.min.x, box3.min.y, box3.min.z),\n this.tempVector3D1.set(box3.min.x, box3.min.y, box3.max.z),\n this.tempVector3D2.set(box3.min.x, box3.max.y, box3.min.z),\n this.tempVector3D3.set(box3.min.x, box3.max.y, box3.max.z),\n this.tempVector3D4.set(box3.max.x, box3.min.y, box3.min.z),\n this.tempVector3D5.set(box3.max.x, box3.min.y, box3.max.z),\n this.tempVector3D6.set(box3.max.x, box3.max.y, box3.min.z),\n this.tempVector3D7.set(box3.max.x, box3.max.y, box3.max.z),\n ];\n\n const inverseMatrix = this.matrixWorld.clone().invert();\n\n for (const point of points) {\n point.applyMatrix4(inverseMatrix);\n }\n\n const newBox3 = this.tempBox3.setFromPoints(points);\n\n camera.left = newBox3.min.x;\n camera.bottom = newBox3.min.y;\n camera.near = -newBox3.max.z;\n\n camera.right = newBox3.max.x;\n camera.top = newBox3.max.y;\n camera.far = -newBox3.min.z;\n\n camera.updateWorldMatrix(true, false);\n camera.updateProjectionMatrix();\n }\n\n /** Set light direction based on brightest point in an HDR texture */\n public setDirectionFromHDR(texture: Texture, distance = 1): void {\n const data = texture.image.data;\n const width = texture.image.width;\n const height = texture.image.height;\n\n let maxLuminance = 0;\n let maxIndex = 0;\n\n // Find brightest pixel\n\n const step =\n texture.format === RGBAFormat ? RGBA_CHANNEL_COUNT : RGB_CHANNEL_COUNT;\n for (let i = 0; i < data.length; i += step) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n const luminance = LUMINANCE_R * r + LUMINANCE_G * g + LUMINANCE_B * b;\n if (luminance > maxLuminance) {\n maxLuminance = luminance;\n maxIndex = i;\n }\n }\n\n // Convert to spherical coordinates\n const pixelIndex = maxIndex / step;\n const x = pixelIndex % width;\n const y = Math.floor(pixelIndex / width);\n\n const u = x / width;\n const v = y / height;\n\n const elevation = v * Math.PI;\n const azimuth = u * -Math.PI * 2 - Math.PI / 2;\n\n this.position.setFromSphericalCoords(distance, elevation, azimuth);\n }\n}\n"],"names":["MAX_FOV","BiFovCamera","PerspectiveCamera","constructor","horizontalFov","verticalFov","aspect","near","far","super","this","horizontalFovInternal","verticalFovInternal","updateProjectionMatrix","value","MathUtils","clamp","setFov","horizontal","vertical","copyFovSettings","source","radians","degToRad","fov","radToDeg","Math","atan","tan","getEffectiveHorizontalFov","verticalRadians","getEffectiveVerticalFov","horizontalRadians","clone","camera","copy","Bounds","Box3","object","tempVector3A","Vector3","setFromObject","width","max","x","min","height","y","depth","z","diagonal","subVectors","length","getVolume","getSurfaceArea","w","h","d","GeometryHasher","getGeometryHash","geometry","tolerance","positionArray","attributes","array","positionHashParts","i","push","round","normalHashParts","normalArray","join","SceneTraversal","getObjectByName","name","child","children","result","getMaterialByName","Mesh","Array","isArray","material","enumerateObjectsByType","type","callback","enumerateMaterials","filterObjects","test","concat","filterMaterials","setShadowRecursive","castShadow","receiveShadow","filter","InstanceAssembler","assemble","container","options","dictionary","Map","instances","_a","geometryTolerance","geometryHashes","materials","geometryHash","get","uuid","set","compositeKey","map","m","entry","meshes","descriptor","values","sortedMeshes","sort","a","b","localeCompare","defaultMesh","instancedMesh","InstancedMesh","mesh","updateWorldMatrix","setMatrixAt","matrixWorld","userData","instanceMatrix","needsUpdate","_b","parent","remove","add","SceneProcessor","process","asset","cloneAsset","assembleInstances","transparent","matchesAny","transparentMaterialExpressions","depthWrite","noDepthWriteMaterialExpressions","side","FrontSide","forceSinglePass","depthTest","castShadowExpressions","receiveShadwoExpressions","expressions","some","p","SkinnedMeshBaker","bakePose","skinnedMesh","bakedGeometry","position","newPositions","Float32Array","count","target","fromBufferAttribute","applyBoneTransform","setAttribute","BufferAttribute","computeVertexNormals","deleteAttribute","bakeAnimationFrame","armature","timeOffset","clip","mixer","AnimationMixer","clipAction","play","setTime","skeleton","update","Sun","DirectionalLight","tempVector3D0","tempVector3D1","tempVector3D2","tempVector3D3","tempVector3D4","tempVector3D5","tempVector3D6","tempVector3D7","tempBox3","tempSpherical","Spherical","distance","elevation","setFromVector3","phi","azimuth","theta","setFromSphericalCoords","radius","setShadowMapFromBox3","box3","shadow","lookAt","getWorldPosition","points","inverseMatrix","invert","point","applyMatrix4","newBox3","setFromPoints","left","bottom","right","top","setDirectionFromHDR","texture","data","image","maxLuminance","maxIndex","step","format","RGBAFormat","luminance","pixelIndex","floor","PI"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.min.js","sources":["../src/BiFovCamera.ts","../src/Bounds.ts","../src/GeometryHasher.ts","../src/SceneTraversal.ts","../src/InstanceAssembler.ts","../src/SceneProcessor.ts","../src/SkinnedMeshBaker.ts","../src/Sun.ts"],"sourcesContent":["import type { Box3, BufferAttribute, SkinnedMesh } from \"three\";\nimport { MathUtils, PerspectiveCamera, Vector3 } from \"three\";\n\nconst DEFAULT_HORIZONTAL_FOV = 90;\nconst DEFAULT_VERTICAL_FOV = 90;\nconst DEFAULT_ASPECT = 1;\nconst DEFAULT_NEAR = 1;\nconst DEFAULT_FAR = 1000;\n\nconst MIN_FOV = 1;\nconst MAX_FOV = 179;\n\n/**\n * A camera that supports independent horizontal and vertical FOV settings.\n * Extends Three.js PerspectiveCamera to allow separate control over horizontal\n * and vertical fields of view.\n */\nexport class BiFovCamera extends PerspectiveCamera {\n private horizontalFovInternal: number;\n private verticalFovInternal: number;\n\n /**\n * @param horizontalFov - Horizontal FOV in degrees (90° default)\n * @param verticalFov - Vertical FOV in degrees (90° default)\n * @param aspect - Width/height ratio (1 default)\n * @param near - Near clipping plane (1 default)\n * @param far - Far clipping plane (1000 default)\n */\n constructor(\n horizontalFov = DEFAULT_HORIZONTAL_FOV,\n verticalFov = DEFAULT_VERTICAL_FOV,\n aspect = DEFAULT_ASPECT,\n near = DEFAULT_NEAR,\n far = DEFAULT_FAR,\n ) {\n super(verticalFov, aspect, near, far);\n this.horizontalFovInternal = horizontalFov;\n this.verticalFovInternal = verticalFov;\n this.updateProjectionMatrix();\n }\n\n /** Current horizontal FOV in degrees */\n public get horizontalFov(): number {\n return this.horizontalFovInternal;\n }\n\n /** Current vertical FOV in degrees */\n public get verticalFov(): number {\n return this.verticalFovInternal;\n }\n\n /** Set horizontal FOV in degrees (clamped between 1° and 179°) */\n public set horizontalFov(value: number) {\n this.horizontalFovInternal = MathUtils.clamp(value, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /** Set vertical FOV in degrees (clamped between 1° and 179°) */\n public set verticalFov(value: number) {\n this.verticalFovInternal = MathUtils.clamp(value, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /**\n * Update both horizontal and vertical FOV\n * @param horizontal - Horizontal FOV in degrees\n * @param vertical - Vertical FOV in degrees\n */\n public setFov(horizontal: number, vertical: number): void {\n this.horizontalFovInternal = MathUtils.clamp(horizontal, MIN_FOV, MAX_FOV);\n this.verticalFovInternal = MathUtils.clamp(vertical, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /**\n * Copy FOV settings from another BiFovCamera\n * @param source - Camera to copy from\n */\n public copyFovSettings(source: BiFovCamera): void {\n this.horizontalFovInternal = source.horizontalFov;\n this.verticalFovInternal = source.verticalFov;\n this.updateProjectionMatrix();\n }\n\n /**\n * Updates the projection matrix based on FOV settings and aspect ratio.\n * In landscape: preserves horizontal FOV\n * In portrait: preserves vertical FOV\n */\n public override updateProjectionMatrix(): void {\n if (this.aspect > 1) {\n // Landscape orientation: preserve horizontal FOV\n const radians = MathUtils.degToRad(this.horizontalFovInternal);\n this.fov = MathUtils.radToDeg(\n Math.atan(Math.tan(radians / 2) / this.aspect) * 2,\n );\n } else {\n // Portrait orientation: preserve vertical FOV\n this.fov = this.verticalFovInternal;\n }\n\n super.updateProjectionMatrix();\n }\n\n /** Get actual horizontal FOV after aspect ratio adjustments */\n public getEffectiveHorizontalFov(): number {\n if (this.aspect >= 1) {\n return this.horizontalFovInternal;\n }\n const verticalRadians = MathUtils.degToRad(this.verticalFovInternal);\n return MathUtils.radToDeg(\n Math.atan(Math.tan(verticalRadians / 2) * this.aspect) * 2,\n );\n }\n\n /** Get actual vertical FOV after aspect ratio adjustments */\n public getEffectiveVerticalFov(): number {\n if (this.aspect < 1) {\n return this.verticalFovInternal;\n }\n const horizontalRadians = MathUtils.degToRad(this.horizontalFovInternal);\n return MathUtils.radToDeg(\n Math.atan(Math.tan(horizontalRadians / 2) / this.aspect) * 2,\n );\n }\n\n public fitPointsVerticalFov(vertices: Vector3[]): void {\n const up = new Vector3(0, 1, 0).applyQuaternion(this.quaternion);\n\n let maxVerticalAngle = 0;\n\n for (const vertex of vertices) {\n const vertexToCam = this.position.clone().sub(vertex);\n const vertexDirection = vertexToCam.normalize();\n\n const verticalAngle =\n Math.asin(Math.abs(vertexDirection.dot(up))) *\n Math.sign(vertexDirection.dot(up));\n\n if (Math.abs(verticalAngle) > maxVerticalAngle) {\n maxVerticalAngle = Math.abs(verticalAngle);\n }\n }\n\n const requiredFov = MathUtils.radToDeg(2 * maxVerticalAngle);\n\n this.verticalFovInternal = MathUtils.clamp(requiredFov, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n public fitBoxVerticalFov(box: Box3): void {\n this.fitPointsVerticalFov([\n new Vector3(box.min.x, box.min.y, box.min.z),\n new Vector3(box.min.x, box.min.y, box.max.z),\n new Vector3(box.min.x, box.max.y, box.min.z),\n new Vector3(box.min.x, box.max.y, box.max.z),\n new Vector3(box.max.x, box.min.y, box.min.z),\n new Vector3(box.max.x, box.min.y, box.max.z),\n new Vector3(box.max.x, box.max.y, box.min.z),\n new Vector3(box.max.x, box.max.y, box.max.z),\n ]);\n }\n\n public fitSkinnedMeshVerticalFov(skinnedMesh: SkinnedMesh): void {\n skinnedMesh.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n const bakedGeometry = skinnedMesh.geometry;\n const position = bakedGeometry.attributes[\"position\"] as BufferAttribute;\n const target = new Vector3();\n\n const points = [];\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n points.push(target.clone());\n }\n\n this.fitPointsVerticalFov(points);\n }\n\n public lookAtCenterOfMass(skinnedMesh: SkinnedMesh): void {\n skinnedMesh.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n const bakedGeometry = skinnedMesh.geometry;\n const position = bakedGeometry.attributes.position as BufferAttribute;\n const target = new Vector3();\n const points: Vector3[] = [];\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n points.push(target.clone());\n }\n\n const findMainCluster = (points: Vector3[], iterations = 3): Vector3 => {\n if (points.length === 0) {\n return new Vector3();\n }\n\n let center = points[Math.floor(points.length / 2)].clone();\n\n for (let i = 0; i < iterations; i++) {\n let total = new Vector3();\n let count = 0;\n\n for (const point of points) {\n if (\n point.distanceTo(center) < point.distanceTo(total) ||\n count === 0\n ) {\n total.add(point);\n count++;\n }\n }\n\n if (count > 0) {\n center = total.divideScalar(count);\n }\n }\n\n return center;\n };\n\n const centerOfMass = findMainCluster(points);\n this.lookAt(centerOfMass);\n }\n\n public override clone(): this {\n const camera = new BiFovCamera(\n this.horizontalFovInternal,\n this.verticalFovInternal,\n this.aspect,\n this.near,\n this.far,\n ) as this;\n\n camera.copy(this, true);\n return camera;\n }\n}\n","import type { BufferAttribute, Object3D, SkinnedMesh } from \"three\";\nimport { Box3, Vector3 } from \"three\";\n\n/**\n * Box3 with additional convenience methods for width, height, depth, etc.\n */\nexport class Bounds extends Box3 {\n /** Temporary vector for calculations */\n private readonly tempVector3A: Vector3 = new Vector3();\n\n constructor(object?: Object3D) {\n super();\n if (object) {\n this.setFromObject(object);\n }\n }\n\n /** Width (x-axis length) */\n public get width(): number {\n return this.max.x - this.min.x;\n }\n\n /** Height (y-axis length) */\n public get height(): number {\n return this.max.y - this.min.y;\n }\n\n /** Depth (z-axis length) */\n public get depth(): number {\n return this.max.z - this.min.z;\n }\n\n /** Length of the box's diagonal */\n public get diagonal(): number {\n return this.tempVector3A.subVectors(this.max, this.min).length();\n }\n\n public setFromSkinnedMesh(skinnedMesh: SkinnedMesh): Bounds {\n skinnedMesh.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n const geometry = skinnedMesh.geometry;\n const position = geometry.attributes[\"position\"] as BufferAttribute;\n const target = new Vector3();\n\n const points = [];\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n points.push(target.clone());\n }\n\n this.setFromPoints(points);\n return this;\n }\n\n /** Volume (width * height * depth) */\n public getVolume(): number {\n return this.width * this.height * this.depth;\n }\n\n /** Surface area (sum of all six faces) */\n public getSurfaceArea(): number {\n const w = this.width;\n const h = this.height;\n const d = this.depth;\n return 2 * (w * h + h * d + d * w);\n }\n}\n","import type { BufferGeometry } from \"three\";\n\nconst POSITION_COMPONENT_COUNT = 3;\nconst NORMAL_COMPONENT_COUNT = 3;\n\n/**\n * Internal utility to identify identical geometries.\n * @internal\n */\nexport class GeometryHasher {\n /**\n * Creates a hash for a geometry based on its vertex data.\n * Vertices that differ by less than tolerance are considered the same.\n *\n * @param geometry - Geometry to hash\n * @param tolerance - How close vertices need to be to count as identical\n * @returns Hash string that's the same for matching geometries\n * @internal\n */\n public static getGeometryHash(\n geometry: BufferGeometry,\n tolerance: number,\n ): string {\n const position = geometry.attributes[\"position\"];\n\n const positionArray = position.array;\n const positionHashParts: string[] = [];\n\n // Sample vertex positions with tolerance\n for (let i = 0; i < positionArray.length; i += POSITION_COMPONENT_COUNT) {\n const x = Math.round(positionArray[i] / tolerance);\n const y = Math.round(positionArray[i + 1] / tolerance);\n const z = Math.round(positionArray[i + 2] / tolerance);\n positionHashParts.push(`${x},${y},${z}`);\n }\n\n // Hash normal data if available\n const normal = geometry.attributes[\"normal\"];\n const normalHashParts: string[] = [];\n\n const normalArray = normal.array;\n for (let i = 0; i < normalArray.length; i += NORMAL_COMPONENT_COUNT) {\n const x = Math.round(normalArray[i] / tolerance);\n const y = Math.round(normalArray[i + 1] / tolerance);\n const z = Math.round(normalArray[i + 2] / tolerance);\n normalHashParts.push(`${x},${y},${z}`);\n }\n\n // Combine position and normal hashes\n const positionHash = positionHashParts.join(\"|\");\n const normalHash = normalHashParts.join(\"|\");\n\n return `${positionHash}#${normalHash}`;\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { Mesh } from \"three\";\n\n/** Constructor type for type-safe scene traversal */\nexport type Constructor<T> = abstract new (...args: never[]) => T;\n\n/** Find and modify objects in a Three.js scene */\nexport class SceneTraversal {\n /** Find first object with exact name match */\n public static getObjectByName(\n object: Object3D,\n name: string,\n ): Object3D | null {\n if (object.name === name) {\n return object;\n }\n\n for (const child of object.children) {\n const result = SceneTraversal.getObjectByName(child, name);\n if (result) {\n return result;\n }\n }\n\n return null;\n }\n\n /** Find first material with exact name match */\n public static getMaterialByName(\n object: Object3D,\n name: string,\n ): Material | null {\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n if (material.name === name) {\n return material;\n }\n }\n } else if (object.material.name === name) {\n return object.material;\n }\n }\n\n for (const child of object.children) {\n const material = SceneTraversal.getMaterialByName(child, name);\n if (material) {\n return material;\n }\n }\n\n return null;\n }\n\n /** Process all objects of a specific type */\n public static enumerateObjectsByType<T>(\n object: Object3D,\n type: Constructor<T>,\n callback: (instance: T) => void,\n ): void {\n if (object instanceof type) {\n callback(object);\n }\n\n for (const child of object.children) {\n SceneTraversal.enumerateObjectsByType(child, type, callback);\n }\n }\n\n /** Process all materials in meshes */\n public static enumerateMaterials(\n object: Object3D,\n callback: (material: Material) => void,\n ): void {\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n callback(material);\n }\n } else {\n callback(object.material);\n }\n }\n\n for (const child of object.children) {\n SceneTraversal.enumerateMaterials(child, callback);\n }\n }\n\n /** Find all objects whose names match a pattern */\n public static filterObjects(\n object: Object3D,\n filter: RegExp | ((object: Object3D) => boolean),\n ): Object3D[] {\n let result: Object3D[] = [];\n\n if (typeof filter === \"function\") {\n if (filter(object)) {\n result.push(object);\n }\n } else {\n if (object.name && filter.test(object.name)) {\n result.push(object);\n }\n }\n\n for (const child of object.children) {\n result = result.concat(SceneTraversal.filterObjects(child, filter));\n }\n\n return result;\n }\n\n /** Find all materials whose names match a pattern */\n public static filterMaterials(object: Object3D, name: RegExp): Material[] {\n let result: Material[] = [];\n\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n if (material.name && name.test(material.name)) {\n result.push(material);\n }\n }\n } else {\n if (object.material.name && name.test(object.material.name)) {\n result.push(object.material);\n }\n }\n }\n\n for (const child of object.children) {\n result = result.concat(SceneTraversal.filterMaterials(child, name));\n }\n\n return result;\n }\n\n /** Set shadow properties on meshes */\n public static setShadowRecursive(\n object: Object3D,\n castShadow = true,\n receiveShadow = true,\n filter?: (object: Object3D) => boolean,\n ): void {\n if (object instanceof Mesh || \"isMesh\" in object) {\n (object as Mesh).castShadow = castShadow;\n (object as Mesh).receiveShadow = receiveShadow;\n }\n\n for (const child of object.children) {\n SceneTraversal.setShadowRecursive(\n child,\n castShadow,\n receiveShadow,\n filter,\n );\n }\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { InstancedMesh, Mesh } from \"three\";\nimport { GeometryHasher } from \"./GeometryHasher\";\nimport { SceneTraversal } from \"./SceneTraversal\";\n\nconst MIN_INSTANCE_COUNT = 2;\nconst DEFAULT_TOLERANCE = 1e-6;\n\n/** A group of meshes that can be instanced together */\ninterface MeshDescription {\n /** List of meshes */\n meshes: Mesh[];\n /** Materials to use */\n materials: Material[];\n /** Should cast shadows */\n castShadow: boolean;\n /** Should receive shadows */\n receiveShadow: boolean;\n}\n\n/** Configuration for instance assembly */\nexport interface InstanceAssemblerOptions {\n /** Filter which meshes to include */\n filter: (child: Mesh) => boolean;\n\n /** How close vertices need to be to count as identical */\n geometryTolerance: number;\n}\n\n/**\n * Combines identical meshes into instanced versions for better performance.\n * Meshes are considered identical if they share the same geometry and materials.\n */\nexport class InstanceAssembler {\n /**\n * Find meshes that can be instanced and combine them.\n * Only processes meshes that:\n * - Have no children\n * - Pass the filter function (if any)\n * - Share geometry with at least one other mesh\n *\n * @param container - Object containing meshes to process\n * @param options - Optional settings\n */\n public static assemble(\n container: Object3D,\n options: Partial<InstanceAssemblerOptions> = {},\n ): void {\n const dictionary = new Map<string, MeshDescription>();\n const instances: InstancedMesh[] = [];\n\n const tolerance = options.geometryTolerance ?? DEFAULT_TOLERANCE;\n const geometryHashes = new Map<string, string>();\n\n SceneTraversal.enumerateObjectsByType(container, Mesh, (child: Mesh) => {\n if (\n child.children.length === 0 &&\n (!options.filter || options.filter(child))\n ) {\n const materials = Array.isArray(child.material)\n ? child.material\n : [child.material];\n\n let geometryHash = geometryHashes.get(child.geometry.uuid);\n if (!geometryHash) {\n geometryHash = GeometryHasher.getGeometryHash(\n child.geometry,\n tolerance,\n );\n geometryHashes.set(child.geometry.uuid, geometryHash);\n }\n\n const materialKey = materials.map((m) => m.uuid).join(\",\");\n const compositeKey = `${geometryHash}|${materialKey}`;\n\n const entry = dictionary.get(compositeKey) ?? {\n meshes: [],\n materials,\n castShadow: false,\n receiveShadow: false,\n };\n\n if (child.castShadow) {\n entry.castShadow = true;\n }\n\n if (child.receiveShadow) {\n entry.receiveShadow = true;\n }\n\n entry.meshes.push(child);\n dictionary.set(compositeKey, entry);\n }\n });\n\n for (const descriptor of dictionary.values()) {\n if (descriptor.meshes.length < MIN_INSTANCE_COUNT) {\n continue;\n }\n const { meshes, materials, castShadow, receiveShadow } = descriptor;\n\n const sortedMeshes = meshes.sort((a, b) => a.name.localeCompare(b.name));\n const defaultMesh = sortedMeshes[0];\n\n const instancedMesh = new InstancedMesh(\n defaultMesh.geometry,\n materials.length === 1 ? materials[0] : materials,\n sortedMeshes.length,\n );\n\n instancedMesh.name = defaultMesh.name;\n instancedMesh.castShadow = castShadow;\n instancedMesh.receiveShadow = receiveShadow;\n\n for (let i = 0; i < sortedMeshes.length; i++) {\n const mesh = sortedMeshes[i];\n mesh.updateWorldMatrix(true, false);\n instancedMesh.setMatrixAt(i, mesh.matrixWorld);\n instancedMesh.userData[mesh.uuid] = mesh.userData;\n }\n\n instancedMesh.instanceMatrix.needsUpdate = true;\n instances.push(instancedMesh);\n\n for (const mesh of sortedMeshes) {\n mesh.parent?.remove(mesh);\n }\n }\n\n if (instances.length > 0) {\n container.add(...instances);\n }\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { FrontSide, Mesh } from \"three\";\nimport { InstanceAssembler } from \"./InstanceAssembler\";\nimport { SceneTraversal } from \"./SceneTraversal\";\n\n/** Options for scene post-processing */\nexport interface SceneProcessorOptions {\n /** Clone the input asset before processing? */\n cloneAsset: boolean;\n\n /** Combine identical meshes into instances? */\n assembleInstances: boolean;\n\n /** Names matching these patterns will cast shadows */\n castShadowExpressions: RegExp[];\n\n /** Names matching these patterns will receive shadows */\n receiveShadwoExpressions: RegExp[];\n\n /** Names matching these patterns will be transparent */\n transparentMaterialExpressions: RegExp[];\n\n /** Names matching these patterns won't write to depth buffer */\n noDepthWriteMaterialExpressions: RegExp[];\n}\n\n/** Post-processes a scene based on name patterns */\nexport class SceneProcessor {\n /**\n * Process a scene to set up materials and shadows.\n * \n * @param asset - Scene to process\n * @param options - How to process the scene\n * @returns Processed scene root objects\n */\n public static process(\n asset: Object3D,\n options: Partial<SceneProcessorOptions>,\n ): Object3D[] {\n const container = options.cloneAsset !== false ? asset.clone() : asset;\n\n if (options.assembleInstances !== false) {\n InstanceAssembler.assemble(container);\n }\n\n SceneTraversal.enumerateMaterials(container, (material: Material) => {\n material.transparent = SceneProcessor.matchesAny(\n material.name,\n options.transparentMaterialExpressions,\n );\n material.depthWrite = !SceneProcessor.matchesAny(\n material.name,\n options.noDepthWriteMaterialExpressions,\n );\n material.side = FrontSide;\n material.forceSinglePass = true;\n material.depthTest = true;\n });\n\n SceneTraversal.enumerateObjectsByType(container, Mesh, (child: Mesh) => {\n child.castShadow = SceneProcessor.matchesAny(\n child.name,\n options.castShadowExpressions,\n );\n child.receiveShadow = SceneProcessor.matchesAny(\n child.name,\n options.receiveShadwoExpressions,\n );\n });\n\n return container.children;\n }\n\n /** Does the string match any of the patterns? */\n private static matchesAny(\n value: string,\n expressions: RegExp[] = [],\n ): boolean {\n return expressions.some((p) => p.test(value));\n }\n}","import type { AnimationClip, Object3D, SkinnedMesh } from \"three\";\nimport { AnimationMixer, BufferAttribute, Mesh, Vector3 } from \"three\";\n\n/** Number of components per vertex */\nconst COMPONENT_COUNT = 3;\n\n/** Convert skinned meshes to regular static meshes */\nexport class SkinnedMeshBaker {\n /**\n * Convert a skinned mesh to a regular mesh in its current pose.\n * The resulting mesh will have no bones but look identical.\n * \n * @param skinnedMesh - Mesh to convert\n * @returns Static mesh with baked vertex positions\n */\n public static bakePose(skinnedMesh: SkinnedMesh): Mesh {\n const bakedGeometry = skinnedMesh.geometry.clone();\n const position = bakedGeometry.attributes[\"position\"] as BufferAttribute;\n const newPositions = new Float32Array(position.count * COMPONENT_COUNT);\n const target = new Vector3();\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n newPositions[i * COMPONENT_COUNT + 0] = target.x;\n newPositions[i * COMPONENT_COUNT + 1] = target.y;\n newPositions[i * COMPONENT_COUNT + 2] = target.z;\n }\n\n bakedGeometry.setAttribute(\n \"position\",\n new BufferAttribute(newPositions, COMPONENT_COUNT),\n );\n bakedGeometry.computeVertexNormals();\n bakedGeometry.deleteAttribute(\"skinIndex\");\n bakedGeometry.deleteAttribute(\"skinWeight\");\n\n const mesh = new Mesh(bakedGeometry, skinnedMesh.material);\n mesh.name = skinnedMesh.name;\n return mesh;\n }\n\n /**\n * Bake a single frame from an animation into a static mesh.\n * \n * @param armature - Root object with bones (usually from GLTF)\n * @param skinnedMesh - Mesh to convert\n * @param timeOffset - Time in seconds within the animation\n * @param clip - Animation to get the pose from\n * @returns Static mesh with baked vertex positions\n */\n public static bakeAnimationFrame(\n armature: Object3D,\n skinnedMesh: SkinnedMesh,\n timeOffset: number,\n clip: AnimationClip,\n ): Mesh {\n const mixer = new AnimationMixer(armature);\n const action = mixer.clipAction(clip);\n action.play();\n mixer.setTime(timeOffset);\n\n armature.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n return this.bakePose(skinnedMesh);\n }\n}","import type { Texture } from \"three\";\nimport { Box3, DirectionalLight, RGBAFormat, Spherical, Vector3 } from \"three\";\n\nconst RGBA_CHANNEL_COUNT = 4;\nconst RGB_CHANNEL_COUNT = 3;\n\nconst LUMINANCE_R = 0.2126;\nconst LUMINANCE_G = 0.7152;\nconst LUMINANCE_B = 0.0722;\n\n/** A directional light with spherical positioning controls */\nexport class Sun extends DirectionalLight {\n /** Internal vectors to avoid garbage collection */\n private readonly tempVector3D0 = new Vector3();\n private readonly tempVector3D1 = new Vector3();\n private readonly tempVector3D2 = new Vector3();\n private readonly tempVector3D3 = new Vector3();\n private readonly tempVector3D4 = new Vector3();\n private readonly tempVector3D5 = new Vector3();\n private readonly tempVector3D6 = new Vector3();\n private readonly tempVector3D7 = new Vector3();\n private readonly tempBox3 = new Box3();\n private readonly tempSpherical = new Spherical();\n\n /** Distance from the light to its target */\n public get distance(): number {\n return this.position.length();\n }\n\n /** Vertical angle from the ground in radians */\n public get elevation(): number {\n return this.tempSpherical.setFromVector3(this.position).phi;\n }\n\n /** Horizontal angle around the target in radians */\n public get azimuth(): number {\n return this.tempSpherical.setFromVector3(this.position).theta;\n }\n\n /** Set distance while keeping current angles */\n public set distance(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n value,\n this.tempSpherical.phi,\n this.tempSpherical.theta,\n );\n }\n\n /** Set elevation while keeping current distance and azimuth */\n public set elevation(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n this.tempSpherical.radius,\n value,\n this.tempSpherical.theta,\n );\n }\n\n /** Set azimuth while keeping current distance and elevation */\n public set azimuth(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n this.tempSpherical.radius,\n this.tempSpherical.phi,\n value,\n );\n }\n\n /** Configure shadows to cover all corners of a bounding box */\n public setShadowMapFromBox3(box3: Box3): void {\n const camera = this.shadow.camera;\n\n this.target.updateWorldMatrix(true, false);\n this.lookAt(this.target.getWorldPosition(this.tempVector3D0));\n\n this.updateWorldMatrix(true, false);\n\n const points: Vector3[] = [\n this.tempVector3D0.set(box3.min.x, box3.min.y, box3.min.z),\n this.tempVector3D1.set(box3.min.x, box3.min.y, box3.max.z),\n this.tempVector3D2.set(box3.min.x, box3.max.y, box3.min.z),\n this.tempVector3D3.set(box3.min.x, box3.max.y, box3.max.z),\n this.tempVector3D4.set(box3.max.x, box3.min.y, box3.min.z),\n this.tempVector3D5.set(box3.max.x, box3.min.y, box3.max.z),\n this.tempVector3D6.set(box3.max.x, box3.max.y, box3.min.z),\n this.tempVector3D7.set(box3.max.x, box3.max.y, box3.max.z),\n ];\n\n const inverseMatrix = this.matrixWorld.clone().invert();\n\n for (const point of points) {\n point.applyMatrix4(inverseMatrix);\n }\n\n const newBox3 = this.tempBox3.setFromPoints(points);\n\n camera.left = newBox3.min.x;\n camera.bottom = newBox3.min.y;\n camera.near = -newBox3.max.z;\n\n camera.right = newBox3.max.x;\n camera.top = newBox3.max.y;\n camera.far = -newBox3.min.z;\n\n camera.updateWorldMatrix(true, false);\n camera.updateProjectionMatrix();\n }\n\n /** Set light direction based on brightest point in an HDR texture */\n public setDirectionFromHDR(texture: Texture, distance = 1): void {\n const data = texture.image.data;\n const width = texture.image.width;\n const height = texture.image.height;\n\n let maxLuminance = 0;\n let maxIndex = 0;\n\n // Find brightest pixel\n\n const step =\n texture.format === RGBAFormat ? RGBA_CHANNEL_COUNT : RGB_CHANNEL_COUNT;\n for (let i = 0; i < data.length; i += step) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n const luminance = LUMINANCE_R * r + LUMINANCE_G * g + LUMINANCE_B * b;\n if (luminance > maxLuminance) {\n maxLuminance = luminance;\n maxIndex = i;\n }\n }\n\n // Convert to spherical coordinates\n const pixelIndex = maxIndex / step;\n const x = pixelIndex % width;\n const y = Math.floor(pixelIndex / width);\n\n const u = x / width;\n const v = y / height;\n\n const elevation = v * Math.PI;\n const azimuth = u * -Math.PI * 2 - Math.PI / 2;\n\n this.position.setFromSphericalCoords(distance, elevation, azimuth);\n }\n}\n"],"names":["MAX_FOV","BiFovCamera","PerspectiveCamera","constructor","horizontalFov","verticalFov","aspect","near","far","super","this","horizontalFovInternal","verticalFovInternal","updateProjectionMatrix","value","MathUtils","clamp","setFov","horizontal","vertical","copyFovSettings","source","radians","degToRad","fov","radToDeg","Math","atan","tan","getEffectiveHorizontalFov","verticalRadians","getEffectiveVerticalFov","horizontalRadians","fitPointsVerticalFov","vertices","up","Vector3","applyQuaternion","quaternion","maxVerticalAngle","vertex","vertexDirection","position","clone","sub","normalize","verticalAngle","asin","abs","dot","sign","requiredFov","fitBoxVerticalFov","box","min","x","y","z","max","fitSkinnedMeshVerticalFov","skinnedMesh","updateWorldMatrix","skeleton","update","geometry","attributes","target","points","i","count","fromBufferAttribute","applyBoneTransform","push","lookAtCenterOfMass","centerOfMass","iterations","length","center","floor","total","point","distanceTo","add","divideScalar","findMainCluster","lookAt","camera","copy","Bounds","Box3","object","tempVector3A","setFromObject","width","height","depth","diagonal","subVectors","setFromSkinnedMesh","setFromPoints","getVolume","getSurfaceArea","w","h","d","GeometryHasher","getGeometryHash","tolerance","positionArray","array","positionHashParts","round","normalHashParts","normalArray","join","SceneTraversal","getObjectByName","name","child","children","result","getMaterialByName","Mesh","Array","isArray","material","enumerateObjectsByType","type","callback","enumerateMaterials","filterObjects","filter","test","concat","filterMaterials","setShadowRecursive","castShadow","receiveShadow","InstanceAssembler","assemble","container","options","dictionary","Map","instances","_a","geometryTolerance","geometryHashes","materials","geometryHash","get","uuid","set","compositeKey","map","m","entry","meshes","descriptor","values","sortedMeshes","sort","a","b","localeCompare","defaultMesh","instancedMesh","InstancedMesh","mesh","setMatrixAt","matrixWorld","userData","instanceMatrix","needsUpdate","_b","parent","remove","SceneProcessor","process","asset","cloneAsset","assembleInstances","transparent","matchesAny","transparentMaterialExpressions","depthWrite","noDepthWriteMaterialExpressions","side","FrontSide","forceSinglePass","depthTest","castShadowExpressions","receiveShadwoExpressions","expressions","some","p","SkinnedMeshBaker","bakePose","bakedGeometry","newPositions","Float32Array","setAttribute","BufferAttribute","computeVertexNormals","deleteAttribute","bakeAnimationFrame","armature","timeOffset","clip","mixer","AnimationMixer","clipAction","play","setTime","Sun","DirectionalLight","tempVector3D0","tempVector3D1","tempVector3D2","tempVector3D3","tempVector3D4","tempVector3D5","tempVector3D6","tempVector3D7","tempBox3","tempSpherical","Spherical","distance","elevation","setFromVector3","phi","azimuth","theta","setFromSphericalCoords","radius","setShadowMapFromBox3","box3","shadow","getWorldPosition","inverseMatrix","invert","applyMatrix4","newBox3","left","bottom","right","top","setDirectionFromHDR","texture","data","image","maxLuminance","maxIndex","step","format","RGBAFormat","luminance","pixelIndex","PI"],"mappings":"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"}
|