three-zoo 0.5.4 → 0.5.5

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
@@ -21,13 +21,13 @@ const MAX_FOV = 179;
21
21
  */
22
22
  class DualFovCamera extends PerspectiveCamera {
23
23
  /**
24
- * Creates a new DualFovCamera instance with independent horizontal and vertical FOV control.
24
+ * Creates a new DualFovCamera instance.
25
25
  *
26
- * @param horizontalFov - Horizontal field of view in degrees. Must be between 1° and 179°. Defaults to 90°.
27
- * @param verticalFov - Vertical field of view in degrees. Must be between 1° and 179°. Defaults to 90°.
28
- * @param aspect - Camera aspect ratio (width/height). Defaults to 1.
29
- * @param near - Near clipping plane distance. Must be greater than 0. Defaults to 1.
30
- * @param far - Far clipping plane distance. Must be greater than near plane. Defaults to 1000.
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.
31
31
  */
32
32
  constructor(horizontalFov = DEFAULT_HORIZONTAL_FOV, verticalFov = DEFAULT_VERTICAL_FOV, aspect = DEFAULT_ASPECT, near = DEFAULT_NEAR, far = DEFAULT_FAR) {
33
33
  super(verticalFov, aspect, near, far);
@@ -36,17 +36,17 @@ class DualFovCamera extends PerspectiveCamera {
36
36
  this.updateProjectionMatrix();
37
37
  }
38
38
  /**
39
- * Gets the current horizontal field of view in degrees.
39
+ * Gets the horizontal field of view in degrees.
40
40
  *
41
- * @returns The horizontal FOV value between 1° and 179°
41
+ * @returns The horizontal FOV value
42
42
  */
43
43
  get horizontalFov() {
44
44
  return this._private_horizontalFovInternal;
45
45
  }
46
46
  /**
47
- * Gets the current vertical field of view in degrees.
47
+ * Gets the vertical field of view in degrees.
48
48
  *
49
- * @returns The vertical FOV value between 1° and 179°
49
+ * @returns The vertical FOV value
50
50
  */
51
51
  get verticalFov() {
52
52
  return this._private_verticalFovInternal;
@@ -54,7 +54,7 @@ class DualFovCamera extends PerspectiveCamera {
54
54
  /**
55
55
  * Sets the horizontal field of view in degrees.
56
56
  *
57
- * @param value - The horizontal FOV value in degrees. Will be clamped between 1° and 179°.
57
+ * @param value - The horizontal FOV value in degrees. Clamped between 1° and 179°.
58
58
  */
59
59
  set horizontalFov(value) {
60
60
  this._private_horizontalFovInternal = MathUtils.clamp(value, MIN_FOV, MAX_FOV);
@@ -63,17 +63,17 @@ class DualFovCamera extends PerspectiveCamera {
63
63
  /**
64
64
  * Sets the vertical field of view in degrees.
65
65
  *
66
- * @param value - The vertical FOV value in degrees. Will be clamped between 1° and 179°.
66
+ * @param value - The vertical FOV value in degrees. Clamped between 1° and 179°.
67
67
  */
68
68
  set verticalFov(value) {
69
69
  this._private_verticalFovInternal = MathUtils.clamp(value, MIN_FOV, MAX_FOV);
70
70
  this.updateProjectionMatrix();
71
71
  }
72
72
  /**
73
- * Updates both horizontal and vertical field of view values simultaneously.
73
+ * Sets both horizontal and vertical field of view values.
74
74
  *
75
- * @param horizontal - Horizontal FOV in degrees. Will be clamped between 1° and 179°.
76
- * @param vertical - Vertical FOV in degrees. Will be clamped between 1° and 179°.
75
+ * @param horizontal - Horizontal FOV in degrees. Clamped between 1° and 179°.
76
+ * @param vertical - Vertical FOV in degrees. Clamped between 1° and 179°.
77
77
  */
78
78
  setFov(horizontal, vertical) {
79
79
  this._private_horizontalFovInternal = MathUtils.clamp(horizontal, MIN_FOV, MAX_FOV);
@@ -81,9 +81,9 @@ class DualFovCamera extends PerspectiveCamera {
81
81
  this.updateProjectionMatrix();
82
82
  }
83
83
  /**
84
- * Copies the field of view settings from another DualFovCamera instance.
84
+ * Copies the field of view settings from another DualFovCamera.
85
85
  *
86
- * @param source - The DualFovCamera instance to copy FOV settings from.
86
+ * @param source - The DualFovCamera to copy FOV settings from.
87
87
  */
88
88
  copyFovSettings(source) {
89
89
  this._private_horizontalFovInternal = source.horizontalFov;
@@ -97,7 +97,7 @@ class DualFovCamera extends PerspectiveCamera {
97
97
  * - **Landscape mode (aspect > 1)**: Preserves horizontal FOV, calculates vertical FOV
98
98
  * - **Portrait mode (aspect ≤ 1)**: Preserves vertical FOV, calculates horizontal FOV
99
99
  *
100
- * This method is automatically called when FOV values or aspect ratio changes.
100
+ * Called when FOV values or aspect ratio changes.
101
101
  *
102
102
  * @override
103
103
  */
@@ -114,12 +114,12 @@ class DualFovCamera extends PerspectiveCamera {
114
114
  super.updateProjectionMatrix();
115
115
  }
116
116
  /**
117
- * Gets the actual horizontal field of view after aspect ratio adjustments.
117
+ * Gets the horizontal field of view after aspect ratio adjustments.
118
118
  *
119
- * In landscape mode, this returns the set horizontal FOV.
120
- * In portrait mode, this calculates the actual horizontal FOV based on the vertical FOV and aspect ratio.
119
+ * In landscape mode, returns the set horizontal FOV.
120
+ * In portrait mode, calculates the horizontal FOV from vertical FOV and aspect ratio.
121
121
  *
122
- * @returns The actual horizontal FOV in degrees
122
+ * @returns The horizontal FOV in degrees
123
123
  */
124
124
  getActualHorizontalFov() {
125
125
  if (this.aspect >= 1) {
@@ -129,12 +129,12 @@ class DualFovCamera extends PerspectiveCamera {
129
129
  return MathUtils.radToDeg(Math.atan(Math.tan(verticalRadians / 2) * this.aspect) * 2);
130
130
  }
131
131
  /**
132
- * Gets the actual vertical field of view after aspect ratio adjustments.
132
+ * Gets the vertical field of view after aspect ratio adjustments.
133
133
  *
134
- * In portrait mode, this returns the set vertical FOV.
135
- * In landscape mode, this calculates the actual vertical FOV based on the horizontal FOV and aspect ratio.
134
+ * In portrait mode, returns the set vertical FOV.
135
+ * In landscape mode, calculates the vertical FOV from horizontal FOV and aspect ratio.
136
136
  *
137
- * @returns The actual vertical FOV in degrees
137
+ * @returns The vertical FOV in degrees
138
138
  */
139
139
  getActualVerticalFov() {
140
140
  if (this.aspect < 1) {
@@ -144,12 +144,12 @@ class DualFovCamera extends PerspectiveCamera {
144
144
  return MathUtils.radToDeg(Math.atan(Math.tan(horizontalRadians / 2) / this.aspect) * 2);
145
145
  }
146
146
  /**
147
- * Adjusts the vertical field of view to fit all specified points within the camera's view.
147
+ * Adjusts the vertical field of view to fit specified points within the camera's view.
148
148
  *
149
- * This method calculates the required vertical FOV to ensure all provided vertices
149
+ * Calculates the required vertical FOV to ensure all provided vertices
150
150
  * are visible within the vertical bounds of the camera's frustum.
151
151
  *
152
- * @param vertices - Array of 3D points (in world coordinates) that should fit within the camera's vertical view
152
+ * @param vertices - Array of 3D points in world coordinates
153
153
  */
154
154
  fitVerticalFovToPoints(vertices) {
155
155
  const up = new Vector3(0, 1, 0).applyQuaternion(this.quaternion);
@@ -170,10 +170,10 @@ class DualFovCamera extends PerspectiveCamera {
170
170
  /**
171
171
  * Adjusts the vertical field of view to fit a bounding box within the camera's view.
172
172
  *
173
- * This method calculates the required vertical FOV to ensure the entire bounding box
173
+ * Calculates the required vertical FOV to ensure the bounding box
174
174
  * is visible within the vertical bounds of the camera's frustum.
175
175
  *
176
- * @param box - The 3D bounding box (in world coordinates) that should fit within the camera's vertical view
176
+ * @param box - The 3D bounding box in world coordinates
177
177
  */
178
178
  fitVerticalFovToBox(box) {
179
179
  this.fitVerticalFovToPoints([
@@ -190,11 +190,11 @@ class DualFovCamera extends PerspectiveCamera {
190
190
  /**
191
191
  * Adjusts the vertical field of view to fit a skinned mesh within the camera's view.
192
192
  *
193
- * This method updates the mesh's skeleton, applies bone transformations to all vertices,
194
- * and then calculates the required vertical FOV to ensure the entire deformed mesh
195
- * is visible within the vertical bounds of the camera's frustum.
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.
196
196
  *
197
- * @param skinnedMesh - The skinned mesh (with active skeleton) that should fit within the camera's vertical view
197
+ * @param skinnedMesh - The skinned mesh with active skeleton
198
198
  */
199
199
  fitVerticalFovToMesh(skinnedMesh) {
200
200
  skinnedMesh.updateWorldMatrix(true, true);
@@ -213,15 +213,14 @@ class DualFovCamera extends PerspectiveCamera {
213
213
  /**
214
214
  * Points the camera to look at the center of mass of a skinned mesh.
215
215
  *
216
- * This method updates the mesh's skeleton, applies bone transformations to all vertices,
217
- * calculates the center of mass using a clustering algorithm, and then orients the camera
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
218
  * to look at that point.
219
219
  *
220
- * The center of mass calculation uses an iterative clustering approach to find the
221
- * main concentration of vertices, which provides better results than a simple average
222
- * for complex meshes.
220
+ * The center of mass calculation uses iterative clustering to find the
221
+ * main concentration of vertices.
223
222
  *
224
- * @param skinnedMesh - The skinned mesh (with active skeleton) whose center of mass should be the camera's target
223
+ * @param skinnedMesh - The skinned mesh with active skeleton
225
224
  */
226
225
  lookAtMeshCenterOfMass(skinnedMesh) {
227
226
  skinnedMesh.updateWorldMatrix(true, true);
@@ -236,11 +235,11 @@ class DualFovCamera extends PerspectiveCamera {
236
235
  points.push(target.clone());
237
236
  }
238
237
  /**
239
- * Finds the main cluster center of a set of 3D points using iterative refinement.
238
+ * Finds the main cluster center of 3D points using iterative refinement.
240
239
  *
241
240
  * @param points - Array of 3D points to cluster
242
- * @param iterations - Number of refinement iterations to perform
243
- * @returns The calculated center point of the main cluster
241
+ * @param iterations - Number of refinement iterations
242
+ * @returns The center point of the main cluster
244
243
  */
245
244
  const findMainCluster = (points, iterations = 3) => {
246
245
  if (points.length === 0) {
@@ -267,12 +266,12 @@ class DualFovCamera extends PerspectiveCamera {
267
266
  this.lookAt(centerOfMass);
268
267
  }
269
268
  /**
270
- * Creates a deep copy of this DualFovCamera instance.
269
+ * Creates a copy of this DualFovCamera.
271
270
  *
272
- * The cloned camera will have identical FOV settings, position, rotation,
271
+ * The cloned camera has identical FOV settings, position, rotation,
273
272
  * and all other camera properties.
274
273
  *
275
- * @returns A new DualFovCamera instance that is an exact copy of this one
274
+ * @returns A new DualFovCamera instance
276
275
  * @override
277
276
  */
278
277
  clone() {
@@ -285,25 +284,23 @@ class DualFovCamera extends PerspectiveCamera {
285
284
  /**
286
285
  * Utility class for finding and modifying objects in a Three.js scene graph.
287
286
  *
288
- * This class provides static methods for traversing Three.js scene hierarchies,
289
- * searching for specific objects or materials, and performing batch operations
290
- * on collections of scene objects.
287
+ * Provides static methods for traversing Three.js scene hierarchies,
288
+ * searching for objects or materials, and performing batch operations.
291
289
  *
292
- * All methods perform depth-first traversal of the scene graph starting from
293
- * the provided root object and recursively processing all children.
290
+ * All methods perform depth-first traversal starting from the provided
291
+ * root object and recursively processing all children.
294
292
  */
295
293
  class SceneTraversal {
296
294
  /**
297
295
  * Finds the first object in the scene hierarchy with an exact name match.
298
296
  *
299
- * Performs a depth-first search through the scene graph starting from the provided
300
- * root object. Returns the first object encountered whose name property exactly
301
- * matches the search string.
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.
302
300
  *
303
301
  * @param object - The root Object3D to start searching from
304
302
  * @param name - The exact name to search for (case-sensitive)
305
303
  * @returns The first matching Object3D, or null if no match is found
306
-
307
304
  */
308
305
  static getObjectByName(object, name) {
309
306
  if (object.name === name) {
@@ -320,15 +317,13 @@ class SceneTraversal {
320
317
  /**
321
318
  * Finds the first material in the scene hierarchy with an exact name match.
322
319
  *
323
- * Performs a depth-first search through the scene graph, examining materials
320
+ * Performs depth-first search through the scene graph, examining materials
324
321
  * attached to Mesh objects. Handles both single materials and material arrays.
325
- * Returns the first material encountered whose name property exactly matches
326
- * the search string.
322
+ * Returns the first material whose name property matches the search string.
327
323
  *
328
324
  * @param object - The root Object3D to start searching from
329
325
  * @param name - The exact material name to search for (case-sensitive)
330
326
  * @returns The first matching Material, or null if no match is found
331
-
332
327
  */
333
328
  static getMaterialByName(object, name) {
334
329
  if (object instanceof Mesh) {
@@ -354,15 +349,13 @@ class SceneTraversal {
354
349
  /**
355
350
  * Processes all objects of a specific type in the scene hierarchy.
356
351
  *
357
- * Performs a depth-first traversal and executes the provided callback function
358
- * for every object that is an instance of the specified type. This is useful
359
- * for batch operations on specific object types (e.g., all lights, all meshes, etc.).
352
+ * Performs depth-first traversal and executes the callback function
353
+ * for every object that is an instance of the specified type.
360
354
  *
361
355
  * @template T - The type of objects to process
362
356
  * @param object - The root Object3D to start searching from
363
357
  * @param type - The constructor/class to filter by (e.g., DirectionalLight, Mesh)
364
358
  * @param callback - Function to execute for each matching object instance
365
-
366
359
  */
367
360
  static enumerateObjectsByType(object, type, callback) {
368
361
  if (object instanceof type) {
@@ -375,13 +368,12 @@ class SceneTraversal {
375
368
  /**
376
369
  * Processes all materials found in mesh objects within the scene hierarchy.
377
370
  *
378
- * Performs a depth-first traversal, finding all Mesh objects and executing
379
- * the provided callback function for each material. Handles both single
380
- * materials and material arrays properly.
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.
381
374
  *
382
375
  * @param object - The root Object3D to start searching from
383
376
  * @param callback - Function to execute for each material found
384
-
385
377
  */
386
378
  static enumerateMaterials(object, callback) {
387
379
  if (object instanceof Mesh) {
@@ -399,16 +391,15 @@ class SceneTraversal {
399
391
  }
400
392
  }
401
393
  /**
402
- * Finds all objects in the scene hierarchy that match the specified filter criteria.
394
+ * Finds all objects in the scene hierarchy that match filter criteria.
403
395
  *
404
- * Performs a depth-first search and collects all objects that either match
405
- * a regular expression pattern (applied to the object's name) or satisfy
406
- * a custom predicate function.
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.
407
399
  *
408
400
  * @param object - The root Object3D to start searching from
409
401
  * @param filter - Either a RegExp to test against object names, or a predicate function
410
402
  * @returns Array of all matching Object3D instances
411
-
412
403
  */
413
404
  static filterObjects(object, filter) {
414
405
  let result = [];
@@ -428,29 +419,29 @@ class SceneTraversal {
428
419
  return result;
429
420
  }
430
421
  /**
431
- * Finds all materials in the scene hierarchy whose names match a regular expression pattern.
422
+ * Finds all materials in the scene hierarchy whose names match a pattern.
432
423
  *
433
- * Performs a depth-first search through all Mesh objects and collects materials
434
- * whose name property matches the provided regular expression. Handles both
435
- * single materials and material arrays properly.
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.
436
427
  *
437
428
  * @param object - The root Object3D to start searching from
438
429
  * @param name - Regular expression pattern to test against material names
439
430
  * @returns Array of all matching Material instances
440
-
441
431
  */
442
432
  static filterMaterials(object, name) {
443
433
  let result = [];
444
434
  if (object instanceof Mesh) {
445
435
  if (Array.isArray(object.material)) {
446
436
  for (const material of object.material) {
447
- if (material.name && name.test(material.name)) {
437
+ if (material.name !== undefined && name.test(material.name)) {
448
438
  result.push(material);
449
439
  }
450
440
  }
451
441
  }
452
442
  else {
453
- if (object.material.name && name.test(object.material.name)) {
443
+ if (object.material.name !== undefined &&
444
+ name.test(object.material.name)) {
454
445
  result.push(object.material);
455
446
  }
456
447
  }
@@ -461,11 +452,10 @@ class SceneTraversal {
461
452
  return result;
462
453
  }
463
454
  /**
464
- * Finds all objects (mesh users) that use materials with names matching a regular expression pattern.
455
+ * Finds all mesh objects that use materials with names matching a pattern.
465
456
  *
466
- * Performs a depth-first search through all Mesh objects and collects the mesh objects
467
- * whose materials have names that match the provided regular expression. This is useful
468
- * for finding all objects that use specific material types or naming patterns.
457
+ * Performs depth-first search through all Mesh objects and collects mesh objects
458
+ * whose materials have names that match the regular expression.
469
459
  *
470
460
  * @param object - The root Object3D to start searching from
471
461
  * @param materialName - Regular expression pattern to test against material names
@@ -477,14 +467,15 @@ class SceneTraversal {
477
467
  let hasMatchingMaterial = false;
478
468
  if (Array.isArray(object.material)) {
479
469
  for (const material of object.material) {
480
- if (material.name && materialName.test(material.name)) {
470
+ if (material.name !== undefined && materialName.test(material.name)) {
481
471
  hasMatchingMaterial = true;
482
472
  break;
483
473
  }
484
474
  }
485
475
  }
486
476
  else {
487
- if (object.material.name && materialName.test(object.material.name)) {
477
+ if (object.material.name !== undefined &&
478
+ materialName.test(object.material.name)) {
488
479
  hasMatchingMaterial = true;
489
480
  }
490
481
  }
@@ -501,11 +492,11 @@ class SceneTraversal {
501
492
 
502
493
  /** Number of components per vertex */
503
494
  const COMPONENT_COUNT = 3;
504
- /** Convert skinned meshes to regular static meshes */
495
+ /** Converts skinned meshes to static meshes */
505
496
  class SkinnedMeshBaker {
506
497
  /**
507
- * Convert a skinned mesh to a regular mesh in its current pose.
508
- * The resulting mesh will have no bones but look identical.
498
+ * Converts a skinned mesh to a static mesh in its current pose.
499
+ * The resulting mesh has no bones but looks identical.
509
500
  *
510
501
  * @param skinnedMesh - Mesh to convert
511
502
  * @returns Static mesh with baked vertex positions
@@ -531,9 +522,9 @@ class SkinnedMeshBaker {
531
522
  return mesh;
532
523
  }
533
524
  /**
534
- * Bake a single frame from an animation into a static mesh.
525
+ * Bakes a single frame from an animation into a static mesh.
535
526
  *
536
- * @param armature - Root object with bones (usually from GLTF)
527
+ * @param armature - Root object with bones
537
528
  * @param skinnedMesh - Mesh to convert
538
529
  * @param timeOffset - Time in seconds within the animation
539
530
  * @param clip - Animation to get the pose from
@@ -550,21 +541,23 @@ class SkinnedMeshBaker {
550
541
  }
551
542
  }
552
543
 
544
+ /** Factor for metalness brightness adjustment */
545
+ const METALNESS_BRIGHTNESS_FACTOR = 0.3;
546
+ /** Factor for emissive color contribution when combining with base color */
547
+ const EMISSIVE_CONTRIBUTION_FACTOR = 0.5;
553
548
  /**
554
- * Converts Three.js MeshStandardMaterial to MeshBasicMaterial
549
+ * Converts Three.js MeshStandardMaterial to MeshBasicMaterial.
555
550
  *
556
- * This converter handles the translation from PBR (Physically Based Rendering)
557
- * StandardMaterial to the unlit BasicMaterial. Since BasicMaterial doesn't respond
558
- * to lighting, this converter applies various compensation techniques to maintain
559
- * visual similarity, including brightness adjustments and emissive color combination.
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.
560
554
  */
561
555
  class StandardToBasicConverter {
562
556
  /**
563
- * Converts a MeshStandardMaterial to MeshBasicMaterial
557
+ * Converts a MeshStandardMaterial to MeshBasicMaterial.
564
558
  *
565
- * This method performs a comprehensive conversion from PBR StandardMaterial to
566
- * unlit BasicMaterial while attempting to preserve visual similarity through
567
- * brightness compensation and intelligent property mapping.
559
+ * Performs conversion from PBR StandardMaterial to unlit BasicMaterial
560
+ * with brightness compensation and property mapping.
568
561
  *
569
562
  * @param standardMaterial - The source MeshStandardMaterial to convert
570
563
  * @param options - Configuration options for the conversion
@@ -584,8 +577,6 @@ class StandardToBasicConverter {
584
577
  * combineEmissive: true
585
578
  * });
586
579
  * ```
587
- *
588
- * @see {@link StandardToBasicConverterOptions} for available configuration options
589
580
  */
590
581
  static convert(standardMaterial, options = {}) {
591
582
  const config = {
@@ -614,10 +605,7 @@ class StandardToBasicConverter {
614
605
  return basicMaterial;
615
606
  }
616
607
  /**
617
- * Copies basic material properties from source to target material
618
- *
619
- * Transfers common material properties including rendering settings,
620
- * visibility, fog interaction, wireframe settings, and user data.
608
+ * Copies basic material properties from source to target material.
621
609
  *
622
610
  * @param source - The source MeshStandardMaterial
623
611
  * @param target - The target MeshBasicMaterial
@@ -639,11 +627,10 @@ class StandardToBasicConverter {
639
627
  }
640
628
  }
641
629
  /**
642
- * Converts color-related properties with lighting compensation
630
+ * Converts color-related properties with lighting compensation.
643
631
  *
644
632
  * Applies brightness compensation and optional emissive color combination
645
- * to account for BasicMaterial's lack of lighting response. Metallic materials
646
- * receive additional brightness adjustment, and colors are clamped to valid ranges.
633
+ * to account for BasicMaterial's lack of lighting response.
647
634
  *
648
635
  * @param source - The source MeshStandardMaterial
649
636
  * @param target - The target MeshBasicMaterial
@@ -657,14 +644,14 @@ class StandardToBasicConverter {
657
644
  target.color.multiplyScalar(config.brightnessFactor);
658
645
  // Adjust for metalness - metallic materials tend to be darker without lighting
659
646
  if (source.metalness > 0) {
660
- const metalnessBrightness = 1 + source.metalness * 0.3;
647
+ const metalnessBrightness = 1 + source.metalness * METALNESS_BRIGHTNESS_FACTOR;
661
648
  target.color.multiplyScalar(metalnessBrightness);
662
649
  }
663
650
  // Combine emissive color if requested
664
651
  if (config.combineEmissive) {
665
652
  const emissiveContribution = source.emissive
666
653
  .clone()
667
- .multiplyScalar(source.emissiveIntensity * 0.5);
654
+ .multiplyScalar(source.emissiveIntensity * EMISSIVE_CONTRIBUTION_FACTOR);
668
655
  target.color.add(emissiveContribution);
669
656
  }
670
657
  // Ensure color doesn't exceed valid range
@@ -673,12 +660,10 @@ class StandardToBasicConverter {
673
660
  target.color.b = Math.min(target.color.b, 1.0);
674
661
  }
675
662
  /**
676
- * Converts and maps texture properties from Standard to Basic material
663
+ * Converts and maps texture properties from Standard to Basic material.
677
664
  *
678
- * Handles the transfer of compatible texture maps including diffuse, alpha,
679
- * environment, light, and AO maps. The metalness map is repurposed as a
680
- * specular map for some reflective effect, and environment map reflectivity
681
- * is set based on the original material's metalness value.
665
+ * Transfers compatible texture maps including diffuse, alpha, environment,
666
+ * light, and AO maps.
682
667
  *
683
668
  * @param source - The source MeshStandardMaterial
684
669
  * @param target - The target MeshBasicMaterial
@@ -718,10 +703,7 @@ class StandardToBasicConverter {
718
703
  this.copyUVTransforms(source, target);
719
704
  }
720
705
  /**
721
- * Copies UV transformation properties for texture maps
722
- *
723
- * Transfers UV offset, repeat, rotation, and center properties from the
724
- * source material's main texture map to the target material's map.
706
+ * Copies UV transformation properties for texture maps.
725
707
  *
726
708
  * @param source - The source MeshStandardMaterial
727
709
  * @param target - The target MeshBasicMaterial
@@ -737,10 +719,7 @@ class StandardToBasicConverter {
737
719
  }
738
720
  }
739
721
  /**
740
- * Converts transparency and rendering properties
741
- *
742
- * Transfers transparency, opacity, alpha testing, depth testing,
743
- * depth writing, and blending mode settings from source to target.
722
+ * Converts transparency and rendering properties.
744
723
  *
745
724
  * @param source - The source MeshStandardMaterial
746
725
  * @param target - The target MeshBasicMaterial
@@ -756,21 +735,27 @@ class StandardToBasicConverter {
756
735
  }
757
736
  }
758
737
 
738
+ /** Factor for metalness darkness adjustment */
739
+ const METALNESS_DARKNESS_FACTOR = 0.3;
740
+ /** Roughness threshold for additional darkening */
741
+ const ROUGHNESS_THRESHOLD = 0.5;
742
+ /** Factor for roughness color adjustment */
743
+ const ROUGHNESS_COLOR_ADJUSTMENT = 0.2;
744
+ /** Minimum reflectivity boost for environment maps */
745
+ const REFLECTIVITY_BOOST = 0.1;
759
746
  /**
760
- * Converts Three.js MeshStandardMaterial to MeshLambertMaterial
747
+ * Converts Three.js MeshStandardMaterial to MeshLambertMaterial.
761
748
  *
762
- * This converter handles the translation between PBR (Physically Based Rendering)
763
- * properties of StandardMaterial and the simpler Lambertian reflectance model
764
- * used by LambertMaterial. The conversion preserves visual similarity by applying
749
+ * Handles translation between PBR properties of StandardMaterial and
750
+ * the Lambertian reflectance model used by LambertMaterial. Applies
765
751
  * color compensation based on metalness and roughness values.
766
752
  */
767
753
  class StandardToLambertConverter {
768
754
  /**
769
- * Converts a MeshStandardMaterial to MeshLambertMaterial
755
+ * Converts a MeshStandardMaterial to MeshLambertMaterial.
770
756
  *
771
- * This method performs a comprehensive conversion from PBR StandardMaterial to
772
- * the simpler Lambert lighting model while attempting to preserve visual similarity
773
- * through intelligent color compensation.
757
+ * Performs conversion from PBR StandardMaterial to Lambert lighting model
758
+ * with color compensation based on metalness and roughness values.
774
759
  *
775
760
  * @param material - The source MeshStandardMaterial to convert
776
761
  * @param options - Configuration options for the conversion
@@ -786,8 +771,6 @@ class StandardToLambertConverter {
786
771
  *
787
772
  * const lambertMaterial = StandardToLambertConverter.convert(standardMaterial);
788
773
  * ```
789
- *
790
- * @see {@link StandardToLambertConverterOptions} for available configuration options
791
774
  */
792
775
  static convert(material, options = {}) {
793
776
  const config = {
@@ -815,10 +798,7 @@ class StandardToLambertConverter {
815
798
  return lambertMaterial;
816
799
  }
817
800
  /**
818
- * Copies basic material properties from source to target material
819
- *
820
- * Transfers common material properties including rendering settings,
821
- * visibility, fog interaction, wireframe settings, and user data.
801
+ * Copies basic material properties from source to target material.
822
802
  *
823
803
  * @param source - The source MeshStandardMaterial
824
804
  * @param target - The target MeshLambertMaterial
@@ -841,12 +821,10 @@ class StandardToLambertConverter {
841
821
  }
842
822
  }
843
823
  /**
844
- * Converts color-related properties with PBR compensation
824
+ * Converts color-related properties with PBR compensation.
845
825
  *
846
- * Applies intelligent color adjustments to compensate for the loss of
847
- * metalness and roughness information when converting to Lambert material.
848
- * Metallic materials are darkened and rough materials receive additional
849
- * darkening based on the roughnessColorFactor.
826
+ * Applies color adjustments to compensate for the loss of metalness and
827
+ * roughness information when converting to Lambert material.
850
828
  *
851
829
  * @param source - The source MeshStandardMaterial
852
830
  * @param target - The target MeshLambertMaterial
@@ -858,23 +836,23 @@ class StandardToLambertConverter {
858
836
  // Adjust color based on metalness and roughness for better visual match
859
837
  if (source.metalness > 0) {
860
838
  // Metallic materials tend to be darker in Lambert shading
861
- const metalnessFactor = 1 - source.metalness * 0.3;
839
+ const metalnessFactor = 1 - source.metalness * METALNESS_DARKNESS_FACTOR;
862
840
  target.color.multiplyScalar(metalnessFactor);
863
841
  }
864
- if (source.roughness > 0.5) {
842
+ if (source.roughness > ROUGHNESS_THRESHOLD) {
865
843
  // Rough materials appear slightly darker
866
- const roughnessFactor = config.roughnessColorFactor + source.roughness * 0.2;
844
+ const roughnessFactor = config.roughnessColorFactor +
845
+ source.roughness * ROUGHNESS_COLOR_ADJUSTMENT;
867
846
  target.color.multiplyScalar(roughnessFactor);
868
847
  }
869
848
  target.emissive = source.emissive.clone();
870
849
  target.emissiveIntensity = source.emissiveIntensity;
871
850
  }
872
851
  /**
873
- * Converts and maps texture properties from Standard to Lambert material
852
+ * Converts and maps texture properties from Standard to Lambert material.
874
853
  *
875
- * Handles the transfer of compatible texture maps including diffuse, normal,
876
- * emissive, AO, light maps, and environment maps. The environment map
877
- * reflectivity is set based on the original material's metalness value.
854
+ * Transfers compatible texture maps including diffuse, normal, emissive,
855
+ * AO, light maps, and environment maps.
878
856
  *
879
857
  * @param source - The source MeshStandardMaterial
880
858
  * @param target - The target MeshLambertMaterial
@@ -907,7 +885,7 @@ class StandardToLambertConverter {
907
885
  // Environment map (for reflections)
908
886
  if (source.envMap) {
909
887
  target.envMap = source.envMap;
910
- target.reflectivity = Math.min(source.metalness + 0.1, 1.0);
888
+ target.reflectivity = Math.min(source.metalness + REFLECTIVITY_BOOST, 1.0);
911
889
  }
912
890
  // Alpha map
913
891
  if (source.alphaMap) {
@@ -917,10 +895,7 @@ class StandardToLambertConverter {
917
895
  this.copyUVTransforms(source, target);
918
896
  }
919
897
  /**
920
- * Copies UV transformation properties for texture maps
921
- *
922
- * Transfers UV offset, repeat, rotation, and center properties from the
923
- * source material's main texture map to the target material's map.
898
+ * Copies UV transformation properties for texture maps.
924
899
  *
925
900
  * @param source - The source MeshStandardMaterial
926
901
  * @param target - The target MeshLambertMaterial
@@ -936,10 +911,7 @@ class StandardToLambertConverter {
936
911
  }
937
912
  }
938
913
  /**
939
- * Converts transparency and rendering properties
940
- *
941
- * Transfers transparency, opacity, alpha testing, depth testing,
942
- * depth writing, and blending mode settings from source to target.
914
+ * Converts transparency and rendering properties.
943
915
  *
944
916
  * @param source - The source MeshStandardMaterial
945
917
  * @param target - The target MeshLambertMaterial
@@ -966,11 +938,11 @@ const LUMINANCE_G = 0.7152;
966
938
  /** Blue channel weight for luminance calculation (ITU-R BT.709) */
967
939
  const LUMINANCE_B = 0.0722;
968
940
  /**
969
- * A directional light with spherical positioning controls and advanced shadow mapping.
941
+ * A directional light with spherical positioning controls.
970
942
  *
971
- * Extends Three.js DirectionalLight to provide intuitive spherical coordinate control
972
- * (distance, elevation, azimuth) and automatic shadow map configuration for bounding boxes.
973
- * Also supports automatic sun direction calculation from HDR environment maps.
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.
974
946
  */
975
947
  class Sun extends DirectionalLight {
976
948
  constructor() {
@@ -988,7 +960,7 @@ class Sun extends DirectionalLight {
988
960
  this._private_tempSpherical = new Spherical();
989
961
  }
990
962
  /**
991
- * Gets the distance from the light to its target (origin).
963
+ * Gets the distance from the light's position to the origin.
992
964
  *
993
965
  * @returns The distance in world units
994
966
  */
@@ -996,17 +968,17 @@ class Sun extends DirectionalLight {
996
968
  return this.position.length();
997
969
  }
998
970
  /**
999
- * Gets the elevation angle (vertical angle from the horizontal plane).
971
+ * Gets the elevation angle from the spherical coordinates.
1000
972
  *
1001
- * @returns The elevation angle in radians (0 = horizontal, π/2 = directly above)
973
+ * @returns The elevation angle in radians (phi angle from Three.js Spherical coordinates)
1002
974
  */
1003
975
  get elevation() {
1004
976
  return this._private_tempSpherical.setFromVector3(this.position).phi;
1005
977
  }
1006
978
  /**
1007
- * Gets the azimuth angle (horizontal rotation around the target).
979
+ * Gets the azimuth angle from the spherical coordinates.
1008
980
  *
1009
- * @returns The azimuth angle in radians (0 = positive X axis, π/2 = positive Z axis)
981
+ * @returns The azimuth angle in radians (theta angle from Three.js Spherical coordinates)
1010
982
  */
1011
983
  get azimuth() {
1012
984
  return this._private_tempSpherical.setFromVector3(this.position).theta;
@@ -1023,7 +995,7 @@ class Sun extends DirectionalLight {
1023
995
  /**
1024
996
  * Sets the elevation angle while preserving current distance and azimuth.
1025
997
  *
1026
- * @param value - The new elevation angle in radians (0 = horizontal, π/2 = directly above)
998
+ * @param value - The new elevation angle in radians (phi angle for Three.js Spherical coordinates)
1027
999
  */
1028
1000
  set elevation(value) {
1029
1001
  this._private_tempSpherical.setFromVector3(this.position);
@@ -1032,18 +1004,18 @@ class Sun extends DirectionalLight {
1032
1004
  /**
1033
1005
  * Sets the azimuth angle while preserving current distance and elevation.
1034
1006
  *
1035
- * @param value - The new azimuth angle in radians (0 = positive X axis, π/2 = positive Z axis)
1007
+ * @param value - The new azimuth angle in radians (theta angle for Three.js Spherical coordinates)
1036
1008
  */
1037
1009
  set azimuth(value) {
1038
1010
  this._private_tempSpherical.setFromVector3(this.position);
1039
1011
  this.position.setFromSphericalCoords(this._private_tempSpherical.radius, this._private_tempSpherical.phi, value);
1040
1012
  }
1041
1013
  /**
1042
- * Configures the shadow camera to optimally cover a bounding box.
1014
+ * Configures the shadow camera frustum to cover a bounding box.
1043
1015
  *
1044
- * This method automatically adjusts the directional light's shadow camera frustum
1045
- * to perfectly encompass the provided bounding box, ensuring efficient shadow map
1046
- * usage and eliminating shadow clipping issues.
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.
1047
1019
  *
1048
1020
  * @param box3 - The 3D bounding box to cover with shadows
1049
1021
  */
@@ -1079,12 +1051,11 @@ class Sun extends DirectionalLight {
1079
1051
  /**
1080
1052
  * Sets the sun's direction based on the brightest point in an HDR environment map.
1081
1053
  *
1082
- * This method analyzes an HDR texture to find the pixel with the highest luminance
1083
- * value and positions the sun to shine from that direction. This is useful for
1084
- * creating realistic lighting that matches HDR environment maps.
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.
1085
1056
  *
1086
1057
  * @param texture - The HDR texture to analyze (must have image data available)
1087
- * @param distance - The distance to place the sun from the origin (defaults to 1)
1058
+ * @param distance - The distance to place the sun from the origin
1088
1059
  */
1089
1060
  setDirectionFromHDRTexture(texture, distance = 1) {
1090
1061
  const data = texture.image.data;