@zephyr3d/scene 0.9.0 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/dist/animation/animationset.js +135 -133
  2. package/dist/animation/animationset.js.map +1 -1
  3. package/dist/animation/cloth/gpu_cloth_system.js +9 -1
  4. package/dist/animation/cloth/gpu_cloth_system.js.map +1 -1
  5. package/dist/animation/fixed_geometry_cache_track.js +5 -1
  6. package/dist/animation/fixed_geometry_cache_track.js.map +1 -1
  7. package/dist/animation/geometry_cache_utils.js +20 -4
  8. package/dist/animation/geometry_cache_utils.js.map +1 -1
  9. package/dist/animation/ik/ik_angle_constraint.js +2 -6
  10. package/dist/animation/ik/ik_angle_constraint.js.map +1 -1
  11. package/dist/animation/ik/two_bone_ik_solver.js +2 -6
  12. package/dist/animation/ik/two_bone_ik_solver.js.map +1 -1
  13. package/dist/animation/joint_dynamics/collision.js +60 -12
  14. package/dist/animation/joint_dynamics/collision.js.map +1 -1
  15. package/dist/animation/joint_dynamics/constraints.js +20 -4
  16. package/dist/animation/joint_dynamics/constraints.js.map +1 -1
  17. package/dist/animation/joint_dynamics/controller.js +151 -103
  18. package/dist/animation/joint_dynamics/controller.js.map +1 -1
  19. package/dist/animation/joint_dynamics/solver.js +21 -11
  20. package/dist/animation/joint_dynamics/solver.js.map +1 -1
  21. package/dist/animation/joint_dynamics/types.js +15 -3
  22. package/dist/animation/joint_dynamics/types.js.map +1 -1
  23. package/dist/animation/pca_geometry_cache_track.js +5 -1
  24. package/dist/animation/pca_geometry_cache_track.js.map +1 -1
  25. package/dist/animation/skeleton.js +2 -2
  26. package/dist/animation/skeleton.js.map +1 -1
  27. package/dist/animation/skeleton_modifier.js +2 -6
  28. package/dist/animation/skeleton_modifier.js.map +1 -1
  29. package/dist/animation/spring/spring_system.js +87 -114
  30. package/dist/animation/spring/spring_system.js.map +1 -1
  31. package/dist/app/app.js.map +1 -1
  32. package/dist/app/engine.js +1 -1
  33. package/dist/app/engine.js.map +1 -1
  34. package/dist/app/screen.js +4 -4
  35. package/dist/app/screen.js.map +1 -1
  36. package/dist/app/scriptingsystem.js +24 -1
  37. package/dist/app/scriptingsystem.js.map +1 -1
  38. package/dist/app/scriptregistry.js +165 -144
  39. package/dist/app/scriptregistry.js.map +1 -1
  40. package/dist/asset/assetmanager.js +2 -2
  41. package/dist/asset/assetmanager.js.map +1 -1
  42. package/dist/asset/model.js +3 -3
  43. package/dist/asset/model.js.map +1 -1
  44. package/dist/camera/camera.js +185 -185
  45. package/dist/camera/camera.js.map +1 -1
  46. package/dist/camera/orbit.js.map +1 -1
  47. package/dist/index.d.ts +794 -261
  48. package/dist/index.js +2 -1
  49. package/dist/index.js.map +1 -1
  50. package/dist/material/material.js +290 -288
  51. package/dist/material/material.js.map +1 -1
  52. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +13 -26
  53. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  54. package/dist/material/pbrmr.js +1 -11
  55. package/dist/material/pbrmr.js.map +1 -1
  56. package/dist/material/sprite.js +6 -6
  57. package/dist/material/sprite.js.map +1 -1
  58. package/dist/material/terrain-cm.js +2 -2
  59. package/dist/material/terrain-cm.js.map +1 -1
  60. package/dist/posteffect/taa.js +31 -39
  61. package/dist/posteffect/taa.js.map +1 -1
  62. package/dist/render/drawable.js +5 -1
  63. package/dist/render/drawable.js.map +1 -1
  64. package/dist/render/rendergraph/device_pool_allocator.js +29 -3
  65. package/dist/render/rendergraph/device_pool_allocator.js.map +1 -1
  66. package/dist/render/rendergraph/executor.js +283 -33
  67. package/dist/render/rendergraph/executor.js.map +1 -1
  68. package/dist/render/rendergraph/forward_plus_builder.js +338 -108
  69. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
  70. package/dist/render/rendergraph/history_resource_manager.js +236 -156
  71. package/dist/render/rendergraph/history_resource_manager.js.map +1 -1
  72. package/dist/render/rendergraph/history_resources.js +10 -0
  73. package/dist/render/rendergraph/history_resources.js.map +1 -0
  74. package/dist/render/rendergraph/rendergraph.js +162 -35
  75. package/dist/render/rendergraph/rendergraph.js.map +1 -1
  76. package/dist/render/rendergraph/types.js +36 -16
  77. package/dist/render/rendergraph/types.js.map +1 -1
  78. package/dist/render/rendertarget.js +5 -1
  79. package/dist/render/rendertarget.js.map +1 -1
  80. package/dist/render/screenrendertarget.js +5 -1
  81. package/dist/render/screenrendertarget.js.map +1 -1
  82. package/dist/render/sky.js +4 -4
  83. package/dist/render/sky.js.map +1 -1
  84. package/dist/scene/basesprite.js +2 -2
  85. package/dist/scene/basesprite.js.map +1 -1
  86. package/dist/scene/graph_node.js +1 -1
  87. package/dist/scene/graph_node.js.map +1 -1
  88. package/dist/scene/mesh.js +4 -20
  89. package/dist/scene/mesh.js.map +1 -1
  90. package/dist/scene/particlesys.js +1 -1
  91. package/dist/scene/particlesys.js.map +1 -1
  92. package/dist/scene/scene_node.js +2 -2
  93. package/dist/scene/scene_node.js.map +1 -1
  94. package/dist/scene/script_attachment.js +15 -3
  95. package/dist/scene/script_attachment.js.map +1 -1
  96. package/dist/scene/terrain-cm/terrain-cm.js +3 -3
  97. package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
  98. package/dist/shadow/shadowmapper.js.map +1 -1
  99. package/dist/shapes/box.js +1 -1
  100. package/dist/shapes/box.js.map +1 -1
  101. package/dist/shapes/capsule.js +0 -3
  102. package/dist/shapes/capsule.js.map +1 -1
  103. package/dist/shapes/cylinder.js +0 -3
  104. package/dist/shapes/cylinder.js.map +1 -1
  105. package/dist/shapes/plane.js +0 -3
  106. package/dist/shapes/plane.js.map +1 -1
  107. package/dist/shapes/tetrahedron.js +3 -9
  108. package/dist/shapes/tetrahedron.js.map +1 -1
  109. package/dist/shapes/torus.js +4 -7
  110. package/dist/shapes/torus.js.map +1 -1
  111. package/dist/utility/blueprint/material/inputs.js +3 -3
  112. package/dist/utility/blueprint/material/inputs.js.map +1 -1
  113. package/dist/utility/blueprint/material/ir.js +493 -493
  114. package/dist/utility/blueprint/material/ir.js.map +1 -1
  115. package/dist/utility/serialization/manager.js +34 -3
  116. package/dist/utility/serialization/manager.js.map +1 -1
  117. package/dist/utility/serialization/scene/animation.js +45 -0
  118. package/dist/utility/serialization/scene/animation.js.map +1 -1
  119. package/dist/utility/serialization/scene/camera.js +53 -0
  120. package/dist/utility/serialization/scene/camera.js.map +1 -1
  121. package/dist/utility/serialization/scene/common.js +10 -0
  122. package/dist/utility/serialization/scene/common.js.map +1 -1
  123. package/dist/utility/serialization/scene/light.js +30 -0
  124. package/dist/utility/serialization/scene/light.js.map +1 -1
  125. package/dist/utility/serialization/scene/material.js +63 -0
  126. package/dist/utility/serialization/scene/material.js.map +1 -1
  127. package/dist/utility/serialization/scene/mesh.js +11 -0
  128. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  129. package/dist/utility/serialization/scene/misc.js +2 -0
  130. package/dist/utility/serialization/scene/misc.js.map +1 -1
  131. package/dist/utility/serialization/scene/node.js +19 -0
  132. package/dist/utility/serialization/scene/node.js.map +1 -1
  133. package/dist/utility/serialization/scene/particle.js +22 -0
  134. package/dist/utility/serialization/scene/particle.js.map +1 -1
  135. package/dist/utility/serialization/scene/primitive.js +33 -0
  136. package/dist/utility/serialization/scene/primitive.js.map +1 -1
  137. package/dist/utility/serialization/scene/scene.js +39 -0
  138. package/dist/utility/serialization/scene/scene.js.map +1 -1
  139. package/dist/utility/serialization/scene/script.js +2 -0
  140. package/dist/utility/serialization/scene/script.js.map +1 -1
  141. package/dist/utility/serialization/scene/sprite.js +6 -0
  142. package/dist/utility/serialization/scene/sprite.js.map +1 -1
  143. package/dist/utility/serialization/scene/terrain.js +9 -0
  144. package/dist/utility/serialization/scene/terrain.js.map +1 -1
  145. package/dist/utility/serialization/scene/water.js +21 -0
  146. package/dist/utility/serialization/scene/water.js.map +1 -1
  147. package/dist/utility/serialization/types.js +5 -1
  148. package/dist/utility/serialization/types.js.map +1 -1
  149. package/package.json +2 -2
