three-zoo 0.5.5 → 0.6.0

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/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
- * A camera that supports independent horizontal and vertical FOV settings.
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
- * Creates a new DualFovCamera instance.
25
- *
26
- * @param horizontalFov - Horizontal field of view in degrees. Clamped between 1° and 179°.
27
- * @param verticalFov - Vertical field of view in degrees. Clamped between 1° and 179°.
28
- * @param aspect - Camera aspect ratio (width/height).
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
- * Gets the horizontal field of view in degrees.
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
- * Gets the vertical field of view in degrees.
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
- * Sets the horizontal field of view in degrees.
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
- * Sets the vertical field of view in degrees.
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 horizontal and vertical field of view values.
61
+ * Sets both FOV values.
74
62
  *
75
- * @param horizontal - Horizontal FOV in degrees. Clamped between and 179°.
76
- * @param vertical - Vertical FOV in degrees. Clamped between and 179°.
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 the field of view settings from another DualFovCamera.
72
+ * Copies FOV settings from another DualFovCamera.
85
73
  *
86
- * @param source - The DualFovCamera to copy FOV settings from.
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 the projection matrix based on current FOV settings and aspect ratio.
95
- *
96
- * The behavior differs based on orientation:
97
- * - **Landscape mode (aspect > 1)**: Preserves horizontal FOV, calculates vertical FOV
98
- * - **Portrait mode (aspect ≤ 1)**: Preserves vertical FOV, calculates horizontal FOV
82
+ * Updates projection matrix based on FOV and aspect ratio.
99
83
  *
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 the horizontal field of view after aspect ratio adjustments.
102
+ * Gets actual horizontal FOV after aspect ratio adjustments.
118
103
  *
119
- * In landscape mode, returns the set horizontal FOV.
120
- * In portrait mode, calculates the horizontal FOV from vertical FOV and aspect ratio.
121
- *
122
- * @returns The horizontal FOV in degrees
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 the vertical field of view after aspect ratio adjustments.
133
- *
134
- * In portrait mode, returns the set vertical FOV.
135
- * In landscape mode, calculates the vertical FOV from horizontal FOV and aspect ratio.
114
+ * Gets actual vertical FOV after aspect ratio adjustments.
136
115
  *
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 the vertical field of view to fit specified points within the camera's view.
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 the vertical field of view to fit a bounding box within the camera's view.
147
+ * Adjusts vertical FOV to fit bounding box within camera view.
172
148
  *
173
- * Calculates the required vertical FOV to ensure the bounding box
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 the vertical field of view to fit a skinned mesh within the camera's view.
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 - The skinned mesh with active skeleton
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 the camera to look at the center of mass of a skinned mesh.
184
+ * Points camera to look at skinned mesh center of mass.
185
+ * Uses iterative clustering to find main vertex concentration.
215
186
  *
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.
222
- *
223
- * @param skinnedMesh - The skinned mesh with active skeleton
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 the main cluster center of 3D points using iterative refinement.
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 The center point of the main cluster
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 DualFovCamera.
270
- *
271
- * The cloned camera has identical FOV settings, position, rotation,
272
- * and all other camera properties.
233
+ * Creates a copy of this camera with identical settings.
273
234
  *
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
- * Utility class for finding and modifying objects in a Three.js scene graph.
246
+ * Static methods for traversing Three.js scene hierarchies.
286
247
  *
287
- * Provides static methods for traversing Three.js scene hierarchies,
288
- * searching for objects or materials, and performing batch operations.
289
- *
290
- * All methods perform depth-first traversal starting from the provided
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 the first object in the scene hierarchy with an exact name match.
296
- *
297
- * Performs depth-first search through the scene graph starting from the
298
- * root object. Returns the first object whose name property matches
299
- * the search string.
252
+ * Finds first object with exact name match.
300
253
  *
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 undefined
304
257
  */
