three-zoo 0.5.5 → 0.5.6
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/DualFovCamera.d.ts +33 -72
- package/dist/SceneTraversal.d.ts +48 -65
- package/dist/SkinnedMeshBaker.d.ts +7 -8
- package/dist/StandardToBasicConverter.d.ts +11 -33
- package/dist/StandardToLambertConverter.d.ts +10 -28
- package/dist/Sun.d.ts +12 -35
- package/dist/index.js +179 -281
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15,19 +15,15 @@ const MIN_FOV = 1;
|
|
|
15
15
|
/** Maximum allowed field of view in degrees */
|
|
16
16
|
const MAX_FOV = 179;
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
19
|
-
* Extends Three.js PerspectiveCamera to allow separate control over horizontal
|
|
20
|
-
* and vertical fields of view.
|
|
18
|
+
* Camera with independent horizontal and vertical FOV settings.
|
|
21
19
|
*/
|
|
22
20
|
class DualFovCamera extends PerspectiveCamera {
|
|
23
21
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* @param
|
|
27
|
-
* @param
|
|
28
|
-
* @param
|
|
29
|
-
* @param near - Near clipping plane distance.
|
|
30
|
-
* @param far - Far clipping plane distance.
|
|
22
|
+
* @param horizontalFov - Horizontal FOV in degrees (clamped 1-179°)
|
|
23
|
+
* @param verticalFov - Vertical FOV in degrees (clamped 1-179°)
|
|
24
|
+
* @param aspect - Aspect ratio (width/height)
|
|
25
|
+
* @param near - Near clipping plane distance
|
|
26
|
+
* @param far - Far clipping plane distance
|
|
31
27
|
*/
|
|
32
28
|
constructor(horizontalFov = DEFAULT_HORIZONTAL_FOV, verticalFov = DEFAULT_VERTICAL_FOV, aspect = DEFAULT_ASPECT, near = DEFAULT_NEAR, far = DEFAULT_FAR) {
|
|
33
29
|
super(verticalFov, aspect, near, far);
|
|
@@ -36,44 +32,36 @@ class DualFovCamera extends PerspectiveCamera {
|
|
|
36
32
|
this.updateProjectionMatrix();
|
|
37
33
|
}
|
|
38
34
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* @returns The horizontal FOV value
|
|
35
|
+
* @returns Horizontal FOV in degrees
|
|
42
36
|
*/
|
|
43
37
|
get horizontalFov() {
|
|
44
38
|
return this._private_horizontalFovInternal;
|
|
45
39
|
}
|
|
46
40
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* @returns The vertical FOV value
|
|
41
|
+
* @returns Vertical FOV in degrees
|
|
50
42
|
*/
|
|
51
43
|
get verticalFov() {
|
|
52
44
|
return this._private_verticalFovInternal;
|
|
53
45
|
}
|
|
54
46
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* @param value - The horizontal FOV value in degrees. Clamped between 1° and 179°.
|
|
47
|
+
* @param value - Horizontal FOV in degrees (clamped 1-179°)
|
|
58
48
|
*/
|
|
59
49
|
set horizontalFov(value) {
|
|
60
50
|
this._private_horizontalFovInternal = MathUtils.clamp(value, MIN_FOV, MAX_FOV);
|
|
61
51
|
this.updateProjectionMatrix();
|
|
62
52
|
}
|
|
63
53
|
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* @param value - The vertical FOV value in degrees. Clamped between 1° and 179°.
|
|
54
|
+
* @param value - Vertical FOV in degrees (clamped 1-179°)
|
|
67
55
|
*/
|
|
68
56
|
set verticalFov(value) {
|
|
69
57
|
this._private_verticalFovInternal = MathUtils.clamp(value, MIN_FOV, MAX_FOV);
|
|
70
58
|
this.updateProjectionMatrix();
|
|
71
59
|
}
|
|
72
60
|
/**
|
|
73
|
-
* Sets both
|
|
61
|
+
* Sets both FOV values.
|
|
74
62
|
*
|
|
75
|
-
* @param horizontal - Horizontal FOV in degrees
|
|
76
|
-
* @param vertical - Vertical FOV in degrees
|
|
63
|
+
* @param horizontal - Horizontal FOV in degrees (clamped 1-179°)
|
|
64
|
+
* @param vertical - Vertical FOV in degrees (clamped 1-179°)
|
|
77
65
|
*/
|
|
78
66
|
setFov(horizontal, vertical) {
|
|
79
67
|
this._private_horizontalFovInternal = MathUtils.clamp(horizontal, MIN_FOV, MAX_FOV);
|
|
@@ -81,9 +69,9 @@ class DualFovCamera extends PerspectiveCamera {
|
|
|
81
69
|
this.updateProjectionMatrix();
|
|
82
70
|
}
|
|
83
71
|
/**
|
|
84
|
-
* Copies
|
|
72
|
+
* Copies FOV settings from another DualFovCamera.
|
|
85
73
|
*
|
|
86
|
-
* @param source -
|
|
74
|
+
* @param source - Source camera to copy from
|
|
87
75
|
*/
|
|
88
76
|
copyFovSettings(source) {
|
|
89
77
|
this._private_horizontalFovInternal = source.horizontalFov;
|
|
@@ -91,13 +79,10 @@ class DualFovCamera extends PerspectiveCamera {
|
|
|
91
79
|
this.updateProjectionMatrix();
|
|
92
80
|
}
|
|
93
81
|
/**
|
|
94
|
-
* Updates
|
|
82
|
+
* Updates projection matrix based on FOV and aspect ratio.
|
|
95
83
|
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* - **Portrait mode (aspect ≤ 1)**: Preserves vertical FOV, calculates horizontal FOV
|
|
99
|
-
*
|
|
100
|
-
* Called when FOV values or aspect ratio changes.
|
|
84
|
+
* Landscape (aspect > 1): preserves horizontal FOV.
|
|
85
|
+
* Portrait (aspect ≤ 1): preserves vertical FOV.
|
|
101
86
|
*
|
|
102
87
|
* @override
|
|
103
88
|
*/
|
|
@@ -114,12 +99,9 @@ class DualFovCamera extends PerspectiveCamera {
|
|
|
114
99
|
super.updateProjectionMatrix();
|
|
115
100
|
}
|
|
116
101
|
/**
|
|
117
|
-
* Gets
|
|
118
|
-
*
|
|
119
|
-
* In landscape mode, returns the set horizontal FOV.
|
|
120
|
-
* In portrait mode, calculates the horizontal FOV from vertical FOV and aspect ratio.
|
|
102
|
+
* Gets actual horizontal FOV after aspect ratio adjustments.
|
|
121
103
|
*
|
|
122
|
-
* @returns
|
|
104
|
+
* @returns Horizontal FOV in degrees
|
|
123
105
|
*/
|
|
124
106
|
getActualHorizontalFov() {
|
|
125
107
|
if (this.aspect >= 1) {
|
|
@@ -129,12 +111,9 @@ class DualFovCamera extends PerspectiveCamera {
|
|
|
129
111
|
return MathUtils.radToDeg(Math.atan(Math.tan(verticalRadians / 2) * this.aspect) * 2);
|
|
130
112
|
}
|
|
131
113
|
/**
|
|
132
|
-
* Gets
|
|
114
|
+
* Gets actual vertical FOV after aspect ratio adjustments.
|
|
133
115
|
*
|
|
134
|
-
*
|
|
135
|
-
* In landscape mode, calculates the vertical FOV from horizontal FOV and aspect ratio.
|
|
136
|
-
*
|
|
137
|
-
* @returns The vertical FOV in degrees
|
|
116
|
+
* @returns Vertical FOV in degrees
|
|
138
117
|
*/
|
|
139
118
|
getActualVerticalFov() {
|
|
140
119
|
if (this.aspect < 1) {
|
|
@@ -144,10 +123,7 @@ class DualFovCamera extends PerspectiveCamera {
|
|
|
144
123
|
return MathUtils.radToDeg(Math.atan(Math.tan(horizontalRadians / 2) / this.aspect) * 2);
|
|
145
124
|
}
|
|
146
125
|
/**
|
|
147
|
-
* Adjusts
|
|
148
|
-
*
|
|
149
|
-
* Calculates the required vertical FOV to ensure all provided vertices
|
|
150
|
-
* are visible within the vertical bounds of the camera's frustum.
|
|
126
|
+
* Adjusts vertical FOV to fit points within camera view.
|
|
151
127
|
*
|
|
152
128
|
* @param vertices - Array of 3D points in world coordinates
|
|
153
129
|
*/
|
|
@@ -168,12 +144,9 @@ class DualFovCamera extends PerspectiveCamera {
|
|
|
168
144
|
this.updateProjectionMatrix();
|
|
169
145
|
}
|
|
170
146
|
/**
|
|
171
|
-
* Adjusts
|
|
147
|
+
* Adjusts vertical FOV to fit bounding box within camera view.
|
|
172
148
|
*
|
|
173
|
-
*
|
|
174
|
-
* is visible within the vertical bounds of the camera's frustum.
|
|
175
|
-
*
|
|
176
|
-
* @param box - The 3D bounding box in world coordinates
|
|
149
|
+
* @param box - 3D bounding box in world coordinates
|
|
177
150
|
*/
|
|
178
151
|
fitVerticalFovToBox(box) {
|
|
179
152
|
this.fitVerticalFovToPoints([
|
|
@@ -188,13 +161,10 @@ class DualFovCamera extends PerspectiveCamera {
|
|
|
188
161
|
]);
|
|
189
162
|
}
|
|
190
163
|
/**
|
|
191
|
-
* Adjusts
|
|
192
|
-
*
|
|
193
|
-
* Updates the mesh's skeleton, applies bone transformations to vertices,
|
|
194
|
-
* and calculates the required vertical FOV to fit the deformed mesh
|
|
195
|
-
* within the vertical bounds of the camera's frustum.
|
|
164
|
+
* Adjusts vertical FOV to fit skinned mesh within camera view.
|
|
165
|
+
* Updates skeleton and applies bone transformations.
|
|
196
166
|
*
|
|
197
|
-
* @param skinnedMesh -
|
|
167
|
+
* @param skinnedMesh - Skinned mesh with active skeleton
|
|
198
168
|
*/
|
|
199
169
|
fitVerticalFovToMesh(skinnedMesh) {
|
|
200
170
|
skinnedMesh.updateWorldMatrix(true, true);
|
|
@@ -211,16 +181,10 @@ class DualFovCamera extends PerspectiveCamera {
|
|
|
211
181
|
this.fitVerticalFovToPoints(points);
|
|
212
182
|
}
|
|
213
183
|
/**
|
|
214
|
-
* Points
|
|
215
|
-
*
|
|
216
|
-
* Updates the mesh's skeleton, applies bone transformations to vertices,
|
|
217
|
-
* calculates the center of mass using a clustering algorithm, and orients the camera
|
|
218
|
-
* to look at that point.
|
|
219
|
-
*
|
|
220
|
-
* The center of mass calculation uses iterative clustering to find the
|
|
221
|
-
* main concentration of vertices.
|
|
184
|
+
* Points camera to look at skinned mesh center of mass.
|
|
185
|
+
* Uses iterative clustering to find main vertex concentration.
|
|
222
186
|
*
|
|
223
|
-
* @param skinnedMesh -
|
|
187
|
+
* @param skinnedMesh - Skinned mesh with active skeleton
|
|
224
188
|
*/
|
|
225
189
|
lookAtMeshCenterOfMass(skinnedMesh) {
|
|
226
190
|
skinnedMesh.updateWorldMatrix(true, true);
|
|
@@ -235,11 +199,11 @@ class DualFovCamera extends PerspectiveCamera {
|
|
|
235
199
|
points.push(target.clone());
|
|
236
200
|
}
|
|
237
201
|
/**
|
|
238
|
-
* Finds
|
|
202
|
+
* Finds main cluster center using iterative refinement.
|
|
239
203
|
*
|
|
240
204
|
* @param points - Array of 3D points to cluster
|
|
241
205
|
* @param iterations - Number of refinement iterations
|
|
242
|
-
* @returns
|
|
206
|
+
* @returns Center point of main cluster
|
|
243
207
|
*/
|
|
244
208
|
const findMainCluster = (points, iterations = 3) => {
|
|
245
209
|
if (points.length === 0) {
|
|
@@ -266,12 +230,9 @@ class DualFovCamera extends PerspectiveCamera {
|
|
|
266
230
|
this.lookAt(centerOfMass);
|
|
267
231
|
}
|
|
268
232
|
/**
|
|
269
|
-
* Creates a copy of this
|
|
233
|
+
* Creates a copy of this camera with identical settings.
|
|
270
234
|
*
|
|
271
|
-
*
|
|
272
|
-
* and all other camera properties.
|
|
273
|
-
*
|
|
274
|
-
* @returns A new DualFovCamera instance
|
|
235
|
+
* @returns New DualFovCamera instance
|
|
275
236
|
* @override
|
|
276
237
|
*/
|
|
277
238
|
clone() {
|
|
@@ -282,25 +243,17 @@ class DualFovCamera extends PerspectiveCamera {
|
|
|
282
243
|
}
|
|
283
244
|
|
|
284
245
|
/**
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
* Provides static methods for traversing Three.js scene hierarchies,
|
|
288
|
-
* searching for objects or materials, and performing batch operations.
|
|
246
|
+
* Static methods for traversing Three.js scene hierarchies.
|
|
289
247
|
*
|
|
290
|
-
* All methods
|
|
291
|
-
* root object and recursively processing all children.
|
|
248
|
+
* All methods use depth-first traversal.
|
|
292
249
|
*/
|
|
293
250
|
class SceneTraversal {
|
|
294
251
|
/**
|
|
295
|
-
* Finds
|
|
252
|
+
* Finds first object with exact name match.
|
|
296
253
|
*
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
*
|
|
301
|
-
* @param object - The root Object3D to start searching from
|
|
302
|
-
* @param name - The exact name to search for (case-sensitive)
|
|
303
|
-
* @returns The first matching Object3D, or null if no match is found
|
|
254
|
+
* @param object - Root object to start from
|
|
255
|
+
* @param name - Name to search for (case-sensitive)
|
|
256
|
+
* @returns First matching object or null
|
|
304
257
|
*/
|
|
305
258
|
static getObjectByName(object, name) {
|
|
306
259
|
if (object.name === name) {
|
|
@@ -315,15 +268,11 @@ class SceneTraversal {
|
|
|
315
268
|
return null;
|
|
316
269
|
}
|
|
317
270
|
/**
|
|
318
|
-
* Finds
|
|
319
|
-
*
|
|
320
|
-
* Performs depth-first search through the scene graph, examining materials
|
|
321
|
-
* attached to Mesh objects. Handles both single materials and material arrays.
|
|
322
|
-
* Returns the first material whose name property matches the search string.
|
|
271
|
+
* Finds first material with exact name match from mesh objects.
|
|
323
272
|
*
|
|
324
|
-
* @param object -
|
|
325
|
-
* @param name -
|
|
326
|
-
* @returns
|
|
273
|
+
* @param object - Root object to start from
|
|
274
|
+
* @param name - Material name to search for (case-sensitive)
|
|
275
|
+
* @returns First matching material or null
|
|
327
276
|
*/
|
|
328
277
|
static getMaterialByName(object, name) {
|
|
329
278
|
if (object instanceof Mesh) {
|
|
@@ -347,15 +296,12 @@ class SceneTraversal {
|
|
|
347
296
|
return null;
|
|
348
297
|
}
|
|
349
298
|
/**
|
|
350
|
-
*
|
|
299
|
+
* Executes callback for all objects of specified type.
|
|
351
300
|
*
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
355
|
-
* @
|
|
356
|
-
* @param object - The root Object3D to start searching from
|
|
357
|
-
* @param type - The constructor/class to filter by (e.g., DirectionalLight, Mesh)
|
|
358
|
-
* @param callback - Function to execute for each matching object instance
|
|
301
|
+
* @template T - Type of objects to process
|
|
302
|
+
* @param object - Root object to start from
|
|
303
|
+
* @param type - Constructor to filter by
|
|
304
|
+
* @param callback - Function to execute for each matching object
|
|
359
305
|
*/
|
|
360
306
|
static enumerateObjectsByType(object, type, callback) {
|
|
361
307
|
if (object instanceof type) {
|
|
@@ -366,14 +312,47 @@ class SceneTraversal {
|
|
|
366
312
|
}
|
|
367
313
|
}
|
|
368
314
|
/**
|
|
369
|
-
*
|
|
315
|
+
* Executes callback for all materials of specified type from mesh objects.
|
|
370
316
|
*
|
|
371
|
-
*
|
|
372
|
-
*
|
|
373
|
-
*
|
|
317
|
+
* @template T - Type of materials to process
|
|
318
|
+
* @param object - Root object to start from
|
|
319
|
+
* @param type - Constructor to filter by
|
|
320
|
+
* @param callback - Function to execute for each matching material
|
|
321
|
+
*/
|
|
322
|
+
static enumerateMaterialsByType(object, type, callback) {
|
|
323
|
+
if (object instanceof Mesh) {
|
|
324
|
+
if (Array.isArray(object.material)) {
|
|
325
|
+
for (const material of object.material) {
|
|
326
|
+
if (material instanceof type) {
|
|
327
|
+
callback(material);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
else if (object.material instanceof type) {
|
|
332
|
+
callback(object.material);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
for (const child of object.children) {
|
|
336
|
+
SceneTraversal.enumerateMaterialsByType(child, type, callback);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Executes callback for all objects in hierarchy.
|
|
374
341
|
*
|
|
375
|
-
* @param object -
|
|
376
|
-
* @param callback - Function to execute for each
|
|
342
|
+
* @param object - Root object to start from
|
|
343
|
+
* @param callback - Function to execute for each object
|
|
344
|
+
*/
|
|
345
|
+
static enumerateObjects(object, callback) {
|
|
346
|
+
callback(object);
|
|
347
|
+
for (const child of object.children) {
|
|
348
|
+
SceneTraversal.enumerateObjects(child, callback);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Executes callback for all materials from mesh objects.
|
|
353
|
+
*
|
|
354
|
+
* @param object - Root object to start from
|
|
355
|
+
* @param callback - Function to execute for each material
|
|
377
356
|
*/
|
|
378
357
|
static enumerateMaterials(object, callback) {
|
|
379
358
|
if (object instanceof Mesh) {
|
|
@@ -391,15 +370,11 @@ class SceneTraversal {
|
|
|
391
370
|
}
|
|
392
371
|
}
|
|
393
372
|
/**
|
|
394
|
-
*
|
|
395
|
-
*
|
|
396
|
-
* Performs depth-first search and collects all objects that either match
|
|
397
|
-
* a regular expression pattern (applied to object names) or satisfy
|
|
398
|
-
* a predicate function.
|
|
373
|
+
* Returns all objects matching filter criteria.
|
|
399
374
|
*
|
|
400
|
-
* @param object -
|
|
401
|
-
* @param filter -
|
|
402
|
-
* @returns Array of
|
|
375
|
+
* @param object - Root object to start from
|
|
376
|
+
* @param filter - RegExp for object names or predicate function
|
|
377
|
+
* @returns Array of matching objects
|
|
403
378
|
*/
|
|
404
379
|
static filterObjects(object, filter) {
|
|
405
380
|
let result = [];
|
|
@@ -419,63 +394,62 @@ class SceneTraversal {
|
|
|
419
394
|
return result;
|
|
420
395
|
}
|
|
421
396
|
/**
|
|
422
|
-
*
|
|
397
|
+
* Returns all materials matching filter criteria from mesh objects.
|
|
423
398
|
*
|
|
424
|
-
*
|
|
425
|
-
*
|
|
426
|
-
*
|
|
427
|
-
*
|
|
428
|
-
* @param object - The root Object3D to start searching from
|
|
429
|
-
* @param name - Regular expression pattern to test against material names
|
|
430
|
-
* @returns Array of all matching Material instances
|
|
399
|
+
* @param object - Root object to start from
|
|
400
|
+
* @param filter - RegExp for material names or predicate function
|
|
401
|
+
* @returns Array of matching materials
|
|
431
402
|
*/
|
|
432
|
-
static filterMaterials(object,
|
|
403
|
+
static filterMaterials(object, filter) {
|
|
433
404
|
let result = [];
|
|
434
405
|
if (object instanceof Mesh) {
|
|
435
406
|
if (Array.isArray(object.material)) {
|
|
436
407
|
for (const material of object.material) {
|
|
437
|
-
if (
|
|
408
|
+
if (typeof filter === "function") {
|
|
409
|
+
if (filter(material)) {
|
|
410
|
+
result.push(material);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
else if (filter.test(material.name)) {
|
|
438
414
|
result.push(material);
|
|
439
415
|
}
|
|
440
416
|
}
|
|
441
417
|
}
|
|
442
|
-
else {
|
|
443
|
-
if (object.material
|
|
444
|
-
name.test(object.material.name)) {
|
|
418
|
+
else if (typeof filter === "function") {
|
|
419
|
+
if (filter(object.material)) {
|
|
445
420
|
result.push(object.material);
|
|
446
421
|
}
|
|
447
422
|
}
|
|
423
|
+
else if (filter.test(object.material.name)) {
|
|
424
|
+
result.push(object.material);
|
|
425
|
+
}
|
|
448
426
|
}
|
|
449
427
|
for (const child of object.children) {
|
|
450
|
-
result = result.concat(SceneTraversal.filterMaterials(child,
|
|
428
|
+
result = result.concat(SceneTraversal.filterMaterials(child, filter));
|
|
451
429
|
}
|
|
452
430
|
return result;
|
|
453
431
|
}
|
|
454
432
|
/**
|
|
455
|
-
*
|
|
433
|
+
* Returns all mesh objects that use any of the specified materials.
|
|
456
434
|
*
|
|
457
|
-
*
|
|
458
|
-
*
|
|
459
|
-
*
|
|
460
|
-
* @param object - The root Object3D to start searching from
|
|
461
|
-
* @param materialName - Regular expression pattern to test against material names
|
|
462
|
-
* @returns Array of all Mesh objects that use materials with matching names
|
|
435
|
+
* @param object - Root object to start from
|
|
436
|
+
* @param materials - Array of materials to search for
|
|
437
|
+
* @returns Array of mesh objects using the materials
|
|
463
438
|
*/
|
|
464
|
-
static findMaterialUsers(object,
|
|
439
|
+
static findMaterialUsers(object, materials) {
|
|
465
440
|
let result = [];
|
|
466
441
|
if (object instanceof Mesh) {
|
|
467
442
|
let hasMatchingMaterial = false;
|
|
468
443
|
if (Array.isArray(object.material)) {
|
|
469
444
|
for (const material of object.material) {
|
|
470
|
-
if (
|
|
445
|
+
if (materials.includes(material)) {
|
|
471
446
|
hasMatchingMaterial = true;
|
|
472
447
|
break;
|
|
473
448
|
}
|
|
474
449
|
}
|
|
475
450
|
}
|
|
476
451
|
else {
|
|
477
|
-
if (object.material
|
|
478
|
-
materialName.test(object.material.name)) {
|
|
452
|
+
if (materials.includes(object.material)) {
|
|
479
453
|
hasMatchingMaterial = true;
|
|
480
454
|
}
|
|
481
455
|
}
|
|
@@ -484,7 +458,7 @@ class SceneTraversal {
|
|
|
484
458
|
}
|
|
485
459
|
}
|
|
486
460
|
for (const child of object.children) {
|
|
487
|
-
result = result.concat(SceneTraversal.findMaterialUsers(child,
|
|
461
|
+
result = result.concat(SceneTraversal.findMaterialUsers(child, materials));
|
|
488
462
|
}
|
|
489
463
|
return result;
|
|
490
464
|
}
|
|
@@ -492,14 +466,13 @@ class SceneTraversal {
|
|
|
492
466
|
|
|
493
467
|
/** Number of components per vertex */
|
|
494
468
|
const COMPONENT_COUNT = 3;
|
|
495
|
-
/** Converts skinned meshes to static meshes */
|
|
469
|
+
/** Converts skinned meshes to static meshes. */
|
|
496
470
|
class SkinnedMeshBaker {
|
|
497
471
|
/**
|
|
498
|
-
* Converts
|
|
499
|
-
* The resulting mesh has no bones but looks identical.
|
|
472
|
+
* Converts skinned mesh to static mesh in current pose.
|
|
500
473
|
*
|
|
501
474
|
* @param skinnedMesh - Mesh to convert
|
|
502
|
-
* @returns Static mesh with baked
|
|
475
|
+
* @returns Static mesh with baked positions
|
|
503
476
|
*/
|
|
504
477
|
static bakePose(skinnedMesh) {
|
|
505
478
|
const bakedGeometry = skinnedMesh.geometry.clone();
|
|
@@ -522,13 +495,13 @@ class SkinnedMeshBaker {
|
|
|
522
495
|
return mesh;
|
|
523
496
|
}
|
|
524
497
|
/**
|
|
525
|
-
* Bakes
|
|
498
|
+
* Bakes animation frame to static mesh.
|
|
526
499
|
*
|
|
527
500
|
* @param armature - Root object with bones
|
|
528
501
|
* @param skinnedMesh - Mesh to convert
|
|
529
|
-
* @param timeOffset - Time in seconds within
|
|
530
|
-
* @param clip - Animation
|
|
531
|
-
* @returns Static mesh with baked
|
|
502
|
+
* @param timeOffset - Time in seconds within animation
|
|
503
|
+
* @param clip - Animation clip for pose
|
|
504
|
+
* @returns Static mesh with baked positions
|
|
532
505
|
*/
|
|
533
506
|
static bakeAnimationFrame(armature, skinnedMesh, timeOffset, clip) {
|
|
534
507
|
const mixer = new AnimationMixer(armature);
|
|
@@ -546,37 +519,15 @@ const METALNESS_BRIGHTNESS_FACTOR = 0.3;
|
|
|
546
519
|
/** Factor for emissive color contribution when combining with base color */
|
|
547
520
|
const EMISSIVE_CONTRIBUTION_FACTOR = 0.5;
|
|
548
521
|
/**
|
|
549
|
-
* Converts
|
|
550
|
-
*
|
|
551
|
-
* Handles translation from PBR StandardMaterial to unlit BasicMaterial.
|
|
552
|
-
* Since BasicMaterial doesn't respond to lighting, applies compensation
|
|
553
|
-
* techniques including brightness adjustments and emissive color combination.
|
|
522
|
+
* Converts MeshStandardMaterial to MeshBasicMaterial with brightness compensation.
|
|
554
523
|
*/
|
|
555
524
|
class StandardToBasicConverter {
|
|
556
525
|
/**
|
|
557
|
-
* Converts
|
|
526
|
+
* Converts MeshStandardMaterial to MeshBasicMaterial.
|
|
558
527
|
*
|
|
559
|
-
*
|
|
560
|
-
*
|
|
561
|
-
*
|
|
562
|
-
* @param standardMaterial - The source MeshStandardMaterial to convert
|
|
563
|
-
* @param options - Configuration options for the conversion
|
|
564
|
-
* @returns A new MeshBasicMaterial with properties mapped from the standard material
|
|
565
|
-
*
|
|
566
|
-
* @example
|
|
567
|
-
* ```typescript
|
|
568
|
-
* const standardMaterial = new MeshStandardMaterial({
|
|
569
|
-
* color: 0x00ff00,
|
|
570
|
-
* metalness: 0.5,
|
|
571
|
-
* emissive: 0x111111,
|
|
572
|
-
* emissiveIntensity: 0.2
|
|
573
|
-
* });
|
|
574
|
-
*
|
|
575
|
-
* const basicMaterial = StandardToBasicConverter.convert(standardMaterial, {
|
|
576
|
-
* brightnessFactor: 1.4,
|
|
577
|
-
* combineEmissive: true
|
|
578
|
-
* });
|
|
579
|
-
* ```
|
|
528
|
+
* @param standardMaterial - Source material to convert
|
|
529
|
+
* @param options - Conversion options
|
|
530
|
+
* @returns New MeshBasicMaterial with mapped properties
|
|
580
531
|
*/
|
|
581
532
|
static convert(standardMaterial, options = {}) {
|
|
582
533
|
const config = {
|
|
@@ -605,11 +556,11 @@ class StandardToBasicConverter {
|
|
|
605
556
|
return basicMaterial;
|
|
606
557
|
}
|
|
607
558
|
/**
|
|
608
|
-
* Copies basic material properties
|
|
559
|
+
* Copies basic material properties.
|
|
609
560
|
*
|
|
610
|
-
* @param source -
|
|
611
|
-
* @param target -
|
|
612
|
-
* @param config -
|
|
561
|
+
* @param source - Source material
|
|
562
|
+
* @param target - Target material
|
|
563
|
+
* @param config - Configuration options
|
|
613
564
|
* @internal
|
|
614
565
|
*/
|
|
615
566
|
static copyBasicProperties(source, target, config) {
|
|
@@ -627,14 +578,11 @@ class StandardToBasicConverter {
|
|
|
627
578
|
}
|
|
628
579
|
}
|
|
629
580
|
/**
|
|
630
|
-
* Converts color
|
|
631
|
-
*
|
|
632
|
-
* Applies brightness compensation and optional emissive color combination
|
|
633
|
-
* to account for BasicMaterial's lack of lighting response.
|
|
581
|
+
* Converts color properties with lighting compensation.
|
|
634
582
|
*
|
|
635
|
-
* @param source -
|
|
636
|
-
* @param target -
|
|
637
|
-
* @param config -
|
|
583
|
+
* @param source - Source material
|
|
584
|
+
* @param target - Target material
|
|
585
|
+
* @param config - Configuration options
|
|
638
586
|
* @internal
|
|
639
587
|
*/
|
|
640
588
|
static convertColorProperties(source, target, config) {
|
|
@@ -660,13 +608,10 @@ class StandardToBasicConverter {
|
|
|
660
608
|
target.color.b = Math.min(target.color.b, 1.0);
|
|
661
609
|
}
|
|
662
610
|
/**
|
|
663
|
-
* Converts
|
|
611
|
+
* Converts texture properties from Standard to Basic material.
|
|
664
612
|
*
|
|
665
|
-
*
|
|
666
|
-
*
|
|
667
|
-
*
|
|
668
|
-
* @param source - The source MeshStandardMaterial
|
|
669
|
-
* @param target - The target MeshBasicMaterial
|
|
613
|
+
* @param source - Source material
|
|
614
|
+
* @param target - Target material
|
|
670
615
|
* @internal
|
|
671
616
|
*/
|
|
672
617
|
static convertTextureMaps(source, target) {
|
|
@@ -703,10 +648,10 @@ class StandardToBasicConverter {
|
|
|
703
648
|
this.copyUVTransforms(source, target);
|
|
704
649
|
}
|
|
705
650
|
/**
|
|
706
|
-
* Copies UV transformation properties
|
|
651
|
+
* Copies UV transformation properties.
|
|
707
652
|
*
|
|
708
|
-
* @param source -
|
|
709
|
-
* @param target -
|
|
653
|
+
* @param source - Source material
|
|
654
|
+
* @param target - Target material
|
|
710
655
|
* @internal
|
|
711
656
|
*/
|
|
712
657
|
static copyUVTransforms(source, target) {
|
|
@@ -721,8 +666,8 @@ class StandardToBasicConverter {
|
|
|
721
666
|
/**
|
|
722
667
|
* Converts transparency and rendering properties.
|
|
723
668
|
*
|
|
724
|
-
* @param source -
|
|
725
|
-
* @param target -
|
|
669
|
+
* @param source - Source material
|
|
670
|
+
* @param target - Target material
|
|
726
671
|
* @internal
|
|
727
672
|
*/
|
|
728
673
|
static convertTransparencyProperties(source, target) {
|
|
@@ -744,33 +689,15 @@ const ROUGHNESS_COLOR_ADJUSTMENT = 0.2;
|
|
|
744
689
|
/** Minimum reflectivity boost for environment maps */
|
|
745
690
|
const REFLECTIVITY_BOOST = 0.1;
|
|
746
691
|
/**
|
|
747
|
-
* Converts
|
|
748
|
-
*
|
|
749
|
-
* Handles translation between PBR properties of StandardMaterial and
|
|
750
|
-
* the Lambertian reflectance model used by LambertMaterial. Applies
|
|
751
|
-
* color compensation based on metalness and roughness values.
|
|
692
|
+
* Converts MeshStandardMaterial to MeshLambertMaterial with PBR compensation.
|
|
752
693
|
*/
|
|
753
694
|
class StandardToLambertConverter {
|
|
754
695
|
/**
|
|
755
|
-
* Converts
|
|
756
|
-
*
|
|
757
|
-
* Performs conversion from PBR StandardMaterial to Lambert lighting model
|
|
758
|
-
* with color compensation based on metalness and roughness values.
|
|
759
|
-
*
|
|
760
|
-
* @param material - The source MeshStandardMaterial to convert
|
|
761
|
-
* @param options - Configuration options for the conversion
|
|
762
|
-
* @returns A new MeshLambertMaterial with properties mapped from the standard material
|
|
696
|
+
* Converts MeshStandardMaterial to MeshLambertMaterial.
|
|
763
697
|
*
|
|
764
|
-
* @
|
|
765
|
-
*
|
|
766
|
-
*
|
|
767
|
-
* color: 0xff0000,
|
|
768
|
-
* metalness: 0.8,
|
|
769
|
-
* roughness: 0.2
|
|
770
|
-
* });
|
|
771
|
-
*
|
|
772
|
-
* const lambertMaterial = StandardToLambertConverter.convert(standardMaterial);
|
|
773
|
-
* ```
|
|
698
|
+
* @param material - Source material to convert
|
|
699
|
+
* @param options - Conversion options
|
|
700
|
+
* @returns New MeshLambertMaterial with mapped properties
|
|
774
701
|
*/
|
|
775
702
|
static convert(material, options = {}) {
|
|
776
703
|
const config = {
|
|
@@ -798,11 +725,11 @@ class StandardToLambertConverter {
|
|
|
798
725
|
return lambertMaterial;
|
|
799
726
|
}
|
|
800
727
|
/**
|
|
801
|
-
* Copies basic material properties
|
|
728
|
+
* Copies basic material properties.
|
|
802
729
|
*
|
|
803
|
-
* @param source -
|
|
804
|
-
* @param target -
|
|
805
|
-
* @param config -
|
|
730
|
+
* @param source - Source material
|
|
731
|
+
* @param target - Target material
|
|
732
|
+
* @param config - Configuration options
|
|
806
733
|
* @internal
|
|
807
734
|
*/
|
|
808
735
|
static copyBasicProperties(source, target, config) {
|
|
@@ -821,14 +748,11 @@ class StandardToLambertConverter {
|
|
|
821
748
|
}
|
|
822
749
|
}
|
|
823
750
|
/**
|
|
824
|
-
* Converts color
|
|
825
|
-
*
|
|
826
|
-
* Applies color adjustments to compensate for the loss of metalness and
|
|
827
|
-
* roughness information when converting to Lambert material.
|
|
751
|
+
* Converts color properties with PBR compensation.
|
|
828
752
|
*
|
|
829
|
-
* @param source -
|
|
830
|
-
* @param target -
|
|
831
|
-
* @param config -
|
|
753
|
+
* @param source - Source material
|
|
754
|
+
* @param target - Target material
|
|
755
|
+
* @param config - Configuration options
|
|
832
756
|
* @internal
|
|
833
757
|
*/
|
|
834
758
|
static convertColorProperties(source, target, config) {
|
|
@@ -849,13 +773,10 @@ class StandardToLambertConverter {
|
|
|
849
773
|
target.emissiveIntensity = source.emissiveIntensity;
|
|
850
774
|
}
|
|
851
775
|
/**
|
|
852
|
-
* Converts
|
|
776
|
+
* Converts texture properties from Standard to Lambert material.
|
|
853
777
|
*
|
|
854
|
-
*
|
|
855
|
-
*
|
|
856
|
-
*
|
|
857
|
-
* @param source - The source MeshStandardMaterial
|
|
858
|
-
* @param target - The target MeshLambertMaterial
|
|
778
|
+
* @param source - Source material
|
|
779
|
+
* @param target - Target material
|
|
859
780
|
* @internal
|
|
860
781
|
*/
|
|
861
782
|
static convertTextureMaps(source, target) {
|
|
@@ -895,10 +816,10 @@ class StandardToLambertConverter {
|
|
|
895
816
|
this.copyUVTransforms(source, target);
|
|
896
817
|
}
|
|
897
818
|
/**
|
|
898
|
-
* Copies UV transformation properties
|
|
819
|
+
* Copies UV transformation properties.
|
|
899
820
|
*
|
|
900
|
-
* @param source -
|
|
901
|
-
* @param target -
|
|
821
|
+
* @param source - Source material
|
|
822
|
+
* @param target - Target material
|
|
902
823
|
* @internal
|
|
903
824
|
*/
|
|
904
825
|
static copyUVTransforms(source, target) {
|
|
@@ -913,8 +834,8 @@ class StandardToLambertConverter {
|
|
|
913
834
|
/**
|
|
914
835
|
* Converts transparency and rendering properties.
|
|
915
836
|
*
|
|
916
|
-
* @param source -
|
|
917
|
-
* @param target -
|
|
837
|
+
* @param source - Source material
|
|
838
|
+
* @param target - Target material
|
|
918
839
|
* @internal
|
|
919
840
|
*/
|
|
920
841
|
static convertTransparencyProperties(source, target) {
|
|
@@ -938,11 +859,7 @@ const LUMINANCE_G = 0.7152;
|
|
|
938
859
|
/** Blue channel weight for luminance calculation (ITU-R BT.709) */
|
|
939
860
|
const LUMINANCE_B = 0.0722;
|
|
940
861
|
/**
|
|
941
|
-
*
|
|
942
|
-
*
|
|
943
|
-
* Extends Three.js DirectionalLight to provide spherical coordinate control
|
|
944
|
-
* (distance, elevation, azimuth) and shadow map configuration for bounding boxes.
|
|
945
|
-
* Also supports sun direction calculation from HDR environment maps.
|
|
862
|
+
* Directional light with spherical positioning and HDR environment support.
|
|
946
863
|
*/
|
|
947
864
|
class Sun extends DirectionalLight {
|
|
948
865
|
constructor() {
|
|
@@ -960,64 +877,48 @@ class Sun extends DirectionalLight {
|
|
|
960
877
|
this._private_tempSpherical = new Spherical();
|
|
961
878
|
}
|
|
962
879
|
/**
|
|
963
|
-
*
|
|
964
|
-
*
|
|
965
|
-
* @returns The distance in world units
|
|
880
|
+
* @returns Distance from light position to origin
|
|
966
881
|
*/
|
|
967
882
|
get distance() {
|
|
968
883
|
return this.position.length();
|
|
969
884
|
}
|
|
970
885
|
/**
|
|
971
|
-
*
|
|
972
|
-
*
|
|
973
|
-
* @returns The elevation angle in radians (phi angle from Three.js Spherical coordinates)
|
|
886
|
+
* @returns Elevation angle in radians (phi angle)
|
|
974
887
|
*/
|
|
975
888
|
get elevation() {
|
|
976
889
|
return this._private_tempSpherical.setFromVector3(this.position).phi;
|
|
977
890
|
}
|
|
978
891
|
/**
|
|
979
|
-
*
|
|
980
|
-
*
|
|
981
|
-
* @returns The azimuth angle in radians (theta angle from Three.js Spherical coordinates)
|
|
892
|
+
* @returns Azimuth angle in radians (theta angle)
|
|
982
893
|
*/
|
|
983
894
|
get azimuth() {
|
|
984
895
|
return this._private_tempSpherical.setFromVector3(this.position).theta;
|
|
985
896
|
}
|
|
986
897
|
/**
|
|
987
|
-
*
|
|
988
|
-
*
|
|
989
|
-
* @param value - The new distance in world units
|
|
898
|
+
* @param value - New distance in world units
|
|
990
899
|
*/
|
|
991
900
|
set distance(value) {
|
|
992
901
|
this._private_tempSpherical.setFromVector3(this.position);
|
|
993
902
|
this.position.setFromSphericalCoords(value, this._private_tempSpherical.phi, this._private_tempSpherical.theta);
|
|
994
903
|
}
|
|
995
904
|
/**
|
|
996
|
-
*
|
|
997
|
-
*
|
|
998
|
-
* @param value - The new elevation angle in radians (phi angle for Three.js Spherical coordinates)
|
|
905
|
+
* @param value - New elevation angle in radians (phi angle)
|
|
999
906
|
*/
|
|
1000
907
|
set elevation(value) {
|
|
1001
908
|
this._private_tempSpherical.setFromVector3(this.position);
|
|
1002
909
|
this.position.setFromSphericalCoords(this._private_tempSpherical.radius, value, this._private_tempSpherical.theta);
|
|
1003
910
|
}
|
|
1004
911
|
/**
|
|
1005
|
-
*
|
|
1006
|
-
*
|
|
1007
|
-
* @param value - The new azimuth angle in radians (theta angle for Three.js Spherical coordinates)
|
|
912
|
+
* @param value - New azimuth angle in radians (theta angle)
|
|
1008
913
|
*/
|
|
1009
914
|
set azimuth(value) {
|
|
1010
915
|
this._private_tempSpherical.setFromVector3(this.position);
|
|
1011
916
|
this.position.setFromSphericalCoords(this._private_tempSpherical.radius, this._private_tempSpherical.phi, value);
|
|
1012
917
|
}
|
|
1013
918
|
/**
|
|
1014
|
-
* Configures
|
|
919
|
+
* Configures shadow camera frustum to cover bounding box.
|
|
1015
920
|
*
|
|
1016
|
-
*
|
|
1017
|
-
* provided bounding box by transforming box corners to light space and
|
|
1018
|
-
* setting camera bounds accordingly.
|
|
1019
|
-
*
|
|
1020
|
-
* @param box3 - The 3D bounding box to cover with shadows
|
|
921
|
+
* @param box3 - 3D bounding box to cover with shadows
|
|
1021
922
|
*/
|
|
1022
923
|
configureShadowsForBoundingBox(box3) {
|
|
1023
924
|
const camera = this.shadow.camera;
|
|
@@ -1049,13 +950,10 @@ class Sun extends DirectionalLight {
|
|
|
1049
950
|
camera.updateProjectionMatrix();
|
|
1050
951
|
}
|
|
1051
952
|
/**
|
|
1052
|
-
* Sets
|
|
1053
|
-
*
|
|
1054
|
-
* Analyzes an HDR texture to find the pixel with the highest luminance value
|
|
1055
|
-
* and positions the sun to shine from that direction using spherical coordinates.
|
|
953
|
+
* Sets sun direction based on brightest point in HDR environment map.
|
|
1056
954
|
*
|
|
1057
|
-
* @param texture -
|
|
1058
|
-
* @param distance -
|
|
955
|
+
* @param texture - HDR texture to analyze (must have image data)
|
|
956
|
+
* @param distance - Distance to place sun from origin
|
|
1059
957
|
*/
|
|
1060
958
|
setDirectionFromHDRTexture(texture, distance = 1) {
|
|
1061
959
|
const data = texture.image.data;
|