three-zoo 0.4.0 → 0.4.2
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 +71 -0
- package/dist/Bounds.d.ts +21 -1
- package/dist/{GeometryComparator.d.ts → GeometryHasher.d.ts} +2 -2
- package/dist/InstanceAssembler.d.ts +2 -1
- package/dist/SceneProcessor.d.ts +1 -1
- package/dist/{Enumerator.d.ts → SceneTraversal.d.ts} +2 -2
- package/dist/SkinnedMeshBaker.d.ts +2 -1
- package/dist/Sun.d.ts +61 -11
- package/dist/index.d.ts +2 -1
- package/dist/index.js +303 -189
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +2 -0
- package/dist/index.min.js.map +1 -0
- package/package.json +12 -4
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { PerspectiveCamera } from "three";
|
|
2
|
+
/**
|
|
3
|
+
* BiFovCamera - A specialized PerspectiveCamera that supports independent horizontal and vertical FOV settings
|
|
4
|
+
*
|
|
5
|
+
* This camera extends Three.js PerspectiveCamera to provide better control over the field of view,
|
|
6
|
+
* allowing separate horizontal and vertical FOV values. The camera automatically adjusts its projection
|
|
7
|
+
* matrix based on the aspect ratio to maintain proper perspective.
|
|
8
|
+
*
|
|
9
|
+
* @extends PerspectiveCamera
|
|
10
|
+
*/
|
|
11
|
+
export declare class BiFovCamera extends PerspectiveCamera {
|
|
12
|
+
private horizontalFovInternal;
|
|
13
|
+
private verticalFovInternal;
|
|
14
|
+
/**
|
|
15
|
+
* Creates a new BiFovCamera instance
|
|
16
|
+
*
|
|
17
|
+
* @param horizontalFov - Horizontal field of view in degrees (default: 90)
|
|
18
|
+
* @param verticalFov - Vertical field of view in degrees (default: 90)
|
|
19
|
+
* @param aspect - Aspect ratio (width/height) of the viewport (default: 1)
|
|
20
|
+
* @param near - Near clipping plane distance (default: 1)
|
|
21
|
+
* @param far - Far clipping plane distance (default: 1000)
|
|
22
|
+
*/
|
|
23
|
+
constructor(horizontalFov?: number, verticalFov?: number, aspect?: number, near?: number, far?: number);
|
|
24
|
+
/**
|
|
25
|
+
* Gets the horizontal field of view in degrees
|
|
26
|
+
*/
|
|
27
|
+
get horizontalFov(): number;
|
|
28
|
+
/**
|
|
29
|
+
* Gets the vertical field of view in degrees
|
|
30
|
+
*/
|
|
31
|
+
get verticalFov(): number;
|
|
32
|
+
/**
|
|
33
|
+
* Sets the horizontal field of view in degrees
|
|
34
|
+
* @param value - The new horizontal FOV value
|
|
35
|
+
*/
|
|
36
|
+
set horizontalFov(value: number);
|
|
37
|
+
/**
|
|
38
|
+
* Sets the vertical field of view in degrees
|
|
39
|
+
* @param value - The new vertical FOV value
|
|
40
|
+
*/
|
|
41
|
+
set verticalFov(value: number);
|
|
42
|
+
/**
|
|
43
|
+
* Updates both horizontal and vertical FOV simultaneously
|
|
44
|
+
* @param horizontal - New horizontal FOV in degrees
|
|
45
|
+
* @param vertical - New vertical FOV in degrees
|
|
46
|
+
*/
|
|
47
|
+
setFov(horizontal: number, vertical: number): void;
|
|
48
|
+
/**
|
|
49
|
+
* Copies FOV settings from another BiFovCamera
|
|
50
|
+
* @param source - The camera to copy settings from
|
|
51
|
+
*/
|
|
52
|
+
copyFovSettings(source: BiFovCamera): void;
|
|
53
|
+
/**
|
|
54
|
+
* Updates the projection matrix based on current FOV settings and aspect ratio
|
|
55
|
+
* For aspect ratios >= 1 (landscape), horizontal FOV is preserved
|
|
56
|
+
* For aspect ratios < 1 (portrait), vertical FOV is preserved
|
|
57
|
+
*/
|
|
58
|
+
updateProjectionMatrix(): void;
|
|
59
|
+
/**
|
|
60
|
+
* Returns the actual horizontal FOV after aspect ratio adjustments
|
|
61
|
+
*/
|
|
62
|
+
getEffectiveHorizontalFov(): number;
|
|
63
|
+
/**
|
|
64
|
+
* Returns the actual vertical FOV after aspect ratio adjustments
|
|
65
|
+
*/
|
|
66
|
+
getEffectiveVerticalFov(): number;
|
|
67
|
+
/**
|
|
68
|
+
* Creates a clone of this camera with the same properties
|
|
69
|
+
*/
|
|
70
|
+
clone(): this;
|
|
71
|
+
}
|
package/dist/Bounds.d.ts
CHANGED
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
import { Box3 } from "three";
|
|
2
2
|
export declare class Bounds extends Box3 {
|
|
3
|
-
private readonly
|
|
3
|
+
private readonly tempVector3A;
|
|
4
|
+
/**
|
|
5
|
+
* Gets the width (x-axis length) of the bounding box
|
|
6
|
+
*/
|
|
4
7
|
get width(): number;
|
|
8
|
+
/**
|
|
9
|
+
* Gets the height (y-axis length) of the bounding box
|
|
10
|
+
*/
|
|
5
11
|
get height(): number;
|
|
12
|
+
/**
|
|
13
|
+
* Gets the depth (z-axis length) of the bounding box
|
|
14
|
+
*/
|
|
6
15
|
get depth(): number;
|
|
16
|
+
/**
|
|
17
|
+
* Gets the length of the box's diagonal
|
|
18
|
+
*/
|
|
7
19
|
get diagonal(): number;
|
|
20
|
+
/**
|
|
21
|
+
* Gets the volume of the bounding box
|
|
22
|
+
*/
|
|
23
|
+
getVolume(): number;
|
|
24
|
+
/**
|
|
25
|
+
* Gets the surface area of the bounding box
|
|
26
|
+
*/
|
|
27
|
+
getSurfaceArea(): number;
|
|
8
28
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { BufferGeometry } from "three";
|
|
1
|
+
import type { BufferGeometry } from "three";
|
|
2
2
|
/**
|
|
3
3
|
* Utility class for comparing and hashing BufferGeometry instances with tolerance support.
|
|
4
4
|
*/
|
|
5
|
-
export declare class
|
|
5
|
+
export declare class GeometryHasher {
|
|
6
6
|
/**
|
|
7
7
|
* Generates a consistent hash for a BufferGeometry based on its contents and tolerance.
|
|
8
8
|
*
|
package/dist/SceneProcessor.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Material, Object3D } from "three";
|
|
1
|
+
import type { Material, Object3D } from "three";
|
|
2
2
|
type Constructor<T> = abstract new (...args: never[]) => T;
|
|
3
|
-
export declare class
|
|
3
|
+
export declare class SceneTraversal {
|
|
4
4
|
static getObjectByName(object: Object3D, name: string): Object3D | null;
|
|
5
5
|
static getMaterialByName(object: Object3D, name: string): Material | null;
|
|
6
6
|
static enumerateObjectsByType<T>(object: Object3D, type: Constructor<T>, callback: (instance: T) => void): void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { AnimationClip,
|
|
1
|
+
import type { AnimationClip, Object3D, SkinnedMesh } from "three";
|
|
2
|
+
import { Mesh } from "three";
|
|
2
3
|
/**
|
|
3
4
|
* Utilities for baking poses and animations from SkinnedMesh into a regular static Mesh.
|
|
4
5
|
*/
|
package/dist/Sun.d.ts
CHANGED
|
@@ -1,21 +1,71 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Texture } from "three";
|
|
2
|
+
import { Box3, DirectionalLight } from "three";
|
|
3
|
+
/**
|
|
4
|
+
* Sun extends Three.js DirectionalLight to provide a specialized light source that simulates
|
|
5
|
+
* sunlight with advanced positioning and shadow controls.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Spherical coordinate control (distance, elevation, azimuth)
|
|
9
|
+
* - Automatic shadow map configuration based on bounding boxes
|
|
10
|
+
* - HDR environment map-based positioning
|
|
11
|
+
* - Efficient temporary vector management for calculations
|
|
12
|
+
*
|
|
13
|
+
* @extends DirectionalLight
|
|
14
|
+
*/
|
|
2
15
|
export declare class Sun extends DirectionalLight {
|
|
3
|
-
private tempVector3D0;
|
|
4
|
-
private tempVector3D1;
|
|
5
|
-
private tempVector3D2;
|
|
6
|
-
private tempVector3D3;
|
|
7
|
-
private tempVector3D4;
|
|
8
|
-
private tempVector3D5;
|
|
9
|
-
private tempVector3D6;
|
|
10
|
-
private tempVector3D7;
|
|
11
|
-
private tempBox3;
|
|
12
|
-
private tempSpherical;
|
|
16
|
+
private readonly tempVector3D0;
|
|
17
|
+
private readonly tempVector3D1;
|
|
18
|
+
private readonly tempVector3D2;
|
|
19
|
+
private readonly tempVector3D3;
|
|
20
|
+
private readonly tempVector3D4;
|
|
21
|
+
private readonly tempVector3D5;
|
|
22
|
+
private readonly tempVector3D6;
|
|
23
|
+
private readonly tempVector3D7;
|
|
24
|
+
private readonly tempBox3;
|
|
25
|
+
private readonly tempSpherical;
|
|
26
|
+
/**
|
|
27
|
+
* Gets the distance of the sun from its target (radius in spherical coordinates)
|
|
28
|
+
* @returns The distance in world units
|
|
29
|
+
*/
|
|
13
30
|
get distance(): number;
|
|
31
|
+
/**
|
|
32
|
+
* Gets the elevation angle of the sun (phi in spherical coordinates)
|
|
33
|
+
* @returns The elevation in radians
|
|
34
|
+
*/
|
|
14
35
|
get elevation(): number;
|
|
36
|
+
/**
|
|
37
|
+
* Gets the azimuth angle of the sun (theta in spherical coordinates)
|
|
38
|
+
* @returns The azimuth in radians
|
|
39
|
+
*/
|
|
15
40
|
get azimuth(): number;
|
|
41
|
+
/**
|
|
42
|
+
* Sets the distance of the sun from its target while maintaining current angles
|
|
43
|
+
* @param value - The new distance in world units
|
|
44
|
+
*/
|
|
16
45
|
set distance(value: number);
|
|
46
|
+
/**
|
|
47
|
+
* Sets the elevation angle of the sun while maintaining current distance and azimuth
|
|
48
|
+
* @param value - The new elevation in radians
|
|
49
|
+
*/
|
|
17
50
|
set elevation(value: number);
|
|
51
|
+
/**
|
|
52
|
+
* Sets the azimuth angle of the sun while maintaining current distance and elevation
|
|
53
|
+
* @param value - The new azimuth in radians
|
|
54
|
+
*/
|
|
18
55
|
set azimuth(value: number);
|
|
56
|
+
/**
|
|
57
|
+
* Configures the shadow camera's frustum to encompass the given bounding box
|
|
58
|
+
* This ensures that shadows are cast correctly for objects within the box
|
|
59
|
+
*
|
|
60
|
+
* @param box3 - The bounding box to configure shadows for
|
|
61
|
+
*/
|
|
19
62
|
setShadowMapFromBox3(box3: Box3): void;
|
|
63
|
+
/**
|
|
64
|
+
* Sets the sun's direction based on the brightest point in an HDR texture
|
|
65
|
+
* This is useful for matching the sun's position to an environment map
|
|
66
|
+
*
|
|
67
|
+
* @param texture - The HDR texture to analyze (must be loaded and have valid image data)
|
|
68
|
+
* @param distance - Optional distance to position the sun from its target (default: 1)
|
|
69
|
+
*/
|
|
20
70
|
setDirectionFromHDR(texture: Texture, distance?: number): void;
|
|
21
71
|
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,33 +1,254 @@
|
|
|
1
|
-
import { Box3, Vector3, Mesh, InstancedMesh, FrontSide, BufferAttribute, AnimationMixer, DirectionalLight, Spherical, RGBAFormat } from 'three';
|
|
1
|
+
import { PerspectiveCamera, MathUtils, Box3, Vector3, Mesh, InstancedMesh, FrontSide, BufferAttribute, AnimationMixer, DirectionalLight, Spherical, RGBAFormat } from 'three';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Default camera settings
|
|
5
|
+
*/
|
|
6
|
+
const DEFAULT_HORIZONTAL_FOV = 90;
|
|
7
|
+
const DEFAULT_VERTICAL_FOV = 90;
|
|
8
|
+
const DEFAULT_ASPECT = 1;
|
|
9
|
+
const DEFAULT_NEAR = 1;
|
|
10
|
+
const DEFAULT_FAR = 1000;
|
|
11
|
+
/**
|
|
12
|
+
* BiFovCamera - A specialized PerspectiveCamera that supports independent horizontal and vertical FOV settings
|
|
13
|
+
*
|
|
14
|
+
* This camera extends Three.js PerspectiveCamera to provide better control over the field of view,
|
|
15
|
+
* allowing separate horizontal and vertical FOV values. The camera automatically adjusts its projection
|
|
16
|
+
* matrix based on the aspect ratio to maintain proper perspective.
|
|
17
|
+
*
|
|
18
|
+
* @extends PerspectiveCamera
|
|
19
|
+
*/
|
|
20
|
+
class BiFovCamera extends PerspectiveCamera {
|
|
21
|
+
/**
|
|
22
|
+
* Creates a new BiFovCamera instance
|
|
23
|
+
*
|
|
24
|
+
* @param horizontalFov - Horizontal field of view in degrees (default: 90)
|
|
25
|
+
* @param verticalFov - Vertical field of view in degrees (default: 90)
|
|
26
|
+
* @param aspect - Aspect ratio (width/height) of the viewport (default: 1)
|
|
27
|
+
* @param near - Near clipping plane distance (default: 1)
|
|
28
|
+
* @param far - Far clipping plane distance (default: 1000)
|
|
29
|
+
*/
|
|
30
|
+
constructor(horizontalFov = DEFAULT_HORIZONTAL_FOV, verticalFov = DEFAULT_VERTICAL_FOV, aspect = DEFAULT_ASPECT, near = DEFAULT_NEAR, far = DEFAULT_FAR) {
|
|
31
|
+
super(verticalFov, aspect, near, far);
|
|
32
|
+
this.horizontalFovInternal = horizontalFov;
|
|
33
|
+
this.verticalFovInternal = verticalFov;
|
|
34
|
+
this.updateProjectionMatrix();
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Gets the horizontal field of view in degrees
|
|
38
|
+
*/
|
|
39
|
+
get horizontalFov() {
|
|
40
|
+
return this.horizontalFovInternal;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Gets the vertical field of view in degrees
|
|
44
|
+
*/
|
|
45
|
+
get verticalFov() {
|
|
46
|
+
return this.verticalFovInternal;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Sets the horizontal field of view in degrees
|
|
50
|
+
* @param value - The new horizontal FOV value
|
|
51
|
+
*/
|
|
52
|
+
set horizontalFov(value) {
|
|
53
|
+
this.horizontalFovInternal = MathUtils.clamp(value, 1, 179);
|
|
54
|
+
this.updateProjectionMatrix();
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Sets the vertical field of view in degrees
|
|
58
|
+
* @param value - The new vertical FOV value
|
|
59
|
+
*/
|
|
60
|
+
set verticalFov(value) {
|
|
61
|
+
this.verticalFovInternal = MathUtils.clamp(value, 1, 179);
|
|
62
|
+
this.updateProjectionMatrix();
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Updates both horizontal and vertical FOV simultaneously
|
|
66
|
+
* @param horizontal - New horizontal FOV in degrees
|
|
67
|
+
* @param vertical - New vertical FOV in degrees
|
|
68
|
+
*/
|
|
69
|
+
setFov(horizontal, vertical) {
|
|
70
|
+
this.horizontalFovInternal = MathUtils.clamp(horizontal, 1, 179);
|
|
71
|
+
this.verticalFovInternal = MathUtils.clamp(vertical, 1, 179);
|
|
72
|
+
this.updateProjectionMatrix();
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Copies FOV settings from another BiFovCamera
|
|
76
|
+
* @param source - The camera to copy settings from
|
|
77
|
+
*/
|
|
78
|
+
copyFovSettings(source) {
|
|
79
|
+
this.horizontalFovInternal = source.horizontalFov;
|
|
80
|
+
this.verticalFovInternal = source.verticalFov;
|
|
81
|
+
this.updateProjectionMatrix();
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Updates the projection matrix based on current FOV settings and aspect ratio
|
|
85
|
+
* For aspect ratios >= 1 (landscape), horizontal FOV is preserved
|
|
86
|
+
* For aspect ratios < 1 (portrait), vertical FOV is preserved
|
|
87
|
+
*/
|
|
88
|
+
updateProjectionMatrix() {
|
|
89
|
+
if (this.aspect >= 1) {
|
|
90
|
+
// Landscape orientation: preserve horizontal FOV
|
|
91
|
+
const radians = MathUtils.degToRad(this.horizontalFovInternal);
|
|
92
|
+
this.fov = MathUtils.radToDeg(Math.atan(Math.tan(radians / 2) / this.aspect) * 2);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// Portrait orientation: preserve vertical FOV
|
|
96
|
+
this.fov = this.verticalFovInternal;
|
|
97
|
+
}
|
|
98
|
+
super.updateProjectionMatrix();
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Returns the actual horizontal FOV after aspect ratio adjustments
|
|
102
|
+
*/
|
|
103
|
+
getEffectiveHorizontalFov() {
|
|
104
|
+
if (this.aspect >= 1) {
|
|
105
|
+
return this.horizontalFovInternal;
|
|
106
|
+
}
|
|
107
|
+
const verticalRadians = MathUtils.degToRad(this.verticalFovInternal);
|
|
108
|
+
return MathUtils.radToDeg(Math.atan(Math.tan(verticalRadians / 2) * this.aspect) * 2);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Returns the actual vertical FOV after aspect ratio adjustments
|
|
112
|
+
*/
|
|
113
|
+
getEffectiveVerticalFov() {
|
|
114
|
+
if (this.aspect < 1) {
|
|
115
|
+
return this.verticalFovInternal;
|
|
116
|
+
}
|
|
117
|
+
const horizontalRadians = MathUtils.degToRad(this.horizontalFovInternal);
|
|
118
|
+
return MathUtils.radToDeg(Math.atan(Math.tan(horizontalRadians / 2) / this.aspect) * 2);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Creates a clone of this camera with the same properties
|
|
122
|
+
*/
|
|
123
|
+
clone() {
|
|
124
|
+
const camera = new BiFovCamera(this.horizontalFovInternal, this.verticalFovInternal, this.aspect, this.near, this.far);
|
|
125
|
+
camera.copy(this, true);
|
|
126
|
+
return camera;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
2
129
|
|
|
3
130
|
class Bounds extends Box3 {
|
|
4
131
|
constructor() {
|
|
5
132
|
super(...arguments);
|
|
6
|
-
this.
|
|
133
|
+
this.tempVector3A = new Vector3();
|
|
7
134
|
}
|
|
135
|
+
/**
|
|
136
|
+
* Gets the width (x-axis length) of the bounding box
|
|
137
|
+
*/
|
|
8
138
|
get width() {
|
|
9
139
|
return this.max.x - this.min.x;
|
|
10
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Gets the height (y-axis length) of the bounding box
|
|
143
|
+
*/
|
|
11
144
|
get height() {
|
|
12
145
|
return this.max.y - this.min.y;
|
|
13
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* Gets the depth (z-axis length) of the bounding box
|
|
149
|
+
*/
|
|
14
150
|
get depth() {
|
|
15
151
|
return this.max.z - this.min.z;
|
|
16
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* Gets the length of the box's diagonal
|
|
155
|
+
*/
|
|
17
156
|
get diagonal() {
|
|
18
|
-
this.
|
|
19
|
-
|
|
157
|
+
return this.tempVector3A.subVectors(this.max, this.min).length();
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Gets the volume of the bounding box
|
|
161
|
+
*/
|
|
162
|
+
getVolume() {
|
|
163
|
+
return this.width * this.height * this.depth;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Gets the surface area of the bounding box
|
|
167
|
+
*/
|
|
168
|
+
getSurfaceArea() {
|
|
169
|
+
const w = this.width;
|
|
170
|
+
const h = this.height;
|
|
171
|
+
const d = this.depth;
|
|
172
|
+
return 2 * (w * h + h * d + d * w);
|
|
20
173
|
}
|
|
21
174
|
}
|
|
22
175
|
|
|
23
|
-
|
|
176
|
+
/**
|
|
177
|
+
* Utility class for comparing and hashing BufferGeometry instances with tolerance support.
|
|
178
|
+
*/
|
|
179
|
+
class GeometryHasher {
|
|
180
|
+
/**
|
|
181
|
+
* Generates a consistent hash for a BufferGeometry based on its contents and tolerance.
|
|
182
|
+
*
|
|
183
|
+
* @param geometry - The geometry to hash
|
|
184
|
+
* @param tolerance - Precision level for number comparison (values within tolerance are considered equal)
|
|
185
|
+
* @returns A string hash that will be identical for geometrically equivalent geometries
|
|
186
|
+
*/
|
|
187
|
+
static getGeometryHash(geometry, tolerance = 1e-6) {
|
|
188
|
+
const hashParts = [];
|
|
189
|
+
// Process attributes
|
|
190
|
+
const attributes = geometry.attributes;
|
|
191
|
+
const attributeNames = Object.keys(attributes).sort(); // Sort for consistent order
|
|
192
|
+
for (const name of attributeNames) {
|
|
193
|
+
const attribute = attributes[name];
|
|
194
|
+
hashParts.push(`${name}:${attribute.itemSize}:${this.getAttributeHash(attribute, tolerance)}`);
|
|
195
|
+
}
|
|
196
|
+
// Process index if present
|
|
197
|
+
if (geometry.index) {
|
|
198
|
+
hashParts.push(`index:${this.getAttributeHash(geometry.index, tolerance)}`);
|
|
199
|
+
}
|
|
200
|
+
return hashParts.join("|");
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Compares two BufferGeometry instances for approximate equality.
|
|
204
|
+
* Early exit if UUIDs match (same object or cloned geometry).
|
|
205
|
+
*/
|
|
206
|
+
static compare(firstGeometry, secondGeometry, tolerance = 1e-6) {
|
|
207
|
+
if (firstGeometry.uuid === secondGeometry.uuid) {
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
// Use hash comparison for consistent results
|
|
211
|
+
return (this.getGeometryHash(firstGeometry, tolerance) ===
|
|
212
|
+
this.getGeometryHash(secondGeometry, tolerance));
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Generates a hash for a buffer attribute with tolerance.
|
|
216
|
+
*/
|
|
217
|
+
static getAttributeHash(attribute, tolerance) {
|
|
218
|
+
const array = attribute.array;
|
|
219
|
+
const itemSize = "itemSize" in attribute ? attribute.itemSize : 1;
|
|
220
|
+
const hashParts = [];
|
|
221
|
+
// Group values by their "tolerance buckets"
|
|
222
|
+
for (let i = 0; i < array.length; i += itemSize) {
|
|
223
|
+
const itemValues = [];
|
|
224
|
+
for (let j = 0; j < itemSize; j++) {
|
|
225
|
+
const val = array[i + j];
|
|
226
|
+
// Round to nearest tolerance multiple to group similar values
|
|
227
|
+
itemValues.push(Math.round(val / tolerance) * tolerance);
|
|
228
|
+
}
|
|
229
|
+
hashParts.push(itemValues.join(","));
|
|
230
|
+
}
|
|
231
|
+
return hashParts.join(";");
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Compares two buffer attributes with tolerance.
|
|
235
|
+
*/
|
|
236
|
+
static compareBufferAttributes(firstAttribute, secondAttribute, tolerance) {
|
|
237
|
+
return (this.getAttributeHash(firstAttribute, tolerance) ===
|
|
238
|
+
this.getAttributeHash(secondAttribute, tolerance));
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
class SceneTraversal {
|
|
24
243
|
static getObjectByName(object, name) {
|
|
25
|
-
if (object.name === name)
|
|
244
|
+
if (object.name === name) {
|
|
26
245
|
return object;
|
|
246
|
+
}
|
|
27
247
|
for (const child of object.children) {
|
|
28
|
-
const result =
|
|
29
|
-
if (result)
|
|
248
|
+
const result = SceneTraversal.getObjectByName(child, name);
|
|
249
|
+
if (result) {
|
|
30
250
|
return result;
|
|
251
|
+
}
|
|
31
252
|
}
|
|
32
253
|
return null;
|
|
33
254
|
}
|
|
@@ -35,8 +256,9 @@ class Enumerator {
|
|
|
35
256
|
if (object instanceof Mesh) {
|
|
36
257
|
if (Array.isArray(object.material)) {
|
|
37
258
|
for (const material of object.material) {
|
|
38
|
-
if (material.name === name)
|
|
259
|
+
if (material.name === name) {
|
|
39
260
|
return material;
|
|
261
|
+
}
|
|
40
262
|
}
|
|
41
263
|
}
|
|
42
264
|
else if (object.material.name === name) {
|
|
@@ -44,9 +266,10 @@ class Enumerator {
|
|
|
44
266
|
}
|
|
45
267
|
}
|
|
46
268
|
for (const child of object.children) {
|
|
47
|
-
const material =
|
|
48
|
-
if (material)
|
|
269
|
+
const material = SceneTraversal.getMaterialByName(child, name);
|
|
270
|
+
if (material) {
|
|
49
271
|
return material;
|
|
272
|
+
}
|
|
50
273
|
}
|
|
51
274
|
return null;
|
|
52
275
|
}
|
|
@@ -55,7 +278,7 @@ class Enumerator {
|
|
|
55
278
|
callback(object);
|
|
56
279
|
}
|
|
57
280
|
for (const child of object.children) {
|
|
58
|
-
|
|
281
|
+
SceneTraversal.enumerateObjectsByType(child, type, callback);
|
|
59
282
|
}
|
|
60
283
|
}
|
|
61
284
|
static enumerateMaterials(object, callback) {
|
|
@@ -70,7 +293,7 @@ class Enumerator {
|
|
|
70
293
|
}
|
|
71
294
|
}
|
|
72
295
|
for (const child of object.children) {
|
|
73
|
-
|
|
296
|
+
SceneTraversal.enumerateMaterials(child, callback);
|
|
74
297
|
}
|
|
75
298
|
}
|
|
76
299
|
static filterObjects(object, name) {
|
|
@@ -79,7 +302,7 @@ class Enumerator {
|
|
|
79
302
|
result.push(object);
|
|
80
303
|
}
|
|
81
304
|
for (const child of object.children) {
|
|
82
|
-
result = result.concat(
|
|
305
|
+
result = result.concat(SceneTraversal.filterObjects(child, name));
|
|
83
306
|
}
|
|
84
307
|
return result;
|
|
85
308
|
}
|
|
@@ -100,7 +323,7 @@ class Enumerator {
|
|
|
100
323
|
}
|
|
101
324
|
}
|
|
102
325
|
for (const child of object.children) {
|
|
103
|
-
result = result.concat(
|
|
326
|
+
result = result.concat(SceneTraversal.filterMaterials(child, name));
|
|
104
327
|
}
|
|
105
328
|
return result;
|
|
106
329
|
}
|
|
@@ -110,176 +333,11 @@ class Enumerator {
|
|
|
110
333
|
object.receiveShadow = receiveShadow;
|
|
111
334
|
}
|
|
112
335
|
for (const child of object.children) {
|
|
113
|
-
|
|
336
|
+
SceneTraversal.setShadowRecursive(child, castShadow, receiveShadow);
|
|
114
337
|
}
|
|
115
338
|
}
|
|
116
339
|
}
|
|
117
340
|
|
|
118
|
-
/**
|
|
119
|
-
* Utility class for comparing and hashing BufferGeometry instances with tolerance support.
|
|
120
|
-
*/
|
|
121
|
-
class GeometryComparator {
|
|
122
|
-
/**
|
|
123
|
-
* Generates a consistent hash for a BufferGeometry based on its contents and tolerance.
|
|
124
|
-
*
|
|
125
|
-
* @param geometry - The geometry to hash
|
|
126
|
-
* @param tolerance - Precision level for number comparison (values within tolerance are considered equal)
|
|
127
|
-
* @returns A string hash that will be identical for geometrically equivalent geometries
|
|
128
|
-
*/
|
|
129
|
-
static getGeometryHash(geometry, tolerance = 1e-6) {
|
|
130
|
-
const hashParts = [];
|
|
131
|
-
// Process attributes
|
|
132
|
-
const attributes = geometry.attributes;
|
|
133
|
-
const attributeNames = Object.keys(attributes).sort(); // Sort for consistent order
|
|
134
|
-
for (const name of attributeNames) {
|
|
135
|
-
const attribute = attributes[name];
|
|
136
|
-
hashParts.push(`${name}:${attribute.itemSize}:${this.getAttributeHash(attribute, tolerance)}`);
|
|
137
|
-
}
|
|
138
|
-
// Process index if present
|
|
139
|
-
if (geometry.index) {
|
|
140
|
-
hashParts.push(`index:${this.getAttributeHash(geometry.index, tolerance)}`);
|
|
141
|
-
}
|
|
142
|
-
return hashParts.join("|");
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Compares two BufferGeometry instances for approximate equality.
|
|
146
|
-
* Early exit if UUIDs match (same object or cloned geometry).
|
|
147
|
-
*/
|
|
148
|
-
static compare(firstGeometry, secondGeometry, tolerance = 1e-6) {
|
|
149
|
-
if (firstGeometry.uuid === secondGeometry.uuid) {
|
|
150
|
-
return true;
|
|
151
|
-
}
|
|
152
|
-
// Use hash comparison for consistent results
|
|
153
|
-
return (this.getGeometryHash(firstGeometry, tolerance) ===
|
|
154
|
-
this.getGeometryHash(secondGeometry, tolerance));
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Generates a hash for a buffer attribute with tolerance.
|
|
158
|
-
*/
|
|
159
|
-
static getAttributeHash(attribute, tolerance) {
|
|
160
|
-
const array = attribute.array;
|
|
161
|
-
const itemSize = "itemSize" in attribute ? attribute.itemSize : 1;
|
|
162
|
-
const hashParts = [];
|
|
163
|
-
// Group values by their "tolerance buckets"
|
|
164
|
-
for (let i = 0; i < array.length; i += itemSize) {
|
|
165
|
-
const itemValues = [];
|
|
166
|
-
for (let j = 0; j < itemSize; j++) {
|
|
167
|
-
const val = array[i + j];
|
|
168
|
-
// Round to nearest tolerance multiple to group similar values
|
|
169
|
-
itemValues.push(Math.round(val / tolerance) * tolerance);
|
|
170
|
-
}
|
|
171
|
-
hashParts.push(itemValues.join(","));
|
|
172
|
-
}
|
|
173
|
-
return hashParts.join(";");
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* Compares two buffer attributes with tolerance.
|
|
177
|
-
*/
|
|
178
|
-
static compareBufferAttributes(firstAttribute, secondAttribute, tolerance) {
|
|
179
|
-
return (this.getAttributeHash(firstAttribute, tolerance) ===
|
|
180
|
-
this.getAttributeHash(secondAttribute, tolerance));
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
// import {
|
|
184
|
-
// BufferAttribute,
|
|
185
|
-
// BufferGeometry,
|
|
186
|
-
// InterleavedBufferAttribute,
|
|
187
|
-
// } from "three";
|
|
188
|
-
// type AnySuitableAttribute = BufferAttribute | InterleavedBufferAttribute;
|
|
189
|
-
// /**
|
|
190
|
-
// * Utility class for comparing two BufferGeometry instances with tolerance support.
|
|
191
|
-
// * Checks geometry attributes (positions, normals, UVs, etc.) and indices (if present).
|
|
192
|
-
// */
|
|
193
|
-
// export class GeometryComparator {
|
|
194
|
-
// /**
|
|
195
|
-
// * Compares two BufferGeometry instances for approximate equality.
|
|
196
|
-
// * Early exit if UUIDs match (same object or cloned geometry).
|
|
197
|
-
// *
|
|
198
|
-
// * @param firstGeometry - The first geometry to compare.
|
|
199
|
-
// * @param secondGeometry - The second geometry to compare.
|
|
200
|
-
// * @param tolerance - Maximum allowed difference between numeric values (default: 1e-6).
|
|
201
|
-
// * @returns `true` if geometries are equivalent within tolerance, otherwise `false`.
|
|
202
|
-
// */
|
|
203
|
-
// public static compare(
|
|
204
|
-
// firstGeometry: BufferGeometry,
|
|
205
|
-
// secondGeometry: BufferGeometry,
|
|
206
|
-
// tolerance = 1e-6,
|
|
207
|
-
// ): boolean {
|
|
208
|
-
// if (firstGeometry.uuid === secondGeometry.uuid) {
|
|
209
|
-
// return true;
|
|
210
|
-
// }
|
|
211
|
-
// const firstAttributes = firstGeometry.attributes;
|
|
212
|
-
// const secondAttributes = secondGeometry.attributes;
|
|
213
|
-
// const firstAttributeNames = Object.keys(firstAttributes);
|
|
214
|
-
// const secondAttributeNames = Object.keys(secondAttributes);
|
|
215
|
-
// if (firstAttributeNames.length !== secondAttributeNames.length) {
|
|
216
|
-
// return false;
|
|
217
|
-
// }
|
|
218
|
-
// for (const attributeName of firstAttributeNames) {
|
|
219
|
-
// if (!secondAttributes[attributeName]) {
|
|
220
|
-
// return false;
|
|
221
|
-
// }
|
|
222
|
-
// const firstAttribute = firstAttributes[
|
|
223
|
-
// attributeName
|
|
224
|
-
// ] as AnySuitableAttribute;
|
|
225
|
-
// const secondAttribute = secondAttributes[
|
|
226
|
-
// attributeName
|
|
227
|
-
// ] as AnySuitableAttribute;
|
|
228
|
-
// if (
|
|
229
|
-
// firstAttribute.count !== secondAttribute.count ||
|
|
230
|
-
// firstAttribute.itemSize !== secondAttribute.itemSize ||
|
|
231
|
-
// !this.compareBufferAttributes(
|
|
232
|
-
// firstAttribute,
|
|
233
|
-
// secondAttribute,
|
|
234
|
-
// tolerance,
|
|
235
|
-
// )
|
|
236
|
-
// ) {
|
|
237
|
-
// return false;
|
|
238
|
-
// }
|
|
239
|
-
// }
|
|
240
|
-
// if (firstGeometry.index || secondGeometry.index) {
|
|
241
|
-
// if (!firstGeometry.index || !secondGeometry.index) {
|
|
242
|
-
// return false;
|
|
243
|
-
// }
|
|
244
|
-
// if (
|
|
245
|
-
// !this.compareBufferAttributes(
|
|
246
|
-
// firstGeometry.index,
|
|
247
|
-
// secondGeometry.index,
|
|
248
|
-
// tolerance,
|
|
249
|
-
// )
|
|
250
|
-
// ) {
|
|
251
|
-
// return false;
|
|
252
|
-
// }
|
|
253
|
-
// }
|
|
254
|
-
// return true;
|
|
255
|
-
// }
|
|
256
|
-
// /**
|
|
257
|
-
// * Compares two buffer attributes (or index buffers) with tolerance.
|
|
258
|
-
// *
|
|
259
|
-
// * @param firstAttribute - First attribute/indices to compare.
|
|
260
|
-
// * @param secondAttribute - Second attribute/indices to compare.
|
|
261
|
-
// * @param tolerance - Maximum allowed difference between array elements.
|
|
262
|
-
// * @returns `true` if arrays are equal within tolerance, otherwise `false`.
|
|
263
|
-
// */
|
|
264
|
-
// private static compareBufferAttributes(
|
|
265
|
-
// firstAttribute: AnySuitableAttribute,
|
|
266
|
-
// secondAttribute: AnySuitableAttribute,
|
|
267
|
-
// tolerance: number,
|
|
268
|
-
// ): boolean {
|
|
269
|
-
// const firstArray = firstAttribute.array;
|
|
270
|
-
// const secondArray = secondAttribute.array;
|
|
271
|
-
// if (firstArray.length !== secondArray.length) {
|
|
272
|
-
// return false;
|
|
273
|
-
// }
|
|
274
|
-
// for (let index = 0; index < firstArray.length; index++) {
|
|
275
|
-
// if (Math.abs(firstArray[index] - secondArray[index]) > tolerance) {
|
|
276
|
-
// return false;
|
|
277
|
-
// }
|
|
278
|
-
// }
|
|
279
|
-
// return true;
|
|
280
|
-
// }
|
|
281
|
-
// }
|
|
282
|
-
|
|
283
341
|
class InstanceAssembler {
|
|
284
342
|
static assemble(options) {
|
|
285
343
|
var _a, _b;
|
|
@@ -287,7 +345,7 @@ class InstanceAssembler {
|
|
|
287
345
|
const instancedMeshes = [];
|
|
288
346
|
const tolerance = (_a = options.geometryTolerance) !== null && _a !== void 0 ? _a : 1e-6;
|
|
289
347
|
const geometryHashCache = new Map();
|
|
290
|
-
|
|
348
|
+
SceneTraversal.enumerateObjectsByType(options.container, Mesh, (child) => {
|
|
291
349
|
var _a;
|
|
292
350
|
if (child.children.length === 0 &&
|
|
293
351
|
(!options.filter || options.filter(child))) {
|
|
@@ -296,7 +354,7 @@ class InstanceAssembler {
|
|
|
296
354
|
: [child.material];
|
|
297
355
|
let geometryHash = geometryHashCache.get(child.geometry.uuid);
|
|
298
356
|
if (!geometryHash) {
|
|
299
|
-
geometryHash =
|
|
357
|
+
geometryHash = GeometryHasher.getGeometryHash(child.geometry, tolerance);
|
|
300
358
|
geometryHashCache.set(child.geometry.uuid, geometryHash);
|
|
301
359
|
}
|
|
302
360
|
const materialKey = materials.map((m) => m.uuid).join(",");
|
|
@@ -307,17 +365,20 @@ class InstanceAssembler {
|
|
|
307
365
|
castShadow: false,
|
|
308
366
|
receiveShadow: false,
|
|
309
367
|
};
|
|
310
|
-
if (child.castShadow)
|
|
368
|
+
if (child.castShadow) {
|
|
311
369
|
entry.castShadow = true;
|
|
312
|
-
|
|
370
|
+
}
|
|
371
|
+
if (child.receiveShadow) {
|
|
313
372
|
entry.receiveShadow = true;
|
|
373
|
+
}
|
|
314
374
|
entry.meshes.push(child);
|
|
315
375
|
dictionary.set(compositeKey, entry);
|
|
316
376
|
}
|
|
317
377
|
});
|
|
318
378
|
for (const descriptor of dictionary.values()) {
|
|
319
|
-
if (descriptor.meshes.length < 2)
|
|
379
|
+
if (descriptor.meshes.length < 2) {
|
|
320
380
|
continue;
|
|
381
|
+
}
|
|
321
382
|
const { meshes, materials, castShadow, receiveShadow } = descriptor;
|
|
322
383
|
const sortedMeshes = meshes.sort((a, b) => a.name.localeCompare(b.name));
|
|
323
384
|
const defaultMesh = sortedMeshes[0];
|
|
@@ -347,14 +408,14 @@ class SceneProcessor {
|
|
|
347
408
|
static process(options) {
|
|
348
409
|
const container = options.asset.clone();
|
|
349
410
|
InstanceAssembler.assemble({ container: container });
|
|
350
|
-
|
|
411
|
+
SceneTraversal.enumerateMaterials(container, (material) => {
|
|
351
412
|
material.transparent = SceneProcessor.matchesAny(material.name, options.transparentMaterialNames);
|
|
352
413
|
material.depthWrite = !SceneProcessor.matchesAny(material.name, options.noDepthWriteMaterialNames);
|
|
353
414
|
material.side = FrontSide;
|
|
354
415
|
material.forceSinglePass = true;
|
|
355
416
|
material.depthTest = true;
|
|
356
417
|
});
|
|
357
|
-
|
|
418
|
+
SceneTraversal.enumerateObjectsByType(container, Mesh, (child) => {
|
|
358
419
|
child.castShadow = SceneProcessor.matchesAny(child.name, options.castShadowMeshNames);
|
|
359
420
|
child.receiveShadow = SceneProcessor.matchesAny(child.name, options.receiveShadowMeshNames);
|
|
360
421
|
});
|
|
@@ -416,9 +477,22 @@ class SkinnedMeshBaker {
|
|
|
416
477
|
}
|
|
417
478
|
}
|
|
418
479
|
|
|
480
|
+
/**
|
|
481
|
+
* Sun extends Three.js DirectionalLight to provide a specialized light source that simulates
|
|
482
|
+
* sunlight with advanced positioning and shadow controls.
|
|
483
|
+
*
|
|
484
|
+
* Features:
|
|
485
|
+
* - Spherical coordinate control (distance, elevation, azimuth)
|
|
486
|
+
* - Automatic shadow map configuration based on bounding boxes
|
|
487
|
+
* - HDR environment map-based positioning
|
|
488
|
+
* - Efficient temporary vector management for calculations
|
|
489
|
+
*
|
|
490
|
+
* @extends DirectionalLight
|
|
491
|
+
*/
|
|
419
492
|
class Sun extends DirectionalLight {
|
|
420
493
|
constructor() {
|
|
421
494
|
super(...arguments);
|
|
495
|
+
// Temporary vectors for calculations to avoid garbage collection
|
|
422
496
|
this.tempVector3D0 = new Vector3();
|
|
423
497
|
this.tempVector3D1 = new Vector3();
|
|
424
498
|
this.tempVector3D2 = new Vector3();
|
|
@@ -430,27 +504,57 @@ class Sun extends DirectionalLight {
|
|
|
430
504
|
this.tempBox3 = new Box3();
|
|
431
505
|
this.tempSpherical = new Spherical();
|
|
432
506
|
}
|
|
507
|
+
/**
|
|
508
|
+
* Gets the distance of the sun from its target (radius in spherical coordinates)
|
|
509
|
+
* @returns The distance in world units
|
|
510
|
+
*/
|
|
433
511
|
get distance() {
|
|
434
512
|
return this.position.length();
|
|
435
513
|
}
|
|
514
|
+
/**
|
|
515
|
+
* Gets the elevation angle of the sun (phi in spherical coordinates)
|
|
516
|
+
* @returns The elevation in radians
|
|
517
|
+
*/
|
|
436
518
|
get elevation() {
|
|
437
519
|
return this.tempSpherical.setFromVector3(this.position).phi;
|
|
438
520
|
}
|
|
521
|
+
/**
|
|
522
|
+
* Gets the azimuth angle of the sun (theta in spherical coordinates)
|
|
523
|
+
* @returns The azimuth in radians
|
|
524
|
+
*/
|
|
439
525
|
get azimuth() {
|
|
440
526
|
return this.tempSpherical.setFromVector3(this.position).theta;
|
|
441
527
|
}
|
|
528
|
+
/**
|
|
529
|
+
* Sets the distance of the sun from its target while maintaining current angles
|
|
530
|
+
* @param value - The new distance in world units
|
|
531
|
+
*/
|
|
442
532
|
set distance(value) {
|
|
443
533
|
this.tempSpherical.setFromVector3(this.position);
|
|
444
534
|
this.position.setFromSphericalCoords(value, this.tempSpherical.phi, this.tempSpherical.theta);
|
|
445
535
|
}
|
|
536
|
+
/**
|
|
537
|
+
* Sets the elevation angle of the sun while maintaining current distance and azimuth
|
|
538
|
+
* @param value - The new elevation in radians
|
|
539
|
+
*/
|
|
446
540
|
set elevation(value) {
|
|
447
541
|
this.tempSpherical.setFromVector3(this.position);
|
|
448
542
|
this.position.setFromSphericalCoords(this.tempSpherical.radius, value, this.tempSpherical.theta);
|
|
449
543
|
}
|
|
544
|
+
/**
|
|
545
|
+
* Sets the azimuth angle of the sun while maintaining current distance and elevation
|
|
546
|
+
* @param value - The new azimuth in radians
|
|
547
|
+
*/
|
|
450
548
|
set azimuth(value) {
|
|
451
549
|
this.tempSpherical.setFromVector3(this.position);
|
|
452
550
|
this.position.setFromSphericalCoords(this.tempSpherical.radius, this.tempSpherical.phi, value);
|
|
453
551
|
}
|
|
552
|
+
/**
|
|
553
|
+
* Configures the shadow camera's frustum to encompass the given bounding box
|
|
554
|
+
* This ensures that shadows are cast correctly for objects within the box
|
|
555
|
+
*
|
|
556
|
+
* @param box3 - The bounding box to configure shadows for
|
|
557
|
+
*/
|
|
454
558
|
setShadowMapFromBox3(box3) {
|
|
455
559
|
const camera = this.shadow.camera;
|
|
456
560
|
this.target.updateWorldMatrix(true, false);
|
|
@@ -480,23 +584,33 @@ class Sun extends DirectionalLight {
|
|
|
480
584
|
camera.updateWorldMatrix(true, false);
|
|
481
585
|
camera.updateProjectionMatrix();
|
|
482
586
|
}
|
|
587
|
+
/**
|
|
588
|
+
* Sets the sun's direction based on the brightest point in an HDR texture
|
|
589
|
+
* This is useful for matching the sun's position to an environment map
|
|
590
|
+
*
|
|
591
|
+
* @param texture - The HDR texture to analyze (must be loaded and have valid image data)
|
|
592
|
+
* @param distance - Optional distance to position the sun from its target (default: 1)
|
|
593
|
+
*/
|
|
483
594
|
setDirectionFromHDR(texture, distance = 1) {
|
|
484
595
|
const data = texture.image.data;
|
|
485
596
|
const width = texture.image.width;
|
|
486
597
|
const height = texture.image.height;
|
|
487
598
|
let maxLuminance = 0;
|
|
488
599
|
let maxIndex = 0;
|
|
600
|
+
// Find the brightest pixel in the HDR texture
|
|
489
601
|
const step = texture.format === RGBAFormat ? 4 : 3;
|
|
490
602
|
for (let i = 0; i < data.length; i += step) {
|
|
491
603
|
const r = data[i];
|
|
492
604
|
const g = data[i + 1];
|
|
493
605
|
const b = data[i + 2];
|
|
606
|
+
// Calculate luminance using the Rec. 709 coefficients
|
|
494
607
|
const luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
495
608
|
if (luminance > maxLuminance) {
|
|
496
609
|
maxLuminance = luminance;
|
|
497
610
|
maxIndex = i;
|
|
498
611
|
}
|
|
499
612
|
}
|
|
613
|
+
// Convert pixel coordinates to spherical coordinates
|
|
500
614
|
const pixelIndex = maxIndex / step;
|
|
501
615
|
const x = pixelIndex % width;
|
|
502
616
|
const y = Math.floor(pixelIndex / width);
|
|
@@ -508,5 +622,5 @@ class Sun extends DirectionalLight {
|
|
|
508
622
|
}
|
|
509
623
|
}
|
|
510
624
|
|
|
511
|
-
export {
|
|
625
|
+
export { BiFovCamera, Bounds, InstanceAssembler, SceneProcessor, SceneTraversal, SkinnedMeshBaker, Sun };
|
|
512
626
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/Bounds.ts","../src/Enumerator.ts","../src/GeometryComparator.ts","../src/InstanceAssembler.ts","../src/SceneProcessor.ts","../src/SkinnedMeshBaker.ts","../src/Sun.ts"],"sourcesContent":["import { Box3, Vector3 } from \"three\";\n\nexport class Bounds extends Box3 {\n private readonly tempVector3: Vector3 = new Vector3();\n\n public get width(): number {\n return this.max.x - this.min.x;\n }\n\n public get height(): number {\n return this.max.y - this.min.y;\n }\n\n public get depth(): number {\n return this.max.z - this.min.z;\n }\n\n public get diagonal(): number {\n this.tempVector3.subVectors(this.max, this.min);\n return this.tempVector3.length();\n }\n}\n","import { Material, Mesh, Object3D } from \"three\";\n\ntype Constructor<T> = abstract new (...args: never[]) => T;\n\nexport class Enumerator {\n public static getObjectByName(\n object: Object3D,\n name: string,\n ): Object3D | null {\n if (object.name === name) return object;\n\n for (const child of object.children) {\n const result = Enumerator.getObjectByName(child, name);\n if (result) return result;\n }\n\n return null;\n }\n\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) return material;\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 = Enumerator.getMaterialByName(child, name);\n if (material) return material;\n }\n\n return null;\n }\n\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 Enumerator.enumerateObjectsByType(child, type, callback);\n }\n }\n\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 Enumerator.enumerateMaterials(child, callback);\n }\n }\n\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(Enumerator.filterObjects(child, name));\n }\n\n return result;\n }\n\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(Enumerator.filterMaterials(child, name));\n }\n\n return result;\n }\n\n public static setShadowRecursive(\n object: Object3D,\n castShadow = true,\n receiveShadow = true,\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 Enumerator.setShadowRecursive(child, castShadow, receiveShadow);\n }\n }\n}\n","import {\n BufferAttribute,\n BufferGeometry,\n InterleavedBufferAttribute,\n} from \"three\";\n\ntype AnySuitableAttribute = BufferAttribute | InterleavedBufferAttribute;\n\n/**\n * Utility class for comparing and hashing BufferGeometry instances with tolerance support.\n */\nexport class GeometryComparator {\n /**\n * Generates a consistent hash for a BufferGeometry based on its contents and tolerance.\n *\n * @param geometry - The geometry to hash\n * @param tolerance - Precision level for number comparison (values within tolerance are considered equal)\n * @returns A string hash that will be identical for geometrically equivalent geometries\n */\n public static getGeometryHash(\n geometry: BufferGeometry,\n tolerance = 1e-6,\n ): string {\n const hashParts: string[] = [];\n\n // Process attributes\n const attributes = geometry.attributes;\n const attributeNames = Object.keys(attributes).sort(); // Sort for consistent order\n\n for (const name of attributeNames) {\n const attribute = attributes[name] as AnySuitableAttribute;\n hashParts.push(\n `${name}:${attribute.itemSize}:${this.getAttributeHash(attribute, tolerance)}`,\n );\n }\n\n // Process index if present\n if (geometry.index) {\n hashParts.push(\n `index:${this.getAttributeHash(geometry.index, tolerance)}`,\n );\n }\n\n return hashParts.join(\"|\");\n }\n\n /**\n * Compares two BufferGeometry instances for approximate equality.\n * Early exit if UUIDs match (same object or cloned geometry).\n */\n public static compare(\n firstGeometry: BufferGeometry,\n secondGeometry: BufferGeometry,\n tolerance = 1e-6,\n ): boolean {\n if (firstGeometry.uuid === secondGeometry.uuid) {\n return true;\n }\n\n // Use hash comparison for consistent results\n return (\n this.getGeometryHash(firstGeometry, tolerance) ===\n this.getGeometryHash(secondGeometry, tolerance)\n );\n }\n\n /**\n * Generates a hash for a buffer attribute with tolerance.\n */\n private static getAttributeHash(\n attribute: AnySuitableAttribute,\n tolerance: number,\n ): string {\n const array = attribute.array;\n const itemSize = \"itemSize\" in attribute ? attribute.itemSize : 1;\n const hashParts: string[] = [];\n\n // Group values by their \"tolerance buckets\"\n for (let i = 0; i < array.length; i += itemSize) {\n const itemValues = [];\n for (let j = 0; j < itemSize; j++) {\n const val = array[i + j];\n // Round to nearest tolerance multiple to group similar values\n itemValues.push(Math.round(val / tolerance) * tolerance);\n }\n hashParts.push(itemValues.join(\",\"));\n }\n\n return hashParts.join(\";\");\n }\n\n /**\n * Compares two buffer attributes with tolerance.\n */\n private static compareBufferAttributes(\n firstAttribute: AnySuitableAttribute,\n secondAttribute: AnySuitableAttribute,\n tolerance: number,\n ): boolean {\n return (\n this.getAttributeHash(firstAttribute, tolerance) ===\n this.getAttributeHash(secondAttribute, tolerance)\n );\n }\n}\n\n// import {\n// BufferAttribute,\n// BufferGeometry,\n// InterleavedBufferAttribute,\n// } from \"three\";\n\n// type AnySuitableAttribute = BufferAttribute | InterleavedBufferAttribute;\n\n// /**\n// * Utility class for comparing two BufferGeometry instances with tolerance support.\n// * Checks geometry attributes (positions, normals, UVs, etc.) and indices (if present).\n// */\n// export class GeometryComparator {\n// /**\n// * Compares two BufferGeometry instances for approximate equality.\n// * Early exit if UUIDs match (same object or cloned geometry).\n// *\n// * @param firstGeometry - The first geometry to compare.\n// * @param secondGeometry - The second geometry to compare.\n// * @param tolerance - Maximum allowed difference between numeric values (default: 1e-6).\n// * @returns `true` if geometries are equivalent within tolerance, otherwise `false`.\n// */\n// public static compare(\n// firstGeometry: BufferGeometry,\n// secondGeometry: BufferGeometry,\n// tolerance = 1e-6,\n// ): boolean {\n// if (firstGeometry.uuid === secondGeometry.uuid) {\n// return true;\n// }\n\n// const firstAttributes = firstGeometry.attributes;\n// const secondAttributes = secondGeometry.attributes;\n\n// const firstAttributeNames = Object.keys(firstAttributes);\n// const secondAttributeNames = Object.keys(secondAttributes);\n\n// if (firstAttributeNames.length !== secondAttributeNames.length) {\n// return false;\n// }\n\n// for (const attributeName of firstAttributeNames) {\n// if (!secondAttributes[attributeName]) {\n// return false;\n// }\n\n// const firstAttribute = firstAttributes[\n// attributeName\n// ] as AnySuitableAttribute;\n// const secondAttribute = secondAttributes[\n// attributeName\n// ] as AnySuitableAttribute;\n\n// if (\n// firstAttribute.count !== secondAttribute.count ||\n// firstAttribute.itemSize !== secondAttribute.itemSize ||\n// !this.compareBufferAttributes(\n// firstAttribute,\n// secondAttribute,\n// tolerance,\n// )\n// ) {\n// return false;\n// }\n// }\n\n// if (firstGeometry.index || secondGeometry.index) {\n// if (!firstGeometry.index || !secondGeometry.index) {\n// return false;\n// }\n\n// if (\n// !this.compareBufferAttributes(\n// firstGeometry.index,\n// secondGeometry.index,\n// tolerance,\n// )\n// ) {\n// return false;\n// }\n// }\n\n// return true;\n// }\n\n// /**\n// * Compares two buffer attributes (or index buffers) with tolerance.\n// *\n// * @param firstAttribute - First attribute/indices to compare.\n// * @param secondAttribute - Second attribute/indices to compare.\n// * @param tolerance - Maximum allowed difference between array elements.\n// * @returns `true` if arrays are equal within tolerance, otherwise `false`.\n// */\n// private static compareBufferAttributes(\n// firstAttribute: AnySuitableAttribute,\n// secondAttribute: AnySuitableAttribute,\n// tolerance: number,\n// ): boolean {\n// const firstArray = firstAttribute.array;\n// const secondArray = secondAttribute.array;\n\n// if (firstArray.length !== secondArray.length) {\n// return false;\n// }\n\n// for (let index = 0; index < firstArray.length; index++) {\n// if (Math.abs(firstArray[index] - secondArray[index]) > tolerance) {\n// return false;\n// }\n// }\n\n// return true;\n// }\n// }\n","import { InstancedMesh, Material, Mesh, Object3D } from \"three\";\nimport { Enumerator } from \"./Enumerator\";\nimport { GeometryComparator } from \"./GeometryComparator\";\n\ninterface IMeshDescriptor {\n meshes: Mesh[];\n materials: Material[];\n castShadow: boolean;\n receiveShadow: boolean;\n}\n\ninterface IOptions {\n container: Object3D;\n filter?: (child: Mesh) => boolean;\n geometryTolerance?: number;\n}\n\nexport class InstanceAssembler {\n public static assemble(options: IOptions): void {\n const dictionary = new Map<string, IMeshDescriptor>();\n const instancedMeshes: InstancedMesh[] = [];\n const tolerance = options.geometryTolerance ?? 1e-6;\n const geometryHashCache = new Map<string, string>();\n\n Enumerator.enumerateObjectsByType(\n options.container,\n Mesh,\n (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 = geometryHashCache.get(child.geometry.uuid);\n if (!geometryHash) {\n geometryHash = GeometryComparator.getGeometryHash(\n child.geometry,\n tolerance,\n );\n geometryHashCache.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: materials,\n castShadow: false,\n receiveShadow: false,\n };\n\n if (child.castShadow) entry.castShadow = true;\n if (child.receiveShadow) entry.receiveShadow = true;\n\n entry.meshes.push(child);\n dictionary.set(compositeKey, entry);\n }\n },\n );\n\n for (const descriptor of dictionary.values()) {\n if (descriptor.meshes.length < 2) continue;\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 instancedMeshes.push(instancedMesh);\n\n for (const mesh of sortedMeshes) {\n mesh.parent?.remove(mesh);\n }\n }\n\n if (instancedMeshes.length > 0) {\n options.container.add(...instancedMeshes);\n }\n }\n}\n","import { FrontSide, Material, Mesh, Object3D } from \"three\";\nimport { Enumerator } from \"./Enumerator\";\nimport { InstanceAssembler } from \"./InstanceAssembler\";\n\ntype IPattern = string | RegExp;\n\ninterface IOptions {\n asset: Object3D;\n castShadowMeshNames?: IPattern[];\n receiveShadowMeshNames?: IPattern[];\n transparentMaterialNames?: IPattern[];\n noDepthWriteMaterialNames?: IPattern[];\n}\n\nexport class SceneProcessor {\n public static process(options: IOptions): Object3D[] {\n const container = options.asset.clone();\n InstanceAssembler.assemble({ container: container });\n\n Enumerator.enumerateMaterials(container, (material: Material) => {\n material.transparent = SceneProcessor.matchesAny(\n material.name,\n options.transparentMaterialNames,\n );\n material.depthWrite = !SceneProcessor.matchesAny(\n material.name,\n options.noDepthWriteMaterialNames,\n );\n material.side = FrontSide;\n material.forceSinglePass = true;\n material.depthTest = true;\n });\n\n Enumerator.enumerateObjectsByType(container, Mesh, (child: Mesh) => {\n child.castShadow = SceneProcessor.matchesAny(\n child.name,\n options.castShadowMeshNames,\n );\n child.receiveShadow = SceneProcessor.matchesAny(\n child.name,\n options.receiveShadowMeshNames,\n );\n });\n\n return container.children;\n }\n\n private static matchesAny(value: string, patterns: IPattern[] = []): boolean {\n return patterns.some((p) =>\n typeof p === \"string\" ? value === p : p.test(value),\n );\n }\n}\n","import {\n AnimationClip,\n AnimationMixer,\n BufferAttribute,\n Mesh,\n Object3D,\n SkinnedMesh,\n Vector3,\n} from \"three\";\n\n/**\n * Utilities for baking poses and animations from SkinnedMesh into a regular static Mesh.\n */\nexport class SkinnedMeshBaker {\n /**\n * Bakes the current pose of a SkinnedMesh into a regular geometry.\n * Transforms all vertices according to the current skeleton state.\n *\n * @param skinnedMesh - SkinnedMesh from which to bake the geometry\n * @returns A new Mesh with positions corresponding to the current bone positions\n */\n 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 * 3);\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 * 3 + 0] = target.x;\n newPositions[i * 3 + 1] = target.y;\n newPositions[i * 3 + 2] = target.z;\n }\n\n bakedGeometry.setAttribute(\n \"position\",\n new BufferAttribute(newPositions, 3),\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 * Bakes a SkinnedMesh in a specific pose derived from an AnimationClip at the given timestamp.\n *\n * @param armature - The parent object (typically an armature from GLTF) containing the bones\n * @param skinnedMesh - The SkinnedMesh to be baked\n * @param timeOffset - The animation time in seconds to set\n * @param clip - The animation clip\n * @returns A new Mesh with geometry matching the specified animation frame\n */\n 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}\n","import {\n Box3,\n DirectionalLight,\n RGBAFormat,\n Spherical,\n Texture,\n Vector3,\n} from \"three\";\n\nexport class Sun extends DirectionalLight {\n private tempVector3D0 = new Vector3();\n private tempVector3D1 = new Vector3();\n private tempVector3D2 = new Vector3();\n private tempVector3D3 = new Vector3();\n private tempVector3D4 = new Vector3();\n private tempVector3D5 = new Vector3();\n private tempVector3D6 = new Vector3();\n private tempVector3D7 = new Vector3();\n\n private tempBox3 = new Box3();\n private tempSpherical = new Spherical();\n\n public get distance(): number {\n return this.position.length();\n }\n\n public get elevation(): number {\n return this.tempSpherical.setFromVector3(this.position).phi;\n }\n\n public get azimuth(): number {\n return this.tempSpherical.setFromVector3(this.position).theta;\n }\n\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 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 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 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 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 const step = texture.format === RGBAFormat ? 4 : 3;\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 = 0.2126 * r + 0.7152 * g + 0.0722 * b;\n if (luminance > maxLuminance) {\n maxLuminance = luminance;\n maxIndex = i;\n }\n }\n\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 { MathUtils, PerspectiveCamera } from \"three\";\n\n/**\n * Default camera settings\n */\nconst DEFAULT_HORIZONTAL_FOV = 90;\nconst DEFAULT_VERTICAL_FOV = 90;\nconst DEFAULT_ASPECT = 1;\nconst DEFAULT_NEAR = 1;\nconst DEFAULT_FAR = 1000;\n\n/**\n * BiFovCamera - A specialized PerspectiveCamera that supports independent horizontal and vertical FOV settings\n *\n * This camera extends Three.js PerspectiveCamera to provide better control over the field of view,\n * allowing separate horizontal and vertical FOV values. The camera automatically adjusts its projection\n * matrix based on the aspect ratio to maintain proper perspective.\n *\n * @extends PerspectiveCamera\n */\nexport class BiFovCamera extends PerspectiveCamera {\n private horizontalFovInternal: number;\n private verticalFovInternal: number;\n\n /**\n * Creates a new BiFovCamera instance\n *\n * @param horizontalFov - Horizontal field of view in degrees (default: 90)\n * @param verticalFov - Vertical field of view in degrees (default: 90)\n * @param aspect - Aspect ratio (width/height) of the viewport (default: 1)\n * @param near - Near clipping plane distance (default: 1)\n * @param far - Far clipping plane distance (default: 1000)\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 /**\n * Gets the horizontal field of view in degrees\n */\n public get horizontalFov(): number {\n return this.horizontalFovInternal;\n }\n\n /**\n * Gets the vertical field of view in degrees\n */\n public get verticalFov(): number {\n return this.verticalFovInternal;\n }\n\n /**\n * Sets the horizontal field of view in degrees\n * @param value - The new horizontal FOV value\n */\n public set horizontalFov(value: number) {\n this.horizontalFovInternal = MathUtils.clamp(value, 1, 179);\n this.updateProjectionMatrix();\n }\n\n /**\n * Sets the vertical field of view in degrees\n * @param value - The new vertical FOV value\n */\n public set verticalFov(value: number) {\n this.verticalFovInternal = MathUtils.clamp(value, 1, 179);\n this.updateProjectionMatrix();\n }\n\n /**\n * Updates both horizontal and vertical FOV simultaneously\n * @param horizontal - New horizontal FOV in degrees\n * @param vertical - New vertical FOV in degrees\n */\n public setFov(horizontal: number, vertical: number): void {\n this.horizontalFovInternal = MathUtils.clamp(horizontal, 1, 179);\n this.verticalFovInternal = MathUtils.clamp(vertical, 1, 179);\n this.updateProjectionMatrix();\n }\n\n /**\n * Copies FOV settings from another BiFovCamera\n * @param source - The camera to copy settings 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 current FOV settings and aspect ratio\n * For aspect ratios >= 1 (landscape), horizontal FOV is preserved\n * For aspect ratios < 1 (portrait), vertical FOV is preserved\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 /**\n * Returns the actual horizontal FOV after aspect ratio adjustments\n */\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 /**\n * Returns the actual vertical FOV after aspect ratio adjustments\n */\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 /**\n * Creates a clone of this camera with the same properties\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 { Box3, Vector3 } from \"three\";\n\nexport class Bounds extends Box3 {\n private readonly tempVector3A: Vector3 = new Vector3();\n\n /**\n * Gets the width (x-axis length) of the bounding box\n */\n public get width(): number {\n return this.max.x - this.min.x;\n }\n\n /**\n * Gets the height (y-axis length) of the bounding box\n */\n public get height(): number {\n return this.max.y - this.min.y;\n }\n\n /**\n * Gets the depth (z-axis length) of the bounding box\n */\n public get depth(): number {\n return this.max.z - this.min.z;\n }\n\n /**\n * Gets the length of the box's diagonal\n */\n public get diagonal(): number {\n return this.tempVector3A.subVectors(this.max, this.min).length();\n }\n\n /**\n * Gets the volume of the bounding box\n */\n public getVolume(): number {\n return this.width * this.height * this.depth;\n }\n\n /**\n * Gets the surface area of the bounding box\n */\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 {\n BufferAttribute,\n BufferGeometry,\n InterleavedBufferAttribute,\n} from \"three\";\n\ntype AnySuitableAttribute = BufferAttribute | InterleavedBufferAttribute;\n\n/**\n * Utility class for comparing and hashing BufferGeometry instances with tolerance support.\n */\nexport class GeometryHasher {\n /**\n * Generates a consistent hash for a BufferGeometry based on its contents and tolerance.\n *\n * @param geometry - The geometry to hash\n * @param tolerance - Precision level for number comparison (values within tolerance are considered equal)\n * @returns A string hash that will be identical for geometrically equivalent geometries\n */\n public static getGeometryHash(\n geometry: BufferGeometry,\n tolerance = 1e-6,\n ): string {\n const hashParts: string[] = [];\n\n // Process attributes\n const attributes = geometry.attributes;\n const attributeNames = Object.keys(attributes).sort(); // Sort for consistent order\n\n for (const name of attributeNames) {\n const attribute = attributes[name] as AnySuitableAttribute;\n hashParts.push(\n `${name}:${attribute.itemSize}:${this.getAttributeHash(attribute, tolerance)}`,\n );\n }\n\n // Process index if present\n if (geometry.index) {\n hashParts.push(\n `index:${this.getAttributeHash(geometry.index, tolerance)}`,\n );\n }\n\n return hashParts.join(\"|\");\n }\n\n /**\n * Compares two BufferGeometry instances for approximate equality.\n * Early exit if UUIDs match (same object or cloned geometry).\n */\n public static compare(\n firstGeometry: BufferGeometry,\n secondGeometry: BufferGeometry,\n tolerance = 1e-6,\n ): boolean {\n if (firstGeometry.uuid === secondGeometry.uuid) {\n return true;\n }\n\n // Use hash comparison for consistent results\n return (\n this.getGeometryHash(firstGeometry, tolerance) ===\n this.getGeometryHash(secondGeometry, tolerance)\n );\n }\n\n /**\n * Generates a hash for a buffer attribute with tolerance.\n */\n private static getAttributeHash(\n attribute: AnySuitableAttribute,\n tolerance: number,\n ): string {\n const array = attribute.array;\n const itemSize = \"itemSize\" in attribute ? attribute.itemSize : 1;\n const hashParts: string[] = [];\n\n // Group values by their \"tolerance buckets\"\n for (let i = 0; i < array.length; i += itemSize) {\n const itemValues = [];\n for (let j = 0; j < itemSize; j++) {\n const val = array[i + j];\n // Round to nearest tolerance multiple to group similar values\n itemValues.push(Math.round(val / tolerance) * tolerance);\n }\n hashParts.push(itemValues.join(\",\"));\n }\n\n return hashParts.join(\";\");\n }\n\n /**\n * Compares two buffer attributes with tolerance.\n */\n private static compareBufferAttributes(\n firstAttribute: AnySuitableAttribute,\n secondAttribute: AnySuitableAttribute,\n tolerance: number,\n ): boolean {\n return (\n this.getAttributeHash(firstAttribute, tolerance) ===\n this.getAttributeHash(secondAttribute, tolerance)\n );\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { Mesh } from \"three\";\n\ntype Constructor<T> = abstract new (...args: never[]) => T;\n\nexport class SceneTraversal {\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 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 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 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 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 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 public static setShadowRecursive(\n object: Object3D,\n castShadow = true,\n receiveShadow = true,\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(child, castShadow, receiveShadow);\n }\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { InstancedMesh, Mesh } from \"three\";\nimport { GeometryHasher } from \"./GeometryHasher\";\nimport { SceneTraversal } from \"./SceneTraversal\";\n\ninterface IMeshDescriptor {\n meshes: Mesh[];\n materials: Material[];\n castShadow: boolean;\n receiveShadow: boolean;\n}\n\ninterface IOptions {\n container: Object3D;\n filter?: (child: Mesh) => boolean;\n geometryTolerance?: number;\n}\n\nexport class InstanceAssembler {\n public static assemble(options: IOptions): void {\n const dictionary = new Map<string, IMeshDescriptor>();\n const instancedMeshes: InstancedMesh[] = [];\n const tolerance = options.geometryTolerance ?? 1e-6;\n const geometryHashCache = new Map<string, string>();\n\n SceneTraversal.enumerateObjectsByType(\n options.container,\n Mesh,\n (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 = geometryHashCache.get(child.geometry.uuid);\n if (!geometryHash) {\n geometryHash = GeometryHasher.getGeometryHash(\n child.geometry,\n tolerance,\n );\n geometryHashCache.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: materials,\n castShadow: false,\n receiveShadow: false,\n };\n\n if (child.castShadow) {\n entry.castShadow = true;\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\n for (const descriptor of dictionary.values()) {\n if (descriptor.meshes.length < 2) {\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 instancedMeshes.push(instancedMesh);\n\n for (const mesh of sortedMeshes) {\n mesh.parent?.remove(mesh);\n }\n }\n\n if (instancedMeshes.length > 0) {\n options.container.add(...instancedMeshes);\n }\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { FrontSide, Mesh } from \"three\";\nimport { InstanceAssembler } from \"./InstanceAssembler\";\nimport { SceneTraversal } from \"./SceneTraversal\";\n\ntype IPattern = string | RegExp;\n\ninterface IOptions {\n asset: Object3D;\n castShadowMeshNames?: IPattern[];\n receiveShadowMeshNames?: IPattern[];\n transparentMaterialNames?: IPattern[];\n noDepthWriteMaterialNames?: IPattern[];\n}\n\nexport class SceneProcessor {\n public static process(options: IOptions): Object3D[] {\n const container = options.asset.clone();\n InstanceAssembler.assemble({ container: container });\n\n SceneTraversal.enumerateMaterials(container, (material: Material) => {\n material.transparent = SceneProcessor.matchesAny(\n material.name,\n options.transparentMaterialNames,\n );\n material.depthWrite = !SceneProcessor.matchesAny(\n material.name,\n options.noDepthWriteMaterialNames,\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.castShadowMeshNames,\n );\n child.receiveShadow = SceneProcessor.matchesAny(\n child.name,\n options.receiveShadowMeshNames,\n );\n });\n\n return container.children;\n }\n\n private static matchesAny(value: string, patterns: IPattern[] = []): boolean {\n return patterns.some((p) =>\n typeof p === \"string\" ? value === p : p.test(value),\n );\n }\n}\n","import type { AnimationClip, Object3D, SkinnedMesh } from \"three\";\nimport { AnimationMixer, BufferAttribute, Mesh, Vector3 } from \"three\";\n\n/**\n * Utilities for baking poses and animations from SkinnedMesh into a regular static Mesh.\n */\nexport class SkinnedMeshBaker {\n /**\n * Bakes the current pose of a SkinnedMesh into a regular geometry.\n * Transforms all vertices according to the current skeleton state.\n *\n * @param skinnedMesh - SkinnedMesh from which to bake the geometry\n * @returns A new Mesh with positions corresponding to the current bone 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 * 3);\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 * 3 + 0] = target.x;\n newPositions[i * 3 + 1] = target.y;\n newPositions[i * 3 + 2] = target.z;\n }\n\n bakedGeometry.setAttribute(\n \"position\",\n new BufferAttribute(newPositions, 3),\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 * Bakes a SkinnedMesh in a specific pose derived from an AnimationClip at the given timestamp.\n *\n * @param armature - The parent object (typically an armature from GLTF) containing the bones\n * @param skinnedMesh - The SkinnedMesh to be baked\n * @param timeOffset - The animation time in seconds to set\n * @param clip - The animation clip\n * @returns A new Mesh with geometry matching the specified animation frame\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}\n","import type { Texture } from \"three\";\nimport { Box3, DirectionalLight, RGBAFormat, Spherical, Vector3 } from \"three\";\n\n/**\n * Sun extends Three.js DirectionalLight to provide a specialized light source that simulates\n * sunlight with advanced positioning and shadow controls.\n * \n * Features:\n * - Spherical coordinate control (distance, elevation, azimuth)\n * - Automatic shadow map configuration based on bounding boxes\n * - HDR environment map-based positioning\n * - Efficient temporary vector management for calculations\n * \n * @extends DirectionalLight\n */\nexport class Sun extends DirectionalLight {\n // Temporary vectors for calculations 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\n private readonly tempBox3 = new Box3();\n private readonly tempSpherical = new Spherical();\n\n /**\n * Gets the distance of the sun from its target (radius in spherical coordinates)\n * @returns The distance in world units\n */\n public get distance(): number {\n return this.position.length();\n }\n\n /**\n * Gets the elevation angle of the sun (phi in spherical coordinates)\n * @returns The elevation in radians\n */\n public get elevation(): number {\n return this.tempSpherical.setFromVector3(this.position).phi;\n }\n\n /**\n * Gets the azimuth angle of the sun (theta in spherical coordinates)\n * @returns The azimuth in radians\n */\n public get azimuth(): number {\n return this.tempSpherical.setFromVector3(this.position).theta;\n }\n\n /**\n * Sets the distance of the sun from its target while maintaining current angles\n * @param value - The new distance in world units\n */\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 /**\n * Sets the elevation angle of the sun while maintaining current distance and azimuth\n * @param value - The new elevation in radians\n */\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 /**\n * Sets the azimuth angle of the sun while maintaining current distance and elevation\n * @param value - The new azimuth in radians\n */\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 /**\n * Configures the shadow camera's frustum to encompass the given bounding box\n * This ensures that shadows are cast correctly for objects within the box\n * \n * @param box3 - The bounding box to configure shadows for\n */\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 /**\n * Sets the sun's direction based on the brightest point in an HDR texture\n * This is useful for matching the sun's position to an environment map\n * \n * @param texture - The HDR texture to analyze (must be loaded and have valid image data)\n * @param distance - Optional distance to position the sun from its target (default: 1)\n */\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 the brightest pixel in the HDR texture\n const step = texture.format === RGBAFormat ? 4 : 3;\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 // Calculate luminance using the Rec. 709 coefficients\n const luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;\n if (luminance > maxLuminance) {\n maxLuminance = luminance;\n maxIndex = i;\n }\n }\n\n // Convert pixel coordinates 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}"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{PerspectiveCamera as t,MathUtils as s,Box3 as e,Vector3 as i,Mesh as r,InstancedMesh as n,FrontSide as h,BufferAttribute as o,AnimationMixer as c,DirectionalLight as a,Spherical as f,RGBAFormat as u}from"three";class l extends t{constructor(t=90,s=90,e=1,i=1,r=1e3){super(s,e,i,r),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,179),this.updateProjectionMatrix()}set verticalFov(t){this.verticalFovInternal=s.clamp(t,1,179),this.updateProjectionMatrix()}setFov(t,e){this.horizontalFovInternal=s.clamp(t,1,179),this.verticalFovInternal=s.clamp(e,1,179),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))}clone(){const t=new l(this.horizontalFovInternal,this.verticalFovInternal,this.aspect,this.near,this.far);return t.copy(this,!0),t}}class w extends e{constructor(){super(...arguments),this.tempVector3A=new i}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()}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 m{static getGeometryHash(t,s=1e-6){const e=[],i=t.attributes,r=Object.keys(i).sort();for(const t of r){const r=i[t];e.push(`${t}:${r.itemSize}:${this.getAttributeHash(r,s)}`)}return t.index&&e.push("index:"+this.getAttributeHash(t.index,s)),e.join("|")}static compare(t,s,e=1e-6){return t.uuid===s.uuid||this.getGeometryHash(t,e)===this.getGeometryHash(s,e)}static getAttributeHash(t,s){const e=t.array,i="itemSize"in t?t.itemSize:1,r=[];for(let t=0;t<e.length;t+=i){const n=[];for(let r=0;r<i;r++)n.push(Math.round(e[t+r]/s)*s);r.push(n.join(","))}return r.join(";")}static compareBufferAttributes(t,s,e){return this.getAttributeHash(t,e)===this.getAttributeHash(s,e)}}class g{static getObjectByName(t,s){if(t.name===s)return t;for(const e of t.children){const t=g.getObjectByName(e,s);if(t)return t}return null}static getMaterialByName(t,s){if(t instanceof r)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=g.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)g.enumerateObjectsByType(i,s,e)}static enumerateMaterials(t,s){if(t instanceof r)if(Array.isArray(t.material))for(const e of t.material)s(e);else s(t.material);for(const e of t.children)g.enumerateMaterials(e,s)}static filterObjects(t,s){let e=[];t.name&&s.test(t.name)&&e.push(t);for(const i of t.children)e=e.concat(g.filterObjects(i,s));return e}static filterMaterials(t,s){let e=[];if(t instanceof r)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(g.filterMaterials(i,s));return e}static setShadowRecursive(t,s=!0,e=!0){(t instanceof r||"isMesh"in t)&&(t.castShadow=s,t.receiveShadow=e);for(const i of t.children)g.setShadowRecursive(i,s,e)}}class v{static assemble(t){var s,e;const i=new Map,h=[],o=null!==(s=t.geometryTolerance)&&void 0!==s?s:1e-6,c=new Map;g.enumerateObjectsByType(t.container,r,(s=>{var e;if(0===s.children.length&&(!t.filter||t.filter(s))){const t=Array.isArray(s.material)?s.material:[s.material];let r=c.get(s.geometry.uuid);r||(r=m.getGeometryHash(s.geometry,o),c.set(s.geometry.uuid,r));const n=`${r}|${t.map((t=>t.uuid)).join(",")}`,h=null!==(e=i.get(n))&&void 0!==e?e:{meshes:[],materials:t,castShadow:!1,receiveShadow:!1};s.castShadow&&(h.castShadow=!0),s.receiveShadow&&(h.receiveShadow=!0),h.meshes.push(s),i.set(n,h)}}));for(const t of i.values()){if(t.meshes.length<2)continue;const{meshes:s,materials:i,castShadow:r,receiveShadow:o}=t,c=s.sort(((t,s)=>t.name.localeCompare(s.name))),a=c[0],f=new n(a.geometry,1===i.length?i[0]:i,c.length);f.name=a.name,f.castShadow=r,f.receiveShadow=o;for(let t=0;t<c.length;t++){const s=c[t];s.updateWorldMatrix(!0,!1),f.setMatrixAt(t,s.matrixWorld),f.userData[s.uuid]=s.userData}f.instanceMatrix.needsUpdate=!0,h.push(f);for(const t of c)null===(e=t.parent)||void 0===e||e.remove(t)}h.length>0&&t.container.add(...h)}}class d{static process(t){const s=t.asset.clone();return v.assemble({container:s}),g.enumerateMaterials(s,(s=>{s.transparent=d.matchesAny(s.name,t.transparentMaterialNames),s.depthWrite=!d.matchesAny(s.name,t.noDepthWriteMaterialNames),s.side=h,s.forceSinglePass=!0,s.depthTest=!0})),g.enumerateObjectsByType(s,r,(s=>{s.castShadow=d.matchesAny(s.name,t.castShadowMeshNames),s.receiveShadow=d.matchesAny(s.name,t.receiveShadowMeshNames)})),s.children}static matchesAny(t,s=[]){return s.some((s=>"string"==typeof s?t===s:s.test(t)))}}class M{static bakePose(t){const s=t.geometry.clone(),e=s.attributes.position,n=new Float32Array(3*e.count),h=new i;for(let s=0;s<e.count;s++)h.fromBufferAttribute(e,s),t.applyBoneTransform(s,h),n[3*s+0]=h.x,n[3*s+1]=h.y,n[3*s+2]=h.z;s.setAttribute("position",new o(n,3)),s.computeVertexNormals(),s.deleteAttribute("skinIndex"),s.deleteAttribute("skinWeight");const c=new r(s,t.material);return c.name=t.name,c}static bakeAnimationFrame(t,s,e,i){const r=new c(t);return r.clipAction(i).play(),r.setTime(e),t.updateWorldMatrix(!0,!0),s.skeleton.update(),this.bakePose(s)}}class p extends a{constructor(){super(...arguments),this.tempVector3D0=new i,this.tempVector3D1=new i,this.tempVector3D2=new i,this.tempVector3D3=new i,this.tempVector3D4=new i,this.tempVector3D5=new i,this.tempVector3D6=new i,this.tempVector3D7=new i,this.tempBox3=new e,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 r=this.tempBox3.setFromPoints(e);s.left=r.min.x,s.bottom=r.min.y,s.near=-r.max.z,s.right=r.max.x,s.top=r.max.y,s.far=-r.min.z,s.updateWorldMatrix(!0,!1),s.updateProjectionMatrix()}setDirectionFromHDR(t,s=1){const e=t.image.data,i=t.image.width,r=t.image.height;let n=0,h=0;const o=t.format===u?4:3;for(let t=0;t<e.length;t+=o){const s=.2126*e[t]+.7152*e[t+1]+.0722*e[t+2];s>n&&(n=s,h=t)}const c=h/o,a=c%i;this.position.setFromSphericalCoords(s,Math.floor(c/i)/r*Math.PI,a/i*-Math.PI*2-Math.PI/2)}}export{l as BiFovCamera,w as Bounds,v as InstanceAssembler,d as SceneProcessor,g as SceneTraversal,M as SkinnedMeshBaker,p as Sun};
|
|
2
|
+
//# sourceMappingURL=index.min.js.map
|
|
@@ -0,0 +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\n/**\n * Default camera settings\n */\nconst DEFAULT_HORIZONTAL_FOV = 90;\nconst DEFAULT_VERTICAL_FOV = 90;\nconst DEFAULT_ASPECT = 1;\nconst DEFAULT_NEAR = 1;\nconst DEFAULT_FAR = 1000;\n\n/**\n * BiFovCamera - A specialized PerspectiveCamera that supports independent horizontal and vertical FOV settings\n *\n * This camera extends Three.js PerspectiveCamera to provide better control over the field of view,\n * allowing separate horizontal and vertical FOV values. The camera automatically adjusts its projection\n * matrix based on the aspect ratio to maintain proper perspective.\n *\n * @extends PerspectiveCamera\n */\nexport class BiFovCamera extends PerspectiveCamera {\n private horizontalFovInternal: number;\n private verticalFovInternal: number;\n\n /**\n * Creates a new BiFovCamera instance\n *\n * @param horizontalFov - Horizontal field of view in degrees (default: 90)\n * @param verticalFov - Vertical field of view in degrees (default: 90)\n * @param aspect - Aspect ratio (width/height) of the viewport (default: 1)\n * @param near - Near clipping plane distance (default: 1)\n * @param far - Far clipping plane distance (default: 1000)\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 /**\n * Gets the horizontal field of view in degrees\n */\n public get horizontalFov(): number {\n return this.horizontalFovInternal;\n }\n\n /**\n * Gets the vertical field of view in degrees\n */\n public get verticalFov(): number {\n return this.verticalFovInternal;\n }\n\n /**\n * Sets the horizontal field of view in degrees\n * @param value - The new horizontal FOV value\n */\n public set horizontalFov(value: number) {\n this.horizontalFovInternal = MathUtils.clamp(value, 1, 179);\n this.updateProjectionMatrix();\n }\n\n /**\n * Sets the vertical field of view in degrees\n * @param value - The new vertical FOV value\n */\n public set verticalFov(value: number) {\n this.verticalFovInternal = MathUtils.clamp(value, 1, 179);\n this.updateProjectionMatrix();\n }\n\n /**\n * Updates both horizontal and vertical FOV simultaneously\n * @param horizontal - New horizontal FOV in degrees\n * @param vertical - New vertical FOV in degrees\n */\n public setFov(horizontal: number, vertical: number): void {\n this.horizontalFovInternal = MathUtils.clamp(horizontal, 1, 179);\n this.verticalFovInternal = MathUtils.clamp(vertical, 1, 179);\n this.updateProjectionMatrix();\n }\n\n /**\n * Copies FOV settings from another BiFovCamera\n * @param source - The camera to copy settings 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 current FOV settings and aspect ratio\n * For aspect ratios >= 1 (landscape), horizontal FOV is preserved\n * For aspect ratios < 1 (portrait), vertical FOV is preserved\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 /**\n * Returns the actual horizontal FOV after aspect ratio adjustments\n */\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 /**\n * Returns the actual vertical FOV after aspect ratio adjustments\n */\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 /**\n * Creates a clone of this camera with the same properties\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 { Box3, Vector3 } from \"three\";\n\nexport class Bounds extends Box3 {\n private readonly tempVector3A: Vector3 = new Vector3();\n\n /**\n * Gets the width (x-axis length) of the bounding box\n */\n public get width(): number {\n return this.max.x - this.min.x;\n }\n\n /**\n * Gets the height (y-axis length) of the bounding box\n */\n public get height(): number {\n return this.max.y - this.min.y;\n }\n\n /**\n * Gets the depth (z-axis length) of the bounding box\n */\n public get depth(): number {\n return this.max.z - this.min.z;\n }\n\n /**\n * Gets the length of the box's diagonal\n */\n public get diagonal(): number {\n return this.tempVector3A.subVectors(this.max, this.min).length();\n }\n\n /**\n * Gets the volume of the bounding box\n */\n public getVolume(): number {\n return this.width * this.height * this.depth;\n }\n\n /**\n * Gets the surface area of the bounding box\n */\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 {\n BufferAttribute,\n BufferGeometry,\n InterleavedBufferAttribute,\n} from \"three\";\n\ntype AnySuitableAttribute = BufferAttribute | InterleavedBufferAttribute;\n\n/**\n * Utility class for comparing and hashing BufferGeometry instances with tolerance support.\n */\nexport class GeometryHasher {\n /**\n * Generates a consistent hash for a BufferGeometry based on its contents and tolerance.\n *\n * @param geometry - The geometry to hash\n * @param tolerance - Precision level for number comparison (values within tolerance are considered equal)\n * @returns A string hash that will be identical for geometrically equivalent geometries\n */\n public static getGeometryHash(\n geometry: BufferGeometry,\n tolerance = 1e-6,\n ): string {\n const hashParts: string[] = [];\n\n // Process attributes\n const attributes = geometry.attributes;\n const attributeNames = Object.keys(attributes).sort(); // Sort for consistent order\n\n for (const name of attributeNames) {\n const attribute = attributes[name] as AnySuitableAttribute;\n hashParts.push(\n `${name}:${attribute.itemSize}:${this.getAttributeHash(attribute, tolerance)}`,\n );\n }\n\n // Process index if present\n if (geometry.index) {\n hashParts.push(\n `index:${this.getAttributeHash(geometry.index, tolerance)}`,\n );\n }\n\n return hashParts.join(\"|\");\n }\n\n /**\n * Compares two BufferGeometry instances for approximate equality.\n * Early exit if UUIDs match (same object or cloned geometry).\n */\n public static compare(\n firstGeometry: BufferGeometry,\n secondGeometry: BufferGeometry,\n tolerance = 1e-6,\n ): boolean {\n if (firstGeometry.uuid === secondGeometry.uuid) {\n return true;\n }\n\n // Use hash comparison for consistent results\n return (\n this.getGeometryHash(firstGeometry, tolerance) ===\n this.getGeometryHash(secondGeometry, tolerance)\n );\n }\n\n /**\n * Generates a hash for a buffer attribute with tolerance.\n */\n private static getAttributeHash(\n attribute: AnySuitableAttribute,\n tolerance: number,\n ): string {\n const array = attribute.array;\n const itemSize = \"itemSize\" in attribute ? attribute.itemSize : 1;\n const hashParts: string[] = [];\n\n // Group values by their \"tolerance buckets\"\n for (let i = 0; i < array.length; i += itemSize) {\n const itemValues = [];\n for (let j = 0; j < itemSize; j++) {\n const val = array[i + j];\n // Round to nearest tolerance multiple to group similar values\n itemValues.push(Math.round(val / tolerance) * tolerance);\n }\n hashParts.push(itemValues.join(\",\"));\n }\n\n return hashParts.join(\";\");\n }\n\n /**\n * Compares two buffer attributes with tolerance.\n */\n private static compareBufferAttributes(\n firstAttribute: AnySuitableAttribute,\n secondAttribute: AnySuitableAttribute,\n tolerance: number,\n ): boolean {\n return (\n this.getAttributeHash(firstAttribute, tolerance) ===\n this.getAttributeHash(secondAttribute, tolerance)\n );\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { Mesh } from \"three\";\n\ntype Constructor<T> = abstract new (...args: never[]) => T;\n\nexport class SceneTraversal {\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 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 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 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 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 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 public static setShadowRecursive(\n object: Object3D,\n castShadow = true,\n receiveShadow = true,\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(child, castShadow, receiveShadow);\n }\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { InstancedMesh, Mesh } from \"three\";\nimport { GeometryHasher } from \"./GeometryHasher\";\nimport { SceneTraversal } from \"./SceneTraversal\";\n\ninterface IMeshDescriptor {\n meshes: Mesh[];\n materials: Material[];\n castShadow: boolean;\n receiveShadow: boolean;\n}\n\ninterface IOptions {\n container: Object3D;\n filter?: (child: Mesh) => boolean;\n geometryTolerance?: number;\n}\n\nexport class InstanceAssembler {\n public static assemble(options: IOptions): void {\n const dictionary = new Map<string, IMeshDescriptor>();\n const instancedMeshes: InstancedMesh[] = [];\n const tolerance = options.geometryTolerance ?? 1e-6;\n const geometryHashCache = new Map<string, string>();\n\n SceneTraversal.enumerateObjectsByType(\n options.container,\n Mesh,\n (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 = geometryHashCache.get(child.geometry.uuid);\n if (!geometryHash) {\n geometryHash = GeometryHasher.getGeometryHash(\n child.geometry,\n tolerance,\n );\n geometryHashCache.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: materials,\n castShadow: false,\n receiveShadow: false,\n };\n\n if (child.castShadow) {\n entry.castShadow = true;\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\n for (const descriptor of dictionary.values()) {\n if (descriptor.meshes.length < 2) {\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 instancedMeshes.push(instancedMesh);\n\n for (const mesh of sortedMeshes) {\n mesh.parent?.remove(mesh);\n }\n }\n\n if (instancedMeshes.length > 0) {\n options.container.add(...instancedMeshes);\n }\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { FrontSide, Mesh } from \"three\";\nimport { InstanceAssembler } from \"./InstanceAssembler\";\nimport { SceneTraversal } from \"./SceneTraversal\";\n\ntype IPattern = string | RegExp;\n\ninterface IOptions {\n asset: Object3D;\n castShadowMeshNames?: IPattern[];\n receiveShadowMeshNames?: IPattern[];\n transparentMaterialNames?: IPattern[];\n noDepthWriteMaterialNames?: IPattern[];\n}\n\nexport class SceneProcessor {\n public static process(options: IOptions): Object3D[] {\n const container = options.asset.clone();\n InstanceAssembler.assemble({ container: container });\n\n SceneTraversal.enumerateMaterials(container, (material: Material) => {\n material.transparent = SceneProcessor.matchesAny(\n material.name,\n options.transparentMaterialNames,\n );\n material.depthWrite = !SceneProcessor.matchesAny(\n material.name,\n options.noDepthWriteMaterialNames,\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.castShadowMeshNames,\n );\n child.receiveShadow = SceneProcessor.matchesAny(\n child.name,\n options.receiveShadowMeshNames,\n );\n });\n\n return container.children;\n }\n\n private static matchesAny(value: string, patterns: IPattern[] = []): boolean {\n return patterns.some((p) =>\n typeof p === \"string\" ? value === p : p.test(value),\n );\n }\n}\n","import type { AnimationClip, Object3D, SkinnedMesh } from \"three\";\nimport { AnimationMixer, BufferAttribute, Mesh, Vector3 } from \"three\";\n\n/**\n * Utilities for baking poses and animations from SkinnedMesh into a regular static Mesh.\n */\nexport class SkinnedMeshBaker {\n /**\n * Bakes the current pose of a SkinnedMesh into a regular geometry.\n * Transforms all vertices according to the current skeleton state.\n *\n * @param skinnedMesh - SkinnedMesh from which to bake the geometry\n * @returns A new Mesh with positions corresponding to the current bone 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 * 3);\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 * 3 + 0] = target.x;\n newPositions[i * 3 + 1] = target.y;\n newPositions[i * 3 + 2] = target.z;\n }\n\n bakedGeometry.setAttribute(\n \"position\",\n new BufferAttribute(newPositions, 3),\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 * Bakes a SkinnedMesh in a specific pose derived from an AnimationClip at the given timestamp.\n *\n * @param armature - The parent object (typically an armature from GLTF) containing the bones\n * @param skinnedMesh - The SkinnedMesh to be baked\n * @param timeOffset - The animation time in seconds to set\n * @param clip - The animation clip\n * @returns A new Mesh with geometry matching the specified animation frame\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}\n","import type { Texture } from \"three\";\nimport { Box3, DirectionalLight, RGBAFormat, Spherical, Vector3 } from \"three\";\n\n/**\n * Sun extends Three.js DirectionalLight to provide a specialized light source that simulates\n * sunlight with advanced positioning and shadow controls.\n * \n * Features:\n * - Spherical coordinate control (distance, elevation, azimuth)\n * - Automatic shadow map configuration based on bounding boxes\n * - HDR environment map-based positioning\n * - Efficient temporary vector management for calculations\n * \n * @extends DirectionalLight\n */\nexport class Sun extends DirectionalLight {\n // Temporary vectors for calculations 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\n private readonly tempBox3 = new Box3();\n private readonly tempSpherical = new Spherical();\n\n /**\n * Gets the distance of the sun from its target (radius in spherical coordinates)\n * @returns The distance in world units\n */\n public get distance(): number {\n return this.position.length();\n }\n\n /**\n * Gets the elevation angle of the sun (phi in spherical coordinates)\n * @returns The elevation in radians\n */\n public get elevation(): number {\n return this.tempSpherical.setFromVector3(this.position).phi;\n }\n\n /**\n * Gets the azimuth angle of the sun (theta in spherical coordinates)\n * @returns The azimuth in radians\n */\n public get azimuth(): number {\n return this.tempSpherical.setFromVector3(this.position).theta;\n }\n\n /**\n * Sets the distance of the sun from its target while maintaining current angles\n * @param value - The new distance in world units\n */\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 /**\n * Sets the elevation angle of the sun while maintaining current distance and azimuth\n * @param value - The new elevation in radians\n */\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 /**\n * Sets the azimuth angle of the sun while maintaining current distance and elevation\n * @param value - The new azimuth in radians\n */\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 /**\n * Configures the shadow camera's frustum to encompass the given bounding box\n * This ensures that shadows are cast correctly for objects within the box\n * \n * @param box3 - The bounding box to configure shadows for\n */\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 /**\n * Sets the sun's direction based on the brightest point in an HDR texture\n * This is useful for matching the sun's position to an environment map\n * \n * @param texture - The HDR texture to analyze (must be loaded and have valid image data)\n * @param distance - Optional distance to position the sun from its target (default: 1)\n */\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 the brightest pixel in the HDR texture\n const step = texture.format === RGBAFormat ? 4 : 3;\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 // Calculate luminance using the Rec. 709 coefficients\n const luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;\n if (luminance > maxLuminance) {\n maxLuminance = luminance;\n maxIndex = i;\n }\n }\n\n // Convert pixel coordinates 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}"],"names":["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","tempVector3A","Vector3","width","max","x","min","height","y","depth","z","diagonal","subVectors","length","getVolume","getSurfaceArea","w","h","d","GeometryHasher","getGeometryHash","geometry","tolerance","hashParts","attributes","attributeNames","Object","keys","sort","name","attribute","push","itemSize","getAttributeHash","index","join","compare","firstGeometry","secondGeometry","uuid","array","i","itemValues","j","round","compareBufferAttributes","firstAttribute","secondAttribute","SceneTraversal","getObjectByName","object","child","children","result","getMaterialByName","Mesh","Array","isArray","material","enumerateObjectsByType","type","callback","enumerateMaterials","filterObjects","test","concat","filterMaterials","setShadowRecursive","castShadow","receiveShadow","InstanceAssembler","assemble","options","dictionary","Map","instancedMeshes","_a","geometryTolerance","geometryHashCache","container","filter","materials","geometryHash","get","set","compositeKey","map","m","entry","meshes","descriptor","values","sortedMeshes","a","b","localeCompare","defaultMesh","instancedMesh","InstancedMesh","mesh","updateWorldMatrix","setMatrixAt","matrixWorld","userData","instanceMatrix","needsUpdate","_b","parent","remove","add","SceneProcessor","process","asset","transparent","matchesAny","transparentMaterialNames","depthWrite","noDepthWriteMaterialNames","side","FrontSide","forceSinglePass","depthTest","castShadowMeshNames","receiveShadowMeshNames","patterns","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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"}
|
package/package.json
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "three-zoo",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "zoo of tiny three js tools",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"clean": "rm -rf dist",
|
|
7
|
-
"build": "npm run clean && rollup -c"
|
|
7
|
+
"build": "npm run clean && rollup -c",
|
|
8
|
+
"build:prod": "npm run clean && NODE_ENV=production rollup -c",
|
|
9
|
+
"prepublishOnly": "npm run build:prod"
|
|
8
10
|
},
|
|
9
11
|
"main": "dist/index.js",
|
|
12
|
+
"module": "dist/index.js",
|
|
10
13
|
"types": "dist/index.d.ts",
|
|
11
14
|
"exports": {
|
|
12
15
|
".": {
|
|
13
|
-
"
|
|
14
|
-
"
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"import": {
|
|
18
|
+
"development": "./dist/index.js",
|
|
19
|
+
"production": "./dist/index.min.js",
|
|
20
|
+
"default": "./dist/index.min.js"
|
|
21
|
+
}
|
|
15
22
|
}
|
|
16
23
|
},
|
|
17
24
|
"files": [
|
|
@@ -30,6 +37,7 @@
|
|
|
30
37
|
},
|
|
31
38
|
"devDependencies": {
|
|
32
39
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
40
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
33
41
|
"@types/three": "^0.176.0",
|
|
34
42
|
"@typescript-eslint/eslint-plugin": "^8.32.0",
|
|
35
43
|
"@typescript-eslint/parser": "^8.32.0",
|