305
258
  static getObjectByName(object, name) {
306
259
  if (object.name === name) {
@@ -312,18 +265,14 @@ class SceneTraversal {
312
265
  return result;
313
266
  }
314
267
  }
315
- return null;
268
+ return undefined;
316
269
  }
317
270
  /**
318
- * Finds the first material in the scene hierarchy with an exact name match.
271
+ * Finds first material with exact name match from mesh objects.
319
272
  *
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.
323
- *
324
- * @param object - The root Object3D to start searching from
325
- * @param name - The exact material name to search for (case-sensitive)
326
- * @returns The first matching Material, or null if no match is found
273
+ * @param object - Root object to start from
274
+ * @param name - Material name to search for (case-sensitive)
275
+ * @returns First matching material or undefined
327
276
  */
328
277
  static getMaterialByName(object, name) {
329
278
  if (object instanceof Mesh) {
@@ -344,18 +293,15 @@ class SceneTraversal {
344
293
  return material;
345
294
  }
346
295
  }
347
- return null;
296
+ return undefined;
348
297
  }
349
298
  /**
350
- * Processes all objects of a specific type in the scene hierarchy.
351
- *
352
- * Performs depth-first traversal and executes the callback function
353
- * for every object that is an instance of the specified type.
299
+ * Executes callback for all objects of specified type.
354
300
  *
355
- * @template T - The type of objects to process
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
- * Processes all materials found in mesh objects within the scene hierarchy.
315
+ * Executes callback for all materials of specified type from mesh objects.
370
316
  *
371
- * Performs depth-first traversal, finding all Mesh objects and executing
372
- * the callback function for each material. Handles both single
373
- * materials and material arrays.
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.
341
+ *
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.
374
353
  *
375
- * @param object - The root Object3D to start searching from
376
- * @param callback - Function to execute for each material found
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
- * Finds all objects in the scene hierarchy that match filter criteria.
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 - The root Object3D to start searching from
401
- * @param filter - Either a RegExp to test against object names, or a predicate function
402
- * @returns Array of all matching Object3D instances
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
- * Finds all materials in the scene hierarchy whose names match a pattern.
397
+ * Returns all materials matching filter criteria from mesh objects.
423
398
  *
424
- * Performs depth-first search through all Mesh objects and collects materials
425
- * whose name property matches the regular expression. Handles both
426
- * single materials and material arrays.
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, name) {
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 (material.name !== undefined && name.test(material.name)) {
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.name !== undefined &&
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, name));
428
+ result = result.concat(SceneTraversal.filterMaterials(child, filter));
451
429
  }
452
430
  return result;
453
431
  }
454
432
  /**
455
- * Finds all mesh objects that use materials with names matching a pattern.
456
- *
457
- * Performs depth-first search through all Mesh objects and collects mesh objects
458
- * whose materials have names that match the regular expression.
433
+ * Returns all mesh objects that use any of the specified materials.
459
434
  *
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, materialName) {
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 (material.name !== undefined && materialName.test(material.name)) {
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.name !== undefined &&
478
- materialName.test(object.material.name)) {
452
+ if (materials.includes(object.material)) {
479
453
  hasMatchingMaterial = true;
480
454
  }
481
455
  }
@@ -484,22 +458,57 @@ class SceneTraversal {
484
458
  }
485
459
  }
486
460
  for (const child of object.children) {
487
- result = result.concat(SceneTraversal.findMaterialUsers(child, materialName));
461
+ result = result.concat(SceneTraversal.findMaterialUsers(child, materials));
488
462
  }
489
463
  return result;
490
464
  }
465
+ /**
466
+ * Clones material by name and replaces all instances with the clone.
467
+ *
468
+ * @param object - Root object to start from
469
+ * @param name - Material name to search for (case-sensitive)
470
+ * @returns Cloned material or undefined if not found
471
+ */
472
+ static cloneMaterialByName(object, name) {
473
+ const originalMaterial = SceneTraversal.getMaterialByName(object, name);
474
+ if (!originalMaterial) {
475
+ return undefined;
476
+ }
477
+ const clonedMaterial = originalMaterial.clone();
478
+ SceneTraversal.replaceMaterial(object, originalMaterial, clonedMaterial);
479
+ return clonedMaterial;
480
+ }
481
+ /**
482
+ * Replaces all instances of a material with another material.
483
+ *
484
+ * @param object - Root object to start from
485
+ * @param oldMaterial - Material to replace
486
+ * @param newMaterial - Material to use as replacement
487
+ */
488
+ static replaceMaterial(object, oldMaterial, newMaterial) {
489
+ if (object instanceof Mesh) {
490
+ if (Array.isArray(object.material)) {
491
+ object.material = object.material.map((material) => material === oldMaterial ? newMaterial : material);
492
+ }
493
+ else if (object.material === oldMaterial) {
494
+ object.material = newMaterial;
495
+ }
496
+ }
497
+ for (const child of object.children) {
498
+ SceneTraversal.replaceMaterial(child, oldMaterial, newMaterial);
499
+ }
500
+ }
491
501
  }