@@ -15,9 +15,7 @@
15
15
  */ get weight() {
16
16
  return this._getWeight();
17
17
  }
18
- /**
19
- * Set the blend weight [0-1]
20
- */ set weight(value) {
18
+ set weight(value) {
21
19
  this._setWeight(value);
22
20
  }
23
21
  /**
@@ -25,9 +23,7 @@
25
23
  */ get enabled() {
26
24
  return this._enabled;
27
25
  }
28
- /**
29
- * Set whether this processor is enabled
30
- */ set enabled(value) {
26
+ set enabled(value) {
31
27
  this._enabled = value;
32
28
  }
33
29
  }
@@ -1 +1 @@
1
- {"version":3,"file":"skeleton_modifier.js","sources":["../../src/animation/skeleton_modifier.ts"],"sourcesContent":["import type { Skeleton } from './skeleton';\r\n\r\n/**\r\n * Abstract base class for skeleton post-processors.\r\n *\r\n * Post-processors are applied after the base animation/bind pose layer,\r\n * allowing procedural modifications like IK, spring physics, or manual overrides.\r\n *\r\n * @public\r\n */\r\nexport abstract class SkeletonModifier {\r\n /** Whether this processor is enabled */\r\n protected _enabled: boolean;\r\n\r\n constructor() {\r\n this._enabled = true;\r\n }\r\n\r\n /**\r\n * Get the blend weight [0-1]\r\n */\r\n get weight(): number {\r\n return this._getWeight();\r\n }\r\n\r\n /**\r\n * Set the blend weight [0-1]\r\n */\r\n set weight(value: number) {\r\n this._setWeight(value);\r\n }\r\n\r\n /**\r\n * Get whether this processor is enabled\r\n */\r\n get enabled(): boolean {\r\n return this._enabled;\r\n }\r\n\r\n /**\r\n * Set whether this processor is enabled\r\n */\r\n set enabled(value: boolean) {\r\n this._enabled = value;\r\n }\r\n\r\n /**\r\n * Apply post-processing to skeleton joints.\r\n *\r\n * This method is called after the base animation/bind pose has been applied.\r\n * Implementations should modify joint transforms and blend with the current state\r\n * using the processor's weight.\r\n *\r\n * @param skeleton - The skeleton to process\r\n * @param deltaTime - Time elapsed since last frame (in seconds)\r\n */\r\n abstract apply(skeleton: Skeleton, deltaTime: number): void;\r\n\r\n /**\r\n * Reset the processor to its initial state.\r\n *\r\n * Called when the skeleton or animation state changes significantly.\r\n */\r\n abstract reset(): void;\r\n\r\n /**\r\n * Get the blend weight for this processor.\r\n */\r\n protected abstract _getWeight(): number;\r\n\r\n /**\r\n * Set the blend weight for this processor.\r\n * @param _value - New blend weight (0-1)\r\n */\r\n protected abstract _setWeight(_value: number): void;\r\n}\r\n"],"names":["SkeletonModifier","_enabled","weight","_getWeight","value","_setWeight","enabled"],"mappings":"AAEA;;;;;;;AAOC,IACM,MAAeA,gBAAAA,CAAAA;6CAEpB,QAA4B;IAE5B,WAAc,EAAA;QACZ,IAAI,CAACC,QAAQ,GAAG,IAAA;AAClB;AAEA;;AAEC,MACD,IAAIC,MAAiB,GAAA;QACnB,OAAO,IAAI,CAACC,UAAU,EAAA;AACxB;AAEA;;MAGA,IAAID,MAAOE,CAAAA,KAAa,EAAE;QACxB,IAAI,CAACC,UAAU,CAACD,KAAAA,CAAAA;AAClB;AAEA;;AAEC,MACD,IAAIE,OAAmB,GAAA;QACrB,OAAO,IAAI,CAACL,QAAQ;AACtB;AAEA;;MAGA,IAAIK,OAAQF,CAAAA,KAAc,EAAE;QAC1B,IAAI,CAACH,QAAQ,GAAGG,KAAAA;AAClB;AA+BF;;;;"}
1
+ {"version":3,"file":"skeleton_modifier.js","sources":["../../src/animation/skeleton_modifier.ts"],"sourcesContent":["import type { Skeleton } from './skeleton';\r\n\r\n/**\r\n * Abstract base class for skeleton post-processors.\r\n *\r\n * Post-processors are applied after the base animation/bind pose layer,\r\n * allowing procedural modifications like IK, spring physics, or manual overrides.\r\n *\r\n * @public\r\n */\r\nexport abstract class SkeletonModifier {\r\n /** Whether this processor is enabled */\r\n protected _enabled: boolean;\r\n\r\n constructor() {\r\n this._enabled = true;\r\n }\r\n\r\n /**\r\n * Get the blend weight [0-1]\r\n */\r\n get weight(): number {\r\n return this._getWeight();\r\n }\r\n\r\n set weight(value: number) {\r\n this._setWeight(value);\r\n }\r\n\r\n /**\r\n * Get whether this processor is enabled\r\n */\r\n get enabled(): boolean {\r\n return this._enabled;\r\n }\r\n\r\n set enabled(value: boolean) {\r\n this._enabled = value;\r\n }\r\n\r\n /**\r\n * Apply post-processing to skeleton joints.\r\n *\r\n * This method is called after the base animation/bind pose has been applied.\r\n * Implementations should modify joint transforms and blend with the current state\r\n * using the processor's weight.\r\n *\r\n * @param skeleton - The skeleton to process\r\n * @param deltaTime - Time elapsed since last frame (in seconds)\r\n */\r\n abstract apply(skeleton: Skeleton, deltaTime: number): void;\r\n\r\n /**\r\n * Reset the processor to its initial state.\r\n *\r\n * Called when the skeleton or animation state changes significantly.\r\n */\r\n abstract reset(): void;\r\n\r\n /**\r\n * Get the blend weight for this processor.\r\n */\r\n protected abstract _getWeight(): number;\r\n\r\n /**\r\n * Set the blend weight for this processor.\r\n * @param _value - New blend weight (0-1)\r\n */\r\n protected abstract _setWeight(_value: number): void;\r\n}\r\n"],"names":["SkeletonModifier","_enabled","weight","_getWeight","value","_setWeight","enabled"],"mappings":"AAEA;;;;;;;AAOC,IACM,MAAeA,gBAAAA,CAAAA;6CAEpB,QAA4B;IAE5B,WAAc,EAAA;QACZ,IAAI,CAACC,QAAQ,GAAG,IAAA;AAClB;AAEA;;AAEC,MACD,IAAIC,MAAiB,GAAA;QACnB,OAAO,IAAI,CAACC,UAAU,EAAA;AACxB;IAEA,IAAID,MAAAA,CAAOE,KAAa,EAAE;QACxB,IAAI,CAACC,UAAU,CAACD,KAAAA,CAAAA;AAClB;AAEA;;AAEC,MACD,IAAIE,OAAmB,GAAA;QACrB,OAAO,IAAI,CAACL,QAAQ;AACtB;IAEA,IAAIK,OAAAA,CAAQF,KAAc,EAAE;QAC1B,IAAI,CAACH,QAAQ,GAAGG,KAAAA;AAClB;AA+BF;;;;"}
@@ -7,11 +7,11 @@ const MAX_ACCUMULATED_SIMULATION_TIME = 1 / 20;
7
7
  const MAX_SIMULATION_STEPS_PER_UPDATE = Math.max(1, Math.ceil(MAX_ACCUMULATED_SIMULATION_TIME / FIXED_SIMULATION_TIME_STEP));
8
8
  const DEFAULT_PARTICLE_TARGET_SMOOTHING_TIME = 1 / 30;
9
9
  const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
10
- /**
11
- * Physics engine for spring-based particle simulation
12
- * Uses Verlet integration and iterative constraint solving
13
- *
14
- * @public
10
+ /**
11
+ * Physics engine for spring-based particle simulation
12
+ * Uses Verlet integration and iterative constraint solving
13
+ *
14
+ * @public
15
15
  */ class SpringSystem {
16
16
  _chain;
17
17
  _iterations;
@@ -57,9 +57,9 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
57
57
  this._smoothedCapsuleEndpoints = new WeakMap();
58
58
  this._smoothedPlaneData = new WeakMap();
59
59
  }
60
- /**
61
- * Updates the physics simulation
62
- * @param deltaTime - Time step in seconds
60
+ /**
61
+ * Updates the physics simulation
62
+ * @param deltaTime - Time step in seconds
63
63
  */ update(deltaTime) {
64
64
  const frameDt = Math.min(Math.max(Number(deltaTime) || 0, 0), MAX_ACCUMULATED_SIMULATION_TIME);
65
65
  if (frameDt <= 0) {
@@ -136,8 +136,8 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
136
136
  this.solveCollisions(inputDeltaTime);
137
137
  }
138
138
  }
139
- /**
140
- * Updates fixed particles to match their scene node positions
139
+ /**
140
+ * Updates fixed particles to match their scene node positions
141
141
  */ updateFixedParticles(deltaTime) {
142
142
  const blend = this.getTemporalBlendFactor(deltaTime, DEFAULT_PARTICLE_TARGET_SMOOTHING_TIME);
143
143
  for (const particle of this._chain.particles){
@@ -165,9 +165,9 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
165
165
  }
166
166
  }
167
167
  }
168
- /**
169
- * Solves pose preservation (long-range attachment to animated pose).
170
- * This keeps strands close to authored shape while preserving dynamic movement.
168
+ /**
169
+ * Solves pose preservation (long-range attachment to animated pose).
170
+ * This keeps strands close to authored shape while preserving dynamic movement.
171
171
  */ solvePosePreservation(totalIterations) {
172
172
  if (this._poseFollowRoot <= 0 && this._poseFollowTip <= 0) {
173
173
  return;
@@ -200,9 +200,9 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
200
200
  lerp(a, b, t) {
201
201
  return a + (b - a) * t;
202
202
  }
203
- /**
204
- * Calculates global rotation parameters from fixed particle movements
205
- * Uses position history to estimate rotation center
203
+ /**
204
+ * Calculates global rotation parameters from fixed particle movements
205
+ * Uses position history to estimate rotation center
206
206
  */ calculateGlobalRotation(dt) {
207
207
  // Collect fixed particles with movement
208
208
  const fixedParticles = [];
@@ -260,9 +260,9 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
260
260
  omega: sumOmega
261
261
  };
262
262
  }
263
- /**
264
- * Estimates rotation center from a single particle's position history
265
- * Uses circular motion fitting
263
+ /**
264
+ * Estimates rotation center from a single particle's position history
265
+ * Uses circular motion fitting
266
266
  */ estimateRotationCenterFromHistory(particle, currentVelocity) {
267
267
  const history = particle.positionHistory;
268
268
  if (!history || history.length < 3) {
@@ -298,9 +298,9 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
298
298
  const center = this.calculateCircleCenter(p1, p2, p3);
299
299
  return center;
300
300
  }
301
- /**
302
- * Calculates the center of a circle passing through 3 points
303
- * Uses perpendicular bisector method
301
+ /**
302
+ * Calculates the center of a circle passing through 3 points
303
+ * Uses perpendicular bisector method
304
304
  */ calculateCircleCenter(p1, p2, p3) {
305
305
  // Midpoints
306
306
  const mid12 = Vector3.scale(Vector3.add(p1, p2, new Vector3()), 0.5, new Vector3());
@@ -337,8 +337,8 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
337
337
  // Fallback: use centroid
338
338
  return Vector3.scale(Vector3.add(Vector3.add(p1, p2, new Vector3()), p3, new Vector3()), 1.0 / 3.0, new Vector3());
339
339
  }
340
- /**
341
- * Calculates inertial acceleration for a particle in a rotating reference frame
340
+ /**
341
+ * Calculates inertial acceleration for a particle in a rotating reference frame
342
342
  */ calculateInertialAcceleration(particle, rotationCenter, angularVelocity, particleVelocity, centrifugalScale, coriolisScale) {
343
343
  // Vector from rotation center to particle
344
344
  const r = Vector3.sub(particle.position, rotationCenter, new Vector3());
@@ -355,18 +355,10 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
355
355
  const totalAccel = Vector3.add(centrifugalAccel, coriolisAccel, new Vector3());
356
356
  return totalAccel;
357
357
  }
358
- /**
359
- * Solves a single spring constraint using XPBD (Extended Position-Based Dynamics).
360
- *
361
- * Reference: Müller et al., "Detailed Rigid Body Simulation with Extended Position Based Dynamics", 2020.
362
- *
363
- * The XPBD correction for a distance constraint C(x) = |x_b - x_a| - L is:
364
- * α̃ = compliance / dt² (scaled compliance)
365
- * Δλ = (-C - α̃·λ) / (w_a + w_b + α̃)
366
- * λ += Δλ
367
- * Δx_a = -w_a · Δλ · n̂
368
- * Δx_b = +w_b · Δλ · n̂
369
- * where w = 1/mass (0 for fixed particles), n̂ = unit vector from a to b.
358
+ /**
359
+ * Solves a single spring constraint using XPBD (Extended Position-Based Dynamics).
360
+ *
361
+ * Reference: Müller et al., "Detailed Rigid Body Simulation with Extended Position Based Dynamics", 2020.
370
362
  */ solveConstraintXPBD(constraint, dt) {
371
363
  const pA = this._chain.particles[constraint.particleA];
372
364
  const pB = this._chain.particles[constraint.particleB];
@@ -383,7 +375,7 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
383
375
  }
384
376
  // Constraint value C = currentLength - restLength
385
377
  const C = currentLength - constraint.restLength;
386
- // Scaled compliance: α̃ = compliance / dt²
378
+ // Scaled compliance: alphaTilde = compliance / dt^2
387
379
  const alphaTilde = constraint.compliance / (dt * dt);
388
380
  // XPBD Lagrange multiplier update
389
381
  const deltaLambda = (-C - alphaTilde * constraint.lambda) / (wSum + alphaTilde);
@@ -391,16 +383,16 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
391
383
  // Correction direction (unit vector from A to B)
392
384
  const n = Vector3.scale(delta, 1.0 / currentLength, new Vector3());
393
385
  if (!pA.fixed) {
394
- // Δx_a = -w_a · Δλ · n̂
386
+ // deltaX_a = -w_a * deltaLambda * n
395
387
  Vector3.add(pA.position, Vector3.scale(n, -wA * deltaLambda, new Vector3()), pA.position);
396
388
  }
397
389
  if (!pB.fixed) {
398
- // Δx_b = +w_b · Δλ · n̂
390
+ // deltaX_b = +w_b * deltaLambda * n
399
391
  Vector3.add(pB.position, Vector3.scale(n, wB * deltaLambda, new Vector3()), pB.position);
400
392
  }
401
393
  }
402
- /**
403
- * Solves a single spring constraint (Verlet / PBD)
394
+ /**
395
+ * Solves a single spring constraint (Verlet / PBD)
404
396
  */ solveConstraint(constraint) {
405
397
  const pA = this._chain.particles[constraint.particleA];
406
398
  const pB = this._chain.particles[constraint.particleB];
@@ -421,8 +413,8 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
421
413
  Vector3.sub(pB.position, correction, pB.position);
422
414
  }
423
415
  }
424
- /**
425
- * Solves collisions for all particles
416
+ /**
417
+ * Solves collisions for all particles
426
418
  */ solveCollisions(deltaTime) {
427
419
  // Update dynamic colliders from their nodes
428
420
  const blend = this.getTemporalBlendFactor(deltaTime, DEFAULT_COLLIDER_SMOOTHING_TIME);
@@ -495,9 +487,9 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
495
487
  }
496
488
  }
497
489
  }
498
- /**
499
- * Applies simulation results to scene nodes
500
- * @param weight - Blend weight [0-1] (default: 1.0)
490
+ /**
491
+ * Applies simulation results to scene nodes
492
+ * @param weight - Blend weight [0-1] (default: 1.0)
501
493
  */ applyToNodes(weight = 1.0) {
502
494
  for(let i = 0; i < this._chain.particles.length - 1; i++){
503
495
  const particle = this._chain.particles[i];
@@ -545,8 +537,8 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
545
537
  }
546
538
  }
547
539
  }
548
- /**
549
- * Resets the simulation to initial state
540
+ /**
541
+ * Resets the simulation to initial state
550
542
  */ reset() {
551
543
  this._chain.reset();
552
544
  for (const particle of this._chain.particles){
@@ -562,70 +554,65 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
562
554
  this._smoothedCapsuleEndpoints = new WeakMap();
563
555
  this._smoothedPlaneData = new WeakMap();
564
556
  }
565
- /**
566
- * Gets the spring chain
557
+ /**
558
+ * Gets the spring chain
567
559
  */ get chain() {
568
560
  return this._chain;
569
561
  }
570
- /**
571
- * Gets the current gravity
562
+ /**
563
+ * Gets the current gravity
572
564
  */ get gravity() {
573
565
  return this._gravity;
574
566
  }
575
567
  set gravity(gravity) {
576
568
  this._gravity.set(gravity);
577
569
  }
578
- /**
579
- * Gets the current wind
570
+ /**
571
+ * Gets the current wind
580
572
  */ get wind() {
581
573
  return this._wind;
582
574
  }
583
575
  set wind(wind) {
584
576
  this._wind.set(wind);
585
577
  }
586
- /**
587
- * Gets the number of iterations
578
+ /**
579
+ * Gets the number of iterations
588
580
  */ get iterations() {
589
581
  return this._iterations;
590
582
  }
591
583
  set iterations(count) {
592
584
  this._iterations = Math.max(1, count);
593
585
  }
594
- /**
595
- * Gets whether inertial forces are enabled
586
+ /**
587
+ * Gets whether inertial forces are enabled
596
588
  */ get enableInertialForces() {
597
589
  return this._enableInertialForces;
598
590
  }
599
591
  set enableInertialForces(enabled) {
600
592
  this._enableInertialForces = enabled;
601
593
  }
602
- /**
603
- * Gets the centrifugal force scale
594
+ /**
595
+ * Gets the centrifugal force scale
604
596
  */ get centrifugalScale() {
605
597
  return this._centrifugalScale;
606
598
  }
607
599
  set centrifugalScale(scale) {
608
600
  this._centrifugalScale = Math.max(0, scale);
609
601
  }
610
- /**
611
- * Gets the Coriolis force scale
602
+ /**
603
+ * Gets the Coriolis force scale
612
604
  */ get coriolisScale() {
613
605
  return this._coriolisScale;
614
606
  }
615
- /**
616
- * Sets the Coriolis force scale
617
- */ set coriolisScale(scale) {
607
+ set coriolisScale(scale) {
618
608
  this._coriolisScale = Math.max(0, scale);
619
609
  }
620
- /**
621
- * Gets the constraint solver type
610
+ /**
611
+ * Gets the constraint solver type
622
612
  */ get solver() {
623
613
  return this._solver;
624
614
  }
625
- /**
626
- * Sets the constraint solver type.
627
- * Switching to 'xpbd' resets all Lagrange multipliers.
628
- */ set solver(type) {
615
+ set solver(type) {
629
616
  if (this._solver !== type) {
630
617
  this._solver = type;
631
618
  if (type === 'xpbd') {
@@ -635,92 +622,78 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
635
622
  }
636
623
  }
637
624
  }
638
- /**
639
- * Gets pose preservation strength [0-1]
625
+ /**
626
+ * Gets pose preservation strength [0-1]
640
627
  */ get poseFollow() {
641
628
  return this._poseFollow;
642
629
  }
643
- /**
644
- * Sets pose preservation strength [0-1]
645
- */ set poseFollow(value) {
630
+ set poseFollow(value) {
646
631
  const v = Math.max(0, Math.min(1, value));
647
632
  this._poseFollow = v;
648
633
  this._poseFollowRoot = v;
649
634
  this._poseFollowTip = v;
650
635
  }
651
- /**
652
- * Gets max allowed deviation from animated pose
636
+ /**
637
+ * Gets max allowed deviation from animated pose
653
638
  */ get maxPoseOffset() {
654
639
  return this._maxPoseOffset;
655
640
  }
656
- /**
657
- * Sets max allowed deviation from animated pose. 0 disables clamping.
658
- */ set maxPoseOffset(value) {
641
+ set maxPoseOffset(value) {
659
642
  const v = Math.max(0, value);
660
643
  this._maxPoseOffset = v;
661
644
  this._maxPoseOffsetRoot = v;
662
645
  this._maxPoseOffsetTip = v;
663
646
  }
664
- /**
665
- * Gets root pose follow strength [0-1]
647
+ /**
648
+ * Gets root pose follow strength [0-1]
666
649
  */ get poseFollowRoot() {
667
650
  return this._poseFollowRoot;
668
651
  }
669
- /**
670
- * Sets root pose follow strength [0-1]
671
- */ set poseFollowRoot(value) {
652
+ set poseFollowRoot(value) {
672
653
  this._poseFollowRoot = Math.max(0, Math.min(1, value));
673
654
  }
674
- /**
675
- * Gets tip pose follow strength [0-1]
655
+ /**
656
+ * Gets tip pose follow strength [0-1]
676
657
  */ get poseFollowTip() {
677
658
  return this._poseFollowTip;
678
659
  }
679
- /**
680
- * Sets tip pose follow strength [0-1]
681
- */ set poseFollowTip(value) {
660
+ set poseFollowTip(value) {
682
661
  this._poseFollowTip = Math.max(0, Math.min(1, value));
683
662
  }
684
- /**
685
- * Gets exponent for root->tip interpolation
663
+ /**
664
+ * Gets exponent for root-to-tip interpolation
686
665
  */ get poseFollowExponent() {
687
666
  return this._poseFollowExponent;
688
667
  }
689
- /**
690
- * Sets exponent for root->tip interpolation
691
- */ set poseFollowExponent(value) {
668
+ set poseFollowExponent(value) {
692
669
  this._poseFollowExponent = Math.max(0.1, value);
693
670
  }
694
- /**
695
- * Gets root max allowed deviation from animated pose
671
+ /**
672
+ * Gets root max allowed deviation from animated pose
696
673
  */ get maxPoseOffsetRoot() {
697
674
  return this._maxPoseOffsetRoot;
698
675
  }
699
- /**
700
- * Sets root max allowed deviation from animated pose
701
- */ set maxPoseOffsetRoot(value) {
676
+ set maxPoseOffsetRoot(value) {
702
677
  this._maxPoseOffsetRoot = Math.max(0, value);
703
678
  }
704
- /**
705
- * Gets tip max allowed deviation from animated pose
679
+ /**
680
+ * Gets tip max allowed deviation from animated pose
706
681
  */ get maxPoseOffsetTip() {
707
682
  return this._maxPoseOffsetTip;
708
683
  }
709
- /**
710
- * Sets tip max allowed deviation from animated pose
711
- */ set maxPoseOffsetTip(value) {
684
+ set maxPoseOffsetTip(value) {
712
685
  this._maxPoseOffsetTip = Math.max(0, value);
713
686
  }
714
- /**
715
- * Adds a collider to the system
687
+ /**
688
+ * Adds a collider to the system
716
689
  */ addCollider(collider) {
717
690
  this._colliders.push(collider);
718
691
  this._smoothedSphereCenters = new WeakMap();
719
692
  this._smoothedCapsuleEndpoints = new WeakMap();
720
693
  this._smoothedPlaneData = new WeakMap();
721
694
  }
722
- /**
723
- * Removes a collider from the system
695
+ /**
696
+ * Removes a collider from the system
724
697
  */ removeCollider(collider) {
725
698
  const index = this._colliders.indexOf(collider);
726
699
  if (index >= 0) {
@@ -732,16 +705,16 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME = 1 / 30;
732
705
  }
733
706
  return false;
734
707
  }
735
- /**
736
- * Clears all colliders
708
+ /**
709
+ * Clears all colliders
737
710
  */ clearColliders() {
738
711
  this._colliders = [];
739
712
  this._smoothedSphereCenters = new WeakMap();
740
713
  this._smoothedCapsuleEndpoints = new WeakMap();
741
714
  this._smoothedPlaneData = new WeakMap();
742
715
  }
743
- /**
744
- * Gets all colliders
716
+ /**
717
+ * Gets all colliders
745
718
  */ get colliders() {
746
719
  return this._colliders;
747
720
  }