492
502
 
493
503
  /** Number of components per vertex */
494
504
  const COMPONENT_COUNT = 3;
495
- /** Converts skinned meshes to static meshes */
505
+ /** Converts skinned meshes to static meshes. */
496
506
  class SkinnedMeshBaker {
497
507
  /**
498
- * Converts a skinned mesh to a static mesh in its current pose.
499
- * The resulting mesh has no bones but looks identical.
508
+ * Converts skinned mesh to static mesh in current pose.
500
509
  *
501
510
  * @param skinnedMesh - Mesh to convert
502
- * @returns Static mesh with baked vertex positions
511
+ * @returns Static mesh with baked positions
503
512
  */
504
513
  static bakePose(skinnedMesh) {
505
514
  const bakedGeometry = skinnedMesh.geometry.clone();
@@ -522,13 +531,13 @@ class SkinnedMeshBaker {
522
531
  return mesh;
523
532
  }
524
533
  /**
525
- * Bakes a single frame from an animation into a static mesh.
534
+ * Bakes animation frame to static mesh.
526
535
  *
527
536
  * @param armature - Root object with bones
528
537
  * @param skinnedMesh - Mesh to convert
529
- * @param timeOffset - Time in seconds within the animation
530
- * @param clip - Animation to get the pose from
531
- * @returns Static mesh with baked vertex positions
538
+ * @param timeOffset - Time in seconds within animation
539
+ * @param clip - Animation clip for pose
540
+ * @returns Static mesh with baked positions
532
541
  */
533
542
  static bakeAnimationFrame(armature, skinnedMesh, timeOffset, clip) {
534
543
  const mixer = new AnimationMixer(armature);
@@ -546,37 +555,15 @@ const METALNESS_BRIGHTNESS_FACTOR = 0.3;
546
555
  /** Factor for emissive color contribution when combining with base color */
547
556
  const EMISSIVE_CONTRIBUTION_FACTOR = 0.5;
548
557
  /**
549
- * Converts Three.js MeshStandardMaterial to MeshBasicMaterial.
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.
558
+ * Converts MeshStandardMaterial to MeshBasicMaterial with brightness compensation.
554
559
  */
555
560
  class StandardToBasicConverter {
556
561
  /**
557
- * Converts a MeshStandardMaterial to MeshBasicMaterial.
562
+ * Converts MeshStandardMaterial to MeshBasicMaterial.
558
563
  *
559
- * Performs conversion from PBR StandardMaterial to unlit BasicMaterial
560
- * with brightness compensation and property mapping.
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
- * ```
564
+ * @param standardMaterial - Source material to convert
565
+ * @param options - Conversion options
566
+ * @returns New MeshBasicMaterial with mapped properties
580
567
  */
581
568
  static convert(standardMaterial, options = {}) {
582
569
  const config = {
@@ -605,11 +592,11 @@ class StandardToBasicConverter {
605
592
  return basicMaterial;
606
593
  }
607
594
  /**
608
- * Copies basic material properties from source to target material.
595
+ * Copies basic material properties.
609
596
  *
610
- * @param source - The source MeshStandardMaterial
611
- * @param target - The target MeshBasicMaterial
612
- * @param config - The resolved configuration options
597
+ * @param source - Source material
598
+ * @param target - Target material
599
+ * @param config - Configuration options
613
600
  * @internal
614
601
  */
615
602
  static copyBasicProperties(source, target, config) {
@@ -627,14 +614,11 @@ class StandardToBasicConverter {
627
614
  }
628
615
  }
629
616
  /**
630
- * Converts color-related properties with lighting compensation.
617
+ * Converts color properties with lighting compensation.
631
618
  *
632
- * Applies brightness compensation and optional emissive color combination
633
- * to account for BasicMaterial's lack of lighting response.
634
- *
635
- * @param source - The source MeshStandardMaterial
636
- * @param target - The target MeshBasicMaterial
637
- * @param config - The resolved configuration options
619
+ * @param source - Source material
620
+ * @param target - Target material
621
+ * @param config - Configuration options
638
622
  * @internal
639
623
  */
640
624
  static convertColorProperties(source, target, config) {
@@ -660,13 +644,10 @@ class StandardToBasicConverter {
660
644
  target.color.b = Math.min(target.color.b, 1.0);
661
645
  }
662
646
  /**
663
- * Converts and maps texture properties from Standard to Basic material.
664
- *
665
- * Transfers compatible texture maps including diffuse, alpha, environment,
666
- * light, and AO maps.
647
+ * Converts texture properties from Standard to Basic material.
667
648
  *
668
- * @param source - The source MeshStandardMaterial
669
- * @param target - The target MeshBasicMaterial
649
+ * @param source - Source material
650
+ * @param target - Target material
670
651
  * @internal
671
652
  */
672
653
  static convertTextureMaps(source, target) {
@@ -703,10 +684,10 @@ class StandardToBasicConverter {
703
684
  this.copyUVTransforms(source, target);
704
685
  }
705
686
  /**
706
- * Copies UV transformation properties for texture maps.
687
+ * Copies UV transformation properties.
707
688
  *
708
- * @param source - The source MeshStandardMaterial
709
- * @param target - The target MeshBasicMaterial
689
+ * @param source - Source material
690
+ * @param target - Target material
710
691
  * @internal
711
692
  */
712
693
  static copyUVTransforms(source, target) {
@@ -721,8 +702,8 @@ class StandardToBasicConverter {
721
702
  /**
722
703
  * Converts transparency and rendering properties.
723
704
  *
724
- * @param source - The source MeshStandardMaterial
725
- * @param target - The target MeshBasicMaterial
705
+ * @param source - Source material
706
+ * @param target - Target material
726
707
  * @internal
727
708
  */
728
709
  static convertTransparencyProperties(source, target) {
@@ -744,33 +725,15 @@ const ROUGHNESS_COLOR_ADJUSTMENT = 0.2;
744
725
  /** Minimum reflectivity boost for environment maps */
745
726
  const REFLECTIVITY_BOOST = 0.1;
746
727
  /**
747
- * Converts Three.js MeshStandardMaterial to MeshLambertMaterial.
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.
728
+ * Converts MeshStandardMaterial to MeshLambertMaterial with PBR compensation.
752
729
  */
753
730
  class StandardToLambertConverter {
754
731
  /**
755
- * Converts a MeshStandardMaterial to MeshLambertMaterial.
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
732
+ * Converts MeshStandardMaterial to MeshLambertMaterial.
763
733
  *
764
- * @example
765
- * ```typescript
766
- * const standardMaterial = new MeshStandardMaterial({
767
- * color: 0xff0000,
768
- * metalness: 0.8,
769
- * roughness: 0.2
770
- * });
771
- *
772
- * const lambertMaterial = StandardToLambertConverter.convert(standardMaterial);
773
- * ```
734
+ * @param material - Source material to convert
735
+ * @param options - Conversion options
736
+ * @returns New MeshLambertMaterial with mapped properties
774
737
  */
775
738
  static convert(material, options = {}) {
776
739
  const config = {
@@ -798,11 +761,11 @@ class StandardToLambertConverter {
798
761
  return lambertMaterial;
799
762
  }
800
763
  /**
801
- * Copies basic material properties from source to target material.
764
+ * Copies basic material properties.
802
765
  *
803
- * @param source - The source MeshStandardMaterial
804
- * @param target - The target MeshLambertMaterial
805
- * @param config - The resolved configuration options
766
+ * @param source - Source material
767
+ * @param target - Target material
768
+ * @param config - Configuration options
806
769
  * @internal
807
770
  */
808
771
  static copyBasicProperties(source, target, config) {
@@ -821,14 +784,11 @@ class StandardToLambertConverter {
821
784
  }
822
785
  }
823
786
  /**
824
- * Converts color-related properties with PBR compensation.
825
- *
826
- * Applies color adjustments to compensate for the loss of metalness and
827
- * roughness information when converting to Lambert material.
787
+ * Converts color properties with PBR compensation.
828
788
  *
829
- * @param source - The source MeshStandardMaterial
830
- * @param target - The target MeshLambertMaterial
831
- * @param config - The resolved configuration options
789
+ * @param source - Source material
790
+ * @param target - Target material
791
+ * @param config - Configuration options
832
792
  * @internal
833
793
  */
834
794
  static convertColorProperties(source, target, config) {
@@ -849,13 +809,10 @@ class StandardToLambertConverter {
849
809
  target.emissiveIntensity = source.emissiveIntensity;
850
810
  }
851
811
  /**
852
- * Converts and maps texture properties from Standard to Lambert material.
812
+ * Converts texture properties from Standard to Lambert material.
853
813
  *
854
- * Transfers compatible texture maps including diffuse, normal, emissive,
855
- * AO, light maps, and environment maps.
856
- *
857
- * @param source - The source MeshStandardMaterial
858
- * @param target - The target MeshLambertMaterial
814
+ * @param source - Source material
815
+ * @param target - Target material
859
816
  * @internal
860
817
  */
861
818
  static convertTextureMaps(source, target) {
@@ -895,10 +852,10 @@ class StandardToLambertConverter {
895
852
  this.copyUVTransforms(source, target);
896
853
  }
897
854
  /**
898
- * Copies UV transformation properties for texture maps.
855
+ * Copies UV transformation properties.
899
856
  *
900
- * @param source - The source MeshStandardMaterial
901
- * @param target - The target MeshLambertMaterial
857
+ * @param source - Source material
858
+ * @param target - Target material
902
859
  * @internal
903
860
  */
904
861
  static copyUVTransforms(source, target) {
@@ -913,8 +870,8 @@ class StandardToLambertConverter {
913
870
  /**
914
871
  * Converts transparency and rendering properties.
915
872
  *
916
- * @param source - The source MeshStandardMaterial
917
- * @param target - The target MeshLambertMaterial
873
+ * @param source - Source material
874
+ * @param target - Target material
918
875
  * @internal
919
876
  */
920
877
  static convertTransparencyProperties(source, target) {
@@ -938,11 +895,7 @@ const LUMINANCE_G = 0.7152;
938
895
  /** Blue channel weight for luminance calculation (ITU-R BT.709) */
939
896
  const LUMINANCE_B = 0.0722;
940
897
  /**
941
- * A directional light with spherical positioning controls.
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.
898
+ * Directional light with spherical positioning and HDR environment support.
946
899
  */
947
900
  class Sun extends DirectionalLight {
948
901
  constructor() {
@@ -960,64 +913,48 @@ class Sun extends DirectionalLight {
960
913
  this._private_tempSpherical = new Spherical();
961
914
  }
962
915
  /**
963
- * Gets the distance from the light's position to the origin.
964
- *
965
- * @returns The distance in world units
916
+ * @returns Distance from light position to origin
966
917
  */
967
918
  get distance() {
968
919
  return this.position.length();
969
920
  }
970
921
  /**
971
- * Gets the elevation angle from the spherical coordinates.
972
- *
973
- * @returns The elevation angle in radians (phi angle from Three.js Spherical coordinates)
922
+ * @returns Elevation angle in radians (phi angle)
974
923
  */
975
924
  get elevation() {
976
925
  return this._private_tempSpherical.setFromVector3(this.position).phi;
977
926
  }
978
927
  /**
979
- * Gets the azimuth angle from the spherical coordinates.
980
- *
981
- * @returns The azimuth angle in radians (theta angle from Three.js Spherical coordinates)
928
+ * @returns Azimuth angle in radians (theta angle)
982
929
  */
983
930
  get azimuth() {
984
931
  return this._private_tempSpherical.setFromVector3(this.position).theta;
985
932
  }
986
933
  /**
987
- * Sets the distance while preserving current elevation and azimuth angles.
988
- *
989
- * @param value - The new distance in world units
934
+ * @param value - New distance in world units
990
935
  */
991
936
  set distance(value) {
992
937
  this._private_tempSpherical.setFromVector3(this.position);
993
938
  this.position.setFromSphericalCoords(value, this._private_tempSpherical.phi, this._private_tempSpherical.theta);
994
939
  }
995
940
  /**
996
- * Sets the elevation angle while preserving current distance and azimuth.
997
- *
998
- * @param value - The new elevation angle in radians (phi angle for Three.js Spherical coordinates)
941
+ * @param value - New elevation angle in radians (phi angle)
999
942
  */
1000
943
  set elevation(value) {
1001
944
  this._private_tempSpherical.setFromVector3(this.position);
1002
945
  this.position.setFromSphericalCoords(this._private_tempSpherical.radius, value, this._private_tempSpherical.theta);
1003
946
  }
1004
947
  /**
1005
- * Sets the azimuth angle while preserving current distance and elevation.
1006
- *
1007
- * @param value - The new azimuth angle in radians (theta angle for Three.js Spherical coordinates)
948
+ * @param value - New azimuth angle in radians (theta angle)
1008
949
  */
1009
950
  set azimuth(value) {
1010
951
  this._private_tempSpherical.setFromVector3(this.position);
1011
952
  this.position.setFromSphericalCoords(this._private_tempSpherical.radius, this._private_tempSpherical.phi, value);
1012
953
  }
1013
954
  /**
1014
- * Configures the shadow camera frustum to cover a bounding box.
955
+ * Configures shadow camera frustum to cover bounding box.
1015
956
  *
1016
- * Adjusts the directional light's shadow camera frustum to encompass the
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
957
+ * @param box3 - 3D bounding box to cover with shadows
1021
958
  */
1022
959
  configureShadowsForBoundingBox(box3) {
1023
960
  const camera = this.shadow.camera;
@@ -1049,13 +986,10 @@ class Sun extends DirectionalLight {
1049
986
  camera.updateProjectionMatrix();
1050
987
  }
1051
988
  /**
1052
- * Sets the sun's direction based on the brightest point in an HDR environment map.
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.
989
+ * Sets sun direction based on brightest point in HDR environment map.
1056
990
  *
1057
- * @param texture - The HDR texture to analyze (must have image data available)
1058
- * @param distance - The distance to place the sun from the origin
991
+ * @param texture - HDR texture to analyze (must have image data)
992
+ * @param distance - Distance to place sun from origin
1059
993
  */
1060
994
  setDirectionFromHDRTexture(texture, distance = 1) {
1061
995
  const data = texture.image.data;