@zephyr3d/scene 0.8.1 → 0.9.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/animation/animationset.js +563 -128
- package/dist/animation/animationset.js.map +1 -1
- package/dist/animation/cloth/gpu_cloth_system.js +2516 -0
- package/dist/animation/cloth/gpu_cloth_system.js.map +1 -0
- package/dist/animation/fixed_geometry_cache_track.js +138 -0
- package/dist/animation/fixed_geometry_cache_track.js.map +1 -0
- package/dist/animation/geometry_cache_utils.js +120 -0
- package/dist/animation/geometry_cache_utils.js.map +1 -0
- package/dist/animation/ik_modifier.js +9 -1
- package/dist/animation/ik_modifier.js.map +1 -1
- package/dist/animation/joint_dynamics/collision.js +469 -0
- package/dist/animation/joint_dynamics/collision.js.map +1 -0
- package/dist/animation/joint_dynamics/constraints.js +329 -0
- package/dist/animation/joint_dynamics/constraints.js.map +1 -0
- package/dist/animation/joint_dynamics/controller.js +699 -0
- package/dist/animation/joint_dynamics/controller.js.map +1 -0
- package/dist/animation/joint_dynamics/joint_dynamics_system.js +393 -0
- package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -0
- package/dist/animation/joint_dynamics/solver.js +794 -0
- package/dist/animation/joint_dynamics/solver.js.map +1 -0
- package/dist/animation/joint_dynamics/types.js +19 -0
- package/dist/animation/joint_dynamics/types.js.map +1 -0
- package/dist/animation/joint_dynamics/vrm_spring_bone.js +46 -0
- package/dist/animation/joint_dynamics/vrm_spring_bone.js.map +1 -0
- package/dist/animation/joint_dynamics_modifier.js +51 -0
- package/dist/animation/joint_dynamics_modifier.js.map +1 -0
- package/dist/animation/pca_geometry_cache_track.js +222 -0
- package/dist/animation/pca_geometry_cache_track.js.map +1 -0
- package/dist/animation/skeleton.js +1907 -3
- package/dist/animation/skeleton.js.map +1 -1
- package/dist/animation/skeleton_modifier.js +3 -5
- package/dist/animation/skeleton_modifier.js.map +1 -1
- package/dist/animation/spring/multi_chain_spring_system.js +2 -0
- package/dist/animation/spring/multi_chain_spring_system.js.map +1 -1
- package/dist/animation/spring/spring_chain.js +3 -2
- package/dist/animation/spring/spring_chain.js.map +1 -1
- package/dist/animation/spring/spring_collider.js +35 -5
- package/dist/animation/spring/spring_collider.js.map +1 -1
- package/dist/animation/spring/spring_particle.js +1 -0
- package/dist/animation/spring/spring_particle.js.map +1 -1
- package/dist/animation/spring/spring_system.js +325 -28
- package/dist/animation/spring/spring_system.js.map +1 -1
- package/dist/animation/spring2/collision.js +469 -0
- package/dist/animation/spring2/collision.js.map +1 -0
- package/dist/animation/spring2/constraints.js +329 -0
- package/dist/animation/spring2/constraints.js.map +1 -0
- package/dist/animation/spring2/controller.js +434 -0
- package/dist/animation/spring2/controller.js.map +1 -0
- package/dist/animation/spring2/math.js +16 -0
- package/dist/animation/spring2/math.js.map +1 -0
- package/dist/animation/spring2/solver.js +624 -0
- package/dist/animation/spring2/solver.js.map +1 -0
- package/dist/animation/spring2/spring_system.js +118 -0
- package/dist/animation/spring2/spring_system.js.map +1 -0
- package/dist/animation/spring2/types.js +19 -0
- package/dist/animation/spring2/types.js.map +1 -0
- package/dist/animation/spring_modifier.js +17 -1
- package/dist/animation/spring_modifier.js.map +1 -1
- package/dist/app/engine.js +42 -15
- package/dist/app/engine.js.map +1 -1
- package/dist/app/runtimescript.js +132 -1
- package/dist/app/runtimescript.js.map +1 -1
- package/dist/app/screen.js +3 -3
- package/dist/app/screen.js.map +1 -1
- package/dist/app/scriptingsystem.js +69 -37
- package/dist/app/scriptingsystem.js.map +1 -1
- package/dist/app/scriptregistry.js +157 -146
- package/dist/app/scriptregistry.js.map +1 -1
- package/dist/asset/assetmanager.js +2 -1
- package/dist/asset/assetmanager.js.map +1 -1
- package/dist/asset/loaders/zabc/zabc_loader.js +570 -0
- package/dist/asset/loaders/zabc/zabc_loader.js.map +1 -0
- package/dist/asset/model.js +192 -0
- package/dist/asset/model.js.map +1 -1
- package/dist/camera/base.js +26 -7
- package/dist/camera/base.js.map +1 -1
- package/dist/camera/camera.js +146 -24
- package/dist/camera/camera.js.map +1 -1
- package/dist/camera/fps.js +2 -2
- package/dist/camera/fps.js.map +1 -1
- package/dist/camera/orbit.js +2 -2
- package/dist/camera/orbit.js.map +1 -1
- package/dist/index.d.ts +11701 -8506
- package/dist/index.js +29 -8
- package/dist/index.js.map +1 -1
- package/dist/material/lambert.js +1 -1
- package/dist/material/lambert.js.map +1 -1
- package/dist/material/material.js +9 -3
- package/dist/material/material.js.map +1 -1
- package/dist/material/meshmaterial.js +54 -7
- package/dist/material/meshmaterial.js.map +1 -1
- package/dist/material/mixins/lightmodel/blinnphong.js +17 -7
- package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
- package/dist/material/mixins/lightmodel/lambert.js +7 -2
- package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
- package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +108 -16
- package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
- package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +222 -14
- package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
- package/dist/material/mixins/lightmodel/pbrspecularglossness.js +24 -12
- package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
- package/dist/material/mixins/lit.js +11 -8
- package/dist/material/mixins/lit.js.map +1 -1
- package/dist/material/mixins/pbr/common.js +72 -5
- package/dist/material/mixins/pbr/common.js.map +1 -1
- package/dist/material/pbrblueprint.js +148 -1
- package/dist/material/pbrblueprint.js.map +1 -1
- package/dist/material/pbrmr.js +125 -2
- package/dist/material/pbrmr.js.map +1 -1
- package/dist/material/shader/helper.js +10 -4
- package/dist/material/shader/helper.js.map +1 -1
- package/dist/material/water.js +2 -2
- package/dist/material/water.js.map +1 -1
- package/dist/posteffect/coloradjust.js +145 -0
- package/dist/posteffect/coloradjust.js.map +1 -0
- package/dist/posteffect/taa.js +68 -32
- package/dist/posteffect/taa.js.map +1 -1
- package/dist/render/cluster_light.js +17 -12
- package/dist/render/cluster_light.js.map +1 -1
- package/dist/render/deferredlightpass.js +510 -0
- package/dist/render/deferredlightpass.js.map +1 -0
- package/dist/render/deferredshadowlightpass.js +428 -0
- package/dist/render/deferredshadowlightpass.js.map +1 -0
- package/dist/render/drawable.js.map +1 -1
- package/dist/render/drawable_mixin.js +21 -12
- package/dist/render/drawable_mixin.js.map +1 -1
- package/dist/render/envlight.js +20 -22
- package/dist/render/envlight.js.map +1 -1
- package/dist/render/gbufferpass.js +50 -0
- package/dist/render/gbufferpass.js.map +1 -0
- package/dist/render/lightpass.js +1 -2
- package/dist/render/lightpass.js.map +1 -1
- package/dist/render/primitive.js +1 -1
- package/dist/render/primitive.js.map +1 -1
- package/dist/render/render_queue.js +3 -2
- package/dist/render/render_queue.js.map +1 -1
- package/dist/render/renderer.js +5 -358
- package/dist/render/renderer.js.map +1 -1
- package/dist/render/rendergraph/executor.js +15 -12
- package/dist/render/rendergraph/executor.js.map +1 -1
- package/dist/render/rendergraph/forward_plus_builder.js +144 -88
- package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
- package/dist/render/rendergraph/history_resource_manager.js +178 -0
- package/dist/render/rendergraph/history_resource_manager.js.map +1 -0
- package/dist/render/rendergraph/rendergraph.js +12 -1
- package/dist/render/rendergraph/rendergraph.js.map +1 -1
- package/dist/render/rendergraph/types.js +2 -2
- package/dist/render/rendergraph/types.js.map +1 -1
- package/dist/render/sky.js +26 -9
- package/dist/render/sky.js.map +1 -1
- package/dist/scene/basesprite.js +4 -3
- package/dist/scene/basesprite.js.map +1 -1
- package/dist/scene/batchgroup.js +4 -4
- package/dist/scene/environment.js +7 -4
- package/dist/scene/environment.js.map +1 -1
- package/dist/scene/light.js +184 -18
- package/dist/scene/light.js.map +1 -1
- package/dist/scene/mesh.js +30 -0
- package/dist/scene/mesh.js.map +1 -1
- package/dist/scene/particlesys.js +3 -2
- package/dist/scene/particlesys.js.map +1 -1
- package/dist/scene/raycast_visitor.js +29 -3
- package/dist/scene/raycast_visitor.js.map +1 -1
- package/dist/scene/scene.js +86 -19
- package/dist/scene/scene.js.map +1 -1
- package/dist/scene/scene_node.js +87 -31
- package/dist/scene/scene_node.js.map +1 -1
- package/dist/scene/script_attachment.js +59 -0
- package/dist/scene/script_attachment.js.map +1 -0
- package/dist/scene/terrain-cm/grass.js +3 -2
- package/dist/scene/terrain-cm/grass.js.map +1 -1
- package/dist/scene/terrain-cm/terrain-cm.js +4 -3
- package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
- package/dist/scene/water.js +3 -2
- package/dist/scene/water.js.map +1 -1
- package/dist/shaders/shadow.js +2 -2
- package/dist/shaders/shadow.js.map +1 -1
- package/dist/shadow/shadowmapper.js +74 -4
- package/dist/shadow/shadowmapper.js.map +1 -1
- package/dist/shapes/box.js +163 -0
- package/dist/shapes/box.js.map +1 -1
- package/dist/shapes/capsule.js +216 -0
- package/dist/shapes/capsule.js.map +1 -0
- package/dist/shapes/cylinder.js +91 -0
- package/dist/shapes/cylinder.js.map +1 -1
- package/dist/shapes/plane.js +32 -0
- package/dist/shapes/plane.js.map +1 -1
- package/dist/shapes/tetrahedron.js +211 -0
- package/dist/shapes/tetrahedron.js.map +1 -1
- package/dist/shapes/torus.js +173 -0
- package/dist/shapes/torus.js.map +1 -1
- package/dist/utility/blueprint/common/math.js +111 -1
- package/dist/utility/blueprint/common/math.js.map +1 -1
- package/dist/utility/blueprint/material/inputs.js +235 -1
- package/dist/utility/blueprint/material/inputs.js.map +1 -1
- package/dist/utility/blueprint/material/ir.js +154 -10
- package/dist/utility/blueprint/material/ir.js.map +1 -1
- package/dist/utility/blueprint/material/texture.js +273 -19
- package/dist/utility/blueprint/material/texture.js.map +1 -1
- package/dist/utility/serialization/json.js +12 -2
- package/dist/utility/serialization/json.js.map +1 -1
- package/dist/utility/serialization/manager.js +30 -11
- package/dist/utility/serialization/manager.js.map +1 -1
- package/dist/utility/serialization/scene/animation.js +250 -7
- package/dist/utility/serialization/scene/animation.js.map +1 -1
- package/dist/utility/serialization/scene/batch.js +4 -2
- package/dist/utility/serialization/scene/batch.js.map +1 -1
- package/dist/utility/serialization/scene/camera.js +154 -2
- package/dist/utility/serialization/scene/camera.js.map +1 -1
- package/dist/utility/serialization/scene/cloth_script.js +834 -0
- package/dist/utility/serialization/scene/cloth_script.js.map +1 -0
- package/dist/utility/serialization/scene/common.js +7 -0
- package/dist/utility/serialization/scene/common.js.map +1 -1
- package/dist/utility/serialization/scene/light.js +120 -4
- package/dist/utility/serialization/scene/light.js.map +1 -1
- package/dist/utility/serialization/scene/material.js +453 -1
- package/dist/utility/serialization/scene/material.js.map +1 -1
- package/dist/utility/serialization/scene/mesh.js +4 -2
- package/dist/utility/serialization/scene/mesh.js.map +1 -1
- package/dist/utility/serialization/scene/node.js +298 -10
- package/dist/utility/serialization/scene/node.js.map +1 -1
- package/dist/utility/serialization/scene/particle.js +4 -2
- package/dist/utility/serialization/scene/particle.js.map +1 -1
- package/dist/utility/serialization/scene/primitive.js +100 -3
- package/dist/utility/serialization/scene/primitive.js.map +1 -1
- package/dist/utility/serialization/scene/scene.js +130 -3
- package/dist/utility/serialization/scene/scene.js.map +1 -1
- package/dist/utility/serialization/scene/script.js +66 -0
- package/dist/utility/serialization/scene/script.js.map +1 -0
- package/dist/utility/serialization/scene/spring_script.js +596 -0
- package/dist/utility/serialization/scene/spring_script.js.map +1 -0
- package/dist/utility/serialization/scene/sprite.js +5 -3
- package/dist/utility/serialization/scene/sprite.js.map +1 -1
- package/dist/utility/serialization/scene/terrain.js +4 -2
- package/dist/utility/serialization/scene/terrain.js.map +1 -1
- package/dist/utility/serialization/scene/water.js +4 -2
- package/dist/utility/serialization/scene/water.js.map +1 -1
- package/dist/utility/serialization/types.js.map +1 -1
- package/dist/values.js +5 -1
- package/dist/values.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multi_chain_spring_system.js","sources":["../../../src/animation/spring/multi_chain_spring_system.ts"],"sourcesContent":["import type { Nullable } from '@zephyr3d/base';\r\nimport { Vector3, Quaternion } from '@zephyr3d/base';\r\nimport type { SpringChain } from './spring_chain';\r\nimport type { SpringConstraint } from './spring_constraint';\r\nimport { IKUtils } from '../ik/ik_utils';\r\n\r\n/**\r\n * Constraint between particles in different chains\r\n *\r\n * @public\r\n */\r\nexport interface InterChainConstraint {\r\n /** Index of the first chain */\r\n chainAIndex: number;\r\n /** Index of the second chain */\r\n chainBIndex: number;\r\n /** Index of particle in chain A */\r\n particleAIndex: number;\r\n /** Index of particle in chain B */\r\n particleBIndex: number;\r\n /** Desired distance between particles */\r\n restLength: number;\r\n /** Constraint strength [0-1], used by Verlet solver */\r\n stiffness: number;\r\n /**\r\n * XPBD compliance (inverse stiffness) in m/N.\r\n * Only used when solver is 'xpbd'.\r\n */\r\n compliance: number;\r\n /** XPBD Lagrange multiplier accumulator, reset each time step. */\r\n lambda: number;\r\n}\r\n\r\n/**\r\n * Options for creating a MultiChainSpringSystem\r\n *\r\n * @public\r\n */\r\nexport interface MultiChainSpringSystemOptions {\r\n /** Number of constraint solver iterations (default: 5) */\r\n iterations?: number;\r\n /** Gravity force vector (default: (0, -9.8, 0)) */\r\n gravity?: Vector3;\r\n /** Wind force vector (default: (0, 0, 0)) */\r\n wind?: Vector3;\r\n /** Enable inertial forces (centrifugal/Coriolis) when root rotates (default: true) */\r\n enableInertialForces?: boolean;\r\n /** Centrifugal force multiplier (default: 1.0) */\r\n centrifugalScale?: number;\r\n /** Coriolis force multiplier (default: 1.0) */\r\n coriolisScale?: number;\r\n /**\r\n * Constraint solver type (default: 'verlet').\r\n * - 'verlet': stiffness [0-1] controls per-iteration correction strength.\r\n * - 'xpbd': compliance (m/N) gives physically correct, iteration-independent results.\r\n */\r\n solver?: 'verlet' | 'xpbd';\r\n}\r\n\r\n/**\r\n * Physics engine for multiple spring chains with inter-chain constraints\r\n * Suitable for cloth, skirts, capes, and other multi-chain simulations\r\n *\r\n * @public\r\n */\r\nexport class MultiChainSpringSystem {\r\n private _chains: SpringChain[];\r\n private _interChainConstraints: InterChainConstraint[];\r\n private _iterations: number;\r\n private _gravity: Vector3;\r\n private _wind: Vector3;\r\n private _enableInertialForces: boolean;\r\n private _centrifugalScale: number;\r\n private _coriolisScale: number;\r\n private _solver: 'verlet' | 'xpbd';\r\n\r\n constructor(options?: MultiChainSpringSystemOptions) {\r\n this._chains = [];\r\n this._interChainConstraints = [];\r\n this._iterations = options?.iterations ?? 5;\r\n this._gravity = options?.gravity?.clone() ?? new Vector3(0, -9.8, 0);\r\n this._wind = options?.wind?.clone() ?? new Vector3(0, 0, 0);\r\n this._enableInertialForces = options?.enableInertialForces ?? true;\r\n this._centrifugalScale = options?.centrifugalScale ?? 1.0;\r\n this._coriolisScale = options?.coriolisScale ?? 1.0;\r\n this._solver = options?.solver ?? 'verlet';\r\n }\r\n\r\n /**\r\n * Adds a spring chain to the system\r\n * @param chain - The chain to add\r\n * @returns The index of the added chain\r\n */\r\n addChain(chain: SpringChain): number {\r\n this._chains.push(chain);\r\n return this._chains.length - 1;\r\n }\r\n\r\n /**\r\n * Adds an inter-chain constraint\r\n * @param constraint - The constraint to add\r\n */\r\n addInterChainConstraint(constraint: InterChainConstraint): void {\r\n this._interChainConstraints.push(constraint);\r\n }\r\n\r\n /**\r\n * Creates radial constraints between adjacent chains\r\n * Useful for skirts, capes, and other radial multi-chain structures\r\n * @param options - Configuration options\r\n */\r\n createRadialConstraints(options: {\r\n /** Constraint stiffness [0-1], used by Verlet solver */\r\n stiffness: number;\r\n /** Maximum distance to create constraints (particles further apart are not connected) */\r\n maxDistance: number;\r\n /** Skip first N rows of particles (e.g., anchor points at waist) */\r\n skipRows?: number;\r\n /** Connect to next N chains (default: 1, only adjacent chains) */\r\n connectDistance?: number;\r\n /** XPBD compliance in m/N (default: 0 = rigid). Only used when solver is 'xpbd'. */\r\n compliance?: number;\r\n }): void {\r\n const skipRows = options.skipRows ?? 0;\r\n const connectDistance = options.connectDistance ?? 1;\r\n const compliance = options.compliance ?? 0;\r\n\r\n for (let i = 0; i < this._chains.length; i++) {\r\n for (let offset = 1; offset <= connectDistance; offset++) {\r\n const j = (i + offset) % this._chains.length;\r\n const chainA = this._chains[i];\r\n const chainB = this._chains[j];\r\n\r\n const minLength = Math.min(chainA.particles.length, chainB.particles.length);\r\n\r\n for (let row = skipRows; row < minLength; row++) {\r\n const pA = chainA.particles[row];\r\n const pB = chainB.particles[row];\r\n const distance = Vector3.distance(pA.position, pB.position);\r\n\r\n if (distance <= options.maxDistance) {\r\n this.addInterChainConstraint({\r\n chainAIndex: i,\r\n chainBIndex: j,\r\n particleAIndex: row,\r\n particleBIndex: row,\r\n restLength: distance,\r\n stiffness: options.stiffness,\r\n compliance,\r\n lambda: 0\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Updates the physics simulation for all chains\r\n * @param deltaTime - Time step in seconds\r\n */\r\n update(deltaTime: number): void {\r\n const dt = Math.min(deltaTime, 0.033);\r\n\r\n // Save all particle positions before updating\r\n if (this._enableInertialForces) {\r\n for (const chain of this._chains) {\r\n for (const p of chain.particles) {\r\n p.lastFramePosition.set(p.position);\r\n }\r\n }\r\n }\r\n\r\n this.updateFixedParticles();\r\n\r\n // Calculate global rotation parameters\r\n let rotationCenter: Nullable<Vector3> = null;\r\n let angularVelocity: Nullable<Vector3> = null;\r\n\r\n if (this._enableInertialForces && dt > 0.0001) {\r\n const result = this.calculateGlobalRotation(dt);\r\n rotationCenter = result.center;\r\n angularVelocity = result.omega;\r\n }\r\n\r\n for (const chain of this._chains) {\r\n for (const particle of chain.particles) {\r\n if (particle.fixed) {\r\n continue;\r\n }\r\n\r\n const velocity = Vector3.sub(particle.position, particle.prevPosition, new Vector3());\r\n velocity.scaleBy(particle.damping);\r\n\r\n const acceleration = Vector3.add(this._gravity, this._wind, new Vector3());\r\n\r\n // Apply inertial forces\r\n if (this._enableInertialForces && rotationCenter && angularVelocity) {\r\n const inertialAccel = this.calculateInertialAcceleration(\r\n particle,\r\n rotationCenter,\r\n angularVelocity,\r\n velocity,\r\n this._centrifugalScale,\r\n this._coriolisScale\r\n );\r\n Vector3.add(acceleration, inertialAccel, acceleration);\r\n }\r\n\r\n const positionDelta = Vector3.scale(acceleration, dt * dt, new Vector3());\r\n Vector3.add(velocity, positionDelta, velocity);\r\n\r\n particle.prevPosition.set(particle.position);\r\n Vector3.add(particle.position, velocity, particle.position);\r\n }\r\n }\r\n\r\n if (this._solver === 'xpbd') {\r\n for (const chain of this._chains) {\r\n for (const c of chain.constraints) {\r\n c.lambda = 0;\r\n }\r\n }\r\n for (const c of this._interChainConstraints) {\r\n c.lambda = 0;\r\n }\r\n }\r\n for (let iter = 0; iter < this._iterations; iter++) {\r\n for (const chain of this._chains) {\r\n for (const constraint of chain.constraints) {\r\n if (this._solver === 'xpbd') {\r\n this.solveConstraintXPBD(chain, constraint, dt);\r\n } else {\r\n this.solveConstraint(chain, constraint);\r\n }\r\n }\r\n }\r\n\r\n for (const constraint of this._interChainConstraints) {\r\n if (this._solver === 'xpbd') {\r\n this.solveInterChainConstraintXPBD(constraint, dt);\r\n } else {\r\n this.solveInterChainConstraint(constraint);\r\n }\r\n }\r\n }\r\n }\r\n\r\n private updateFixedParticles(): void {\r\n for (const chain of this._chains) {\r\n for (const particle of chain.particles) {\r\n if (particle.fixed && particle.node) {\r\n const worldPos = new Vector3(\r\n particle.node.worldMatrix.m03,\r\n particle.node.worldMatrix.m13,\r\n particle.node.worldMatrix.m23\r\n );\r\n particle.position.set(worldPos);\r\n particle.prevPosition.set(worldPos);\r\n\r\n // Maintain position history\r\n if (this._enableInertialForces) {\r\n if (!particle.positionHistory) {\r\n particle.positionHistory = [];\r\n }\r\n particle.positionHistory.push(worldPos.clone());\r\n if (particle.positionHistory.length > 5) {\r\n particle.positionHistory.shift();\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n private calculateGlobalRotation(dt: number): { center: Vector3; omega: Vector3 } {\r\n const fixedParticles: any[] = [];\r\n const velocities: Vector3[] = [];\r\n\r\n for (const chain of this._chains) {\r\n for (const p of chain.particles) {\r\n if (!p.fixed) {\r\n continue;\r\n }\r\n\r\n const velocity = Vector3.sub(p.position, p.lastFramePosition, new Vector3());\r\n velocity.scaleBy(1.0 / dt);\r\n\r\n if (velocity.magnitudeSq > 0.001) {\r\n fixedParticles.push(p);\r\n velocities.push(velocity);\r\n }\r\n }\r\n }\r\n\r\n if (fixedParticles.length === 0) {\r\n return { center: new Vector3(0, 0, 0), omega: new Vector3(0, 0, 0) };\r\n }\r\n\r\n // Estimate rotation center\r\n let center: Vector3;\r\n\r\n if (fixedParticles.length === 1) {\r\n center = this.estimateRotationCenterFromHistory(fixedParticles[0], velocities[0]);\r\n } else {\r\n center = new Vector3(0, 0, 0);\r\n for (const p of fixedParticles) {\r\n Vector3.add(center, p.position, center);\r\n }\r\n center.scaleBy(1.0 / fixedParticles.length);\r\n }\r\n\r\n // Estimate angular velocity\r\n let sumOmega = new Vector3(0, 0, 0);\r\n let count = 0;\r\n\r\n for (let i = 0; i < fixedParticles.length; i++) {\r\n const r = Vector3.sub(fixedParticles[i].position, center, new Vector3());\r\n const v = velocities[i];\r\n const rLengthSq = r.magnitudeSq;\r\n\r\n if (rLengthSq > 0.0001) {\r\n const omega = Vector3.cross(r, v, new Vector3());\r\n omega.scaleBy(1.0 / rLengthSq);\r\n Vector3.add(sumOmega, omega, sumOmega);\r\n count++;\r\n }\r\n }\r\n\r\n if (count > 0) {\r\n sumOmega.scaleBy(1.0 / count);\r\n }\r\n\r\n return { center, omega: sumOmega };\r\n }\r\n\r\n private estimateRotationCenterFromHistory(particle: any, currentVelocity: Vector3): Vector3 {\r\n const history = particle.positionHistory;\r\n if (!history || history.length < 3) {\r\n const speed = currentVelocity.magnitude;\r\n if (speed < 0.001) {\r\n return particle.position.clone();\r\n }\r\n\r\n const estimatedRadius = Math.max(0.5, speed * 0.5);\r\n const up = new Vector3(0, 1, 0);\r\n const perpDir = Vector3.cross(currentVelocity, up, new Vector3());\r\n\r\n if (perpDir.magnitudeSq < 0.0001) {\r\n perpDir.set(new Vector3(1, 0, 0));\r\n } else {\r\n Vector3.normalize(perpDir, perpDir);\r\n }\r\n\r\n const center = Vector3.add(\r\n particle.position,\r\n Vector3.scale(perpDir, estimatedRadius, new Vector3()),\r\n new Vector3()\r\n );\r\n return center;\r\n }\r\n\r\n const p1 = history[0];\r\n const p2 = history[Math.floor(history.length / 2)];\r\n const p3 = history[history.length - 1];\r\n\r\n const center = this.calculateCircleCenter(p1, p2, p3);\r\n return center;\r\n }\r\n\r\n private calculateCircleCenter(p1: Vector3, p2: Vector3, p3: Vector3): Vector3 {\r\n const mid12 = Vector3.scale(Vector3.add(p1, p2, new Vector3()), 0.5, new Vector3());\r\n const mid23 = Vector3.scale(Vector3.add(p2, p3, new Vector3()), 0.5, new Vector3());\r\n\r\n const dir12 = Vector3.sub(p2, p1, new Vector3());\r\n const dir23 = Vector3.sub(p3, p2, new Vector3());\r\n\r\n const normal = Vector3.cross(dir12, dir23, new Vector3());\r\n\r\n if (normal.magnitudeSq < 0.0001) {\r\n return Vector3.scale(\r\n Vector3.add(Vector3.add(p1, p2, new Vector3()), p3, new Vector3()),\r\n 1.0 / 3.0,\r\n new Vector3()\r\n );\r\n }\r\n\r\n Vector3.normalize(normal, normal);\r\n\r\n const perp12 = Vector3.cross(dir12, normal, new Vector3());\r\n Vector3.normalize(perp12, perp12);\r\n\r\n const perp23 = Vector3.cross(dir23, normal, new Vector3());\r\n Vector3.normalize(perp23, perp23);\r\n\r\n const diff = Vector3.sub(mid23, mid12, new Vector3());\r\n\r\n const det = perp12.x * perp23.y - perp12.y * perp23.x;\r\n\r\n if (Math.abs(det) > 0.0001) {\r\n const t = (diff.x * perp23.y - diff.y * perp23.x) / det;\r\n const center = Vector3.add(mid12, Vector3.scale(perp12, t, new Vector3()), new Vector3());\r\n return center;\r\n }\r\n\r\n return Vector3.scale(\r\n Vector3.add(Vector3.add(p1, p2, new Vector3()), p3, new Vector3()),\r\n 1.0 / 3.0,\r\n new Vector3()\r\n );\r\n }\r\n\r\n private calculateInertialAcceleration(\r\n particle: any,\r\n rotationCenter: Vector3,\r\n angularVelocity: Vector3,\r\n particleVelocity: Vector3,\r\n centrifugalScale: number,\r\n coriolisScale: number\r\n ): Vector3 {\r\n const r = Vector3.sub(particle.position, rotationCenter, new Vector3());\r\n\r\n const omegaCrossR = Vector3.cross(angularVelocity, r, new Vector3());\r\n const centrifugalAccel = Vector3.cross(angularVelocity, omegaCrossR, new Vector3());\r\n centrifugalAccel.scaleBy(centrifugalScale);\r\n\r\n const coriolisAccel = Vector3.cross(angularVelocity, particleVelocity, new Vector3());\r\n coriolisAccel.scaleBy(-2.0 * coriolisScale);\r\n\r\n const totalAccel = Vector3.add(centrifugalAccel, coriolisAccel, new Vector3());\r\n return totalAccel;\r\n }\r\n\r\n private solveConstraint(chain: SpringChain, constraint: SpringConstraint): void {\r\n const pA = chain.particles[constraint.particleA];\r\n const pB = chain.particles[constraint.particleB];\r\n\r\n const delta = Vector3.sub(pB.position, pA.position, new Vector3());\r\n const currentLength = delta.magnitude;\r\n\r\n if (currentLength < 0.0001) {\r\n return;\r\n }\r\n\r\n const diff = (currentLength - constraint.restLength) / currentLength;\r\n const correction = Vector3.scale(delta, diff * constraint.stiffness * 0.5, new Vector3());\r\n\r\n if (!pA.fixed) {\r\n Vector3.add(pA.position, correction, pA.position);\r\n }\r\n if (!pB.fixed) {\r\n Vector3.sub(pB.position, correction, pB.position);\r\n }\r\n }\r\n\r\n private solveInterChainConstraint(constraint: InterChainConstraint): void {\r\n const chainA = this._chains[constraint.chainAIndex];\r\n const chainB = this._chains[constraint.chainBIndex];\r\n const pA = chainA.particles[constraint.particleAIndex];\r\n const pB = chainB.particles[constraint.particleBIndex];\r\n\r\n const delta = Vector3.sub(pB.position, pA.position, new Vector3());\r\n const currentLength = delta.magnitude;\r\n\r\n if (currentLength < 0.0001) {\r\n return;\r\n }\r\n\r\n const diff = (currentLength - constraint.restLength) / currentLength;\r\n const correction = Vector3.scale(delta, diff * constraint.stiffness * 0.5, new Vector3());\r\n\r\n if (!pA.fixed) {\r\n Vector3.add(pA.position, correction, pA.position);\r\n }\r\n if (!pB.fixed) {\r\n Vector3.sub(pB.position, correction, pB.position);\r\n }\r\n }\r\n\r\n private solveConstraintXPBD(chain: SpringChain, constraint: SpringConstraint, dt: number): void {\r\n const pA = chain.particles[constraint.particleA];\r\n const pB = chain.particles[constraint.particleB];\r\n\r\n const wA = pA.fixed ? 0 : 1.0 / pA.mass;\r\n const wB = pB.fixed ? 0 : 1.0 / pB.mass;\r\n const wSum = wA + wB;\r\n if (wSum < 1e-10) {\r\n return;\r\n }\r\n\r\n const delta = Vector3.sub(pB.position, pA.position, new Vector3());\r\n const currentLength = delta.magnitude;\r\n if (currentLength < 0.0001) {\r\n return;\r\n }\r\n\r\n const C = currentLength - constraint.restLength;\r\n const alphaTilde = constraint.compliance / (dt * dt);\r\n const deltaLambda = (-C - alphaTilde * constraint.lambda) / (wSum + alphaTilde);\r\n constraint.lambda += deltaLambda;\r\n\r\n const n = Vector3.scale(delta, 1.0 / currentLength, new Vector3());\r\n if (!pA.fixed) {\r\n Vector3.add(pA.position, Vector3.scale(n, -wA * deltaLambda, new Vector3()), pA.position);\r\n }\r\n if (!pB.fixed) {\r\n Vector3.add(pB.position, Vector3.scale(n, wB * deltaLambda, new Vector3()), pB.position);\r\n }\r\n }\r\n\r\n private solveInterChainConstraintXPBD(constraint: InterChainConstraint, dt: number): void {\r\n const chainA = this._chains[constraint.chainAIndex];\r\n const chainB = this._chains[constraint.chainBIndex];\r\n const pA = chainA.particles[constraint.particleAIndex];\r\n const pB = chainB.particles[constraint.particleBIndex];\r\n\r\n const wA = pA.fixed ? 0 : 1.0 / pA.mass;\r\n const wB = pB.fixed ? 0 : 1.0 / pB.mass;\r\n const wSum = wA + wB;\r\n if (wSum < 1e-10) {\r\n return;\r\n }\r\n\r\n const delta = Vector3.sub(pB.position, pA.position, new Vector3());\r\n const currentLength = delta.magnitude;\r\n if (currentLength < 0.0001) {\r\n return;\r\n }\r\n\r\n const C = currentLength - constraint.restLength;\r\n const alphaTilde = constraint.compliance / (dt * dt);\r\n const deltaLambda = (-C - alphaTilde * constraint.lambda) / (wSum + alphaTilde);\r\n constraint.lambda += deltaLambda;\r\n\r\n const n = Vector3.scale(delta, 1.0 / currentLength, new Vector3());\r\n if (!pA.fixed) {\r\n Vector3.add(pA.position, Vector3.scale(n, -wA * deltaLambda, new Vector3()), pA.position);\r\n }\r\n if (!pB.fixed) {\r\n Vector3.add(pB.position, Vector3.scale(n, wB * deltaLambda, new Vector3()), pB.position);\r\n }\r\n }\r\n\r\n /**\r\n * Applies simulation results to scene nodes\r\n * @param weight - Blend weight [0-1] (default: 1.0)\r\n */\r\n applyToNodes(weight: number = 1.0): void {\r\n for (const chain of this._chains) {\r\n this.applyChainToNodes(chain, weight);\r\n }\r\n }\r\n\r\n private applyChainToNodes(chain: SpringChain, weight: number): void {\r\n for (let i = 0; i < chain.particles.length - 1; i++) {\r\n const particle = chain.particles[i];\r\n const nextParticle = chain.particles[i + 1];\r\n\r\n if (!particle.node) {\r\n continue;\r\n }\r\n\r\n // Get current bone direction from node's world matrix (before physics)\r\n const currentBonePos = new Vector3(\r\n particle.node.worldMatrix.m03,\r\n particle.node.worldMatrix.m13,\r\n particle.node.worldMatrix.m23\r\n );\r\n\r\n const nextNode = nextParticle.node;\r\n if (!nextNode) {\r\n continue;\r\n }\r\n\r\n const nextBonePos = new Vector3(\r\n nextNode.worldMatrix.m03,\r\n nextNode.worldMatrix.m13,\r\n nextNode.worldMatrix.m23\r\n );\r\n const originalDir = Vector3.sub(nextBonePos, currentBonePos, new Vector3());\r\n\r\n // Get current bone rotation from node's world matrix\r\n const currentBoneRotation = new Quaternion();\r\n particle.node.worldMatrix.decompose(null, currentBoneRotation, null);\r\n\r\n // Calculate new direction from physics simulation\r\n const newDir = Vector3.sub(nextParticle.position, particle.position, new Vector3());\r\n\r\n const deltaRotation = new Quaternion();\r\n IKUtils.fromToRotation(originalDir, newDir, deltaRotation);\r\n\r\n let worldRotation = Quaternion.multiply(deltaRotation, currentBoneRotation, new Quaternion());\r\n\r\n if (weight < 1) {\r\n Quaternion.slerp(currentBoneRotation, worldRotation, weight, worldRotation);\r\n }\r\n\r\n const parent = particle.node.parent;\r\n if (parent) {\r\n const parentWorldRotation = new Quaternion();\r\n parent.worldMatrix.decompose(null, parentWorldRotation, null);\r\n const parentInvRotation = Quaternion.conjugate(parentWorldRotation, new Quaternion());\r\n const localRotation = Quaternion.multiply(parentInvRotation, worldRotation, new Quaternion());\r\n particle.node.rotation = localRotation;\r\n } else {\r\n particle.node.rotation = worldRotation;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Resets the simulation to initial state\r\n */\r\n reset(): void {\r\n for (const chain of this._chains) {\r\n chain.reset();\r\n }\r\n }\r\n\r\n /**\r\n * Gets the spring chains\r\n */\r\n get chains(): SpringChain[] {\r\n return this._chains;\r\n }\r\n\r\n /**\r\n * Gets the inter-chain constraints\r\n */\r\n get interChainConstraints(): InterChainConstraint[] {\r\n return this._interChainConstraints;\r\n }\r\n\r\n /**\r\n * Gets the current gravity\r\n */\r\n get gravity(): Vector3 {\r\n return this._gravity;\r\n }\r\n\r\n set gravity(gravity: Vector3) {\r\n this._gravity.set(gravity);\r\n }\r\n\r\n /**\r\n * Gets the current wind\r\n */\r\n get wind(): Vector3 {\r\n return this._wind;\r\n }\r\n\r\n set wind(wind: Vector3) {\r\n this._wind.set(wind);\r\n }\r\n\r\n /**\r\n * Gets the number of iterations\r\n */\r\n get iterations(): number {\r\n return this._iterations;\r\n }\r\n\r\n set iterations(count: number) {\r\n this._iterations = Math.max(1, count);\r\n }\r\n\r\n /**\r\n * Gets whether inertial forces are enabled\r\n */\r\n get enableInertialForces(): boolean {\r\n return this._enableInertialForces;\r\n }\r\n\r\n set enableInertialForces(enabled: boolean) {\r\n this._enableInertialForces = enabled;\r\n }\r\n\r\n /**\r\n * Gets the centrifugal force scale\r\n */\r\n get centrifugalScale(): number {\r\n return this._centrifugalScale;\r\n }\r\n\r\n set centrifugalScale(scale: number) {\r\n this._centrifugalScale = Math.max(0, scale);\r\n }\r\n\r\n /**\r\n * Gets the Coriolis force scale\r\n */\r\n get coriolisScale(): number {\r\n return this._coriolisScale;\r\n }\r\n\r\n set coriolisScale(scale: number) {\r\n this._coriolisScale = Math.max(0, scale);\r\n }\r\n\r\n get solver(): 'verlet' | 'xpbd' {\r\n return this._solver;\r\n }\r\n\r\n set solver(type: 'verlet' | 'xpbd') {\r\n if (this._solver !== type) {\r\n this._solver = type;\r\n if (type === 'xpbd') {\r\n for (const chain of this._chains) {\r\n for (const c of chain.constraints) {\r\n c.lambda = 0;\r\n }\r\n }\r\n for (const c of this._interChainConstraints) {\r\n c.lambda = 0;\r\n }\r\n }\r\n }\r\n }\r\n}\r\n"],"names":["MultiChainSpringSystem","_chains","_interChainConstraints","_iterations","_gravity","_wind","_enableInertialForces","_centrifugalScale","_coriolisScale","_solver","options","iterations","gravity","clone","Vector3","wind","enableInertialForces","centrifugalScale","coriolisScale","solver","addChain","chain","push","length","addInterChainConstraint","constraint","createRadialConstraints","skipRows","connectDistance","compliance","i","offset","j","chainA","chainB","minLength","Math","min","particles","row","pA","pB","distance","position","maxDistance","chainAIndex","chainBIndex","particleAIndex","particleBIndex","restLength","stiffness","lambda","update","deltaTime","dt","p","lastFramePosition","set","updateFixedParticles","rotationCenter","angularVelocity","result","calculateGlobalRotation","center","omega","particle","fixed","velocity","sub","prevPosition","scaleBy","damping","acceleration","add","inertialAccel","calculateInertialAcceleration","positionDelta","scale","c","constraints","iter","solveConstraintXPBD","solveConstraint","solveInterChainConstraintXPBD","solveInterChainConstraint","node","worldPos","worldMatrix","m03","m13","m23","positionHistory","shift","fixedParticles","velocities","magnitudeSq","estimateRotationCenterFromHistory","sumOmega","count","r","v","rLengthSq","cross","currentVelocity","history","speed","magnitude","estimatedRadius","max","up","perpDir","normalize","p1","p2","floor","p3","calculateCircleCenter","mid12","mid23","dir12","dir23","normal","perp12","perp23","diff","det","x","y","abs","t","particleVelocity","omegaCrossR","centrifugalAccel","coriolisAccel","totalAccel","particleA","particleB","delta","currentLength","correction","wA","mass","wB","wSum","C","alphaTilde","deltaLambda","n","applyToNodes","weight","applyChainToNodes","nextParticle","currentBonePos","nextNode","nextBonePos","originalDir","currentBoneRotation","Quaternion","decompose","newDir","deltaRotation","IKUtils","fromToRotation","worldRotation","multiply","slerp","parent","parentWorldRotation","parentInvRotation","conjugate","localRotation","rotation","reset","chains","interChainConstraints","enabled","type"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"multi_chain_spring_system.js","sources":["../../../src/animation/spring/multi_chain_spring_system.ts"],"sourcesContent":["import type { Nullable } from '@zephyr3d/base';\r\nimport { Vector3, Quaternion } from '@zephyr3d/base';\r\nimport type { SpringChain } from './spring_chain';\r\nimport type { SpringConstraint } from './spring_constraint';\r\nimport { IKUtils } from '../ik/ik_utils';\r\n\r\n/**\r\n * Constraint between particles in different chains\r\n *\r\n * @public\r\n */\r\nexport interface InterChainConstraint {\r\n /** Index of the first chain */\r\n chainAIndex: number;\r\n /** Index of the second chain */\r\n chainBIndex: number;\r\n /** Index of particle in chain A */\r\n particleAIndex: number;\r\n /** Index of particle in chain B */\r\n particleBIndex: number;\r\n /** Desired distance between particles */\r\n restLength: number;\r\n /** Constraint strength [0-1], used by Verlet solver */\r\n stiffness: number;\r\n /**\r\n * XPBD compliance (inverse stiffness) in m/N.\r\n * Only used when solver is 'xpbd'.\r\n */\r\n compliance: number;\r\n /** XPBD Lagrange multiplier accumulator, reset each time step. */\r\n lambda: number;\r\n}\r\n\r\n/**\r\n * Options for creating a MultiChainSpringSystem\r\n *\r\n * @public\r\n */\r\nexport interface MultiChainSpringSystemOptions {\r\n /** Number of constraint solver iterations (default: 5) */\r\n iterations?: number;\r\n /** Gravity force vector (default: (0, -9.8, 0)) */\r\n gravity?: Vector3;\r\n /** Wind force vector (default: (0, 0, 0)) */\r\n wind?: Vector3;\r\n /** Enable inertial forces (centrifugal/Coriolis) when root rotates (default: true) */\r\n enableInertialForces?: boolean;\r\n /** Centrifugal force multiplier (default: 1.0) */\r\n centrifugalScale?: number;\r\n /** Coriolis force multiplier (default: 1.0) */\r\n coriolisScale?: number;\r\n /**\r\n * Constraint solver type (default: 'verlet').\r\n * - 'verlet': stiffness [0-1] controls per-iteration correction strength.\r\n * - 'xpbd': compliance (m/N) gives physically correct, iteration-independent results.\r\n */\r\n solver?: 'verlet' | 'xpbd';\r\n}\r\n\r\n/**\r\n * Physics engine for multiple spring chains with inter-chain constraints\r\n * Suitable for cloth, skirts, capes, and other multi-chain simulations\r\n *\r\n * @deprecated Use the new {@link JointDynamicsSystem} class instead.\r\n *\r\n * @public\r\n */\r\nexport class MultiChainSpringSystem {\r\n private _chains: SpringChain[];\r\n private _interChainConstraints: InterChainConstraint[];\r\n private _iterations: number;\r\n private _gravity: Vector3;\r\n private _wind: Vector3;\r\n private _enableInertialForces: boolean;\r\n private _centrifugalScale: number;\r\n private _coriolisScale: number;\r\n private _solver: 'verlet' | 'xpbd';\r\n\r\n constructor(options?: MultiChainSpringSystemOptions) {\r\n this._chains = [];\r\n this._interChainConstraints = [];\r\n this._iterations = options?.iterations ?? 5;\r\n this._gravity = options?.gravity?.clone() ?? new Vector3(0, -9.8, 0);\r\n this._wind = options?.wind?.clone() ?? new Vector3(0, 0, 0);\r\n this._enableInertialForces = options?.enableInertialForces ?? true;\r\n this._centrifugalScale = options?.centrifugalScale ?? 1.0;\r\n this._coriolisScale = options?.coriolisScale ?? 1.0;\r\n this._solver = options?.solver ?? 'verlet';\r\n }\r\n\r\n /**\r\n * Adds a spring chain to the system\r\n * @param chain - The chain to add\r\n * @returns The index of the added chain\r\n */\r\n addChain(chain: SpringChain): number {\r\n this._chains.push(chain);\r\n return this._chains.length - 1;\r\n }\r\n\r\n /**\r\n * Adds an inter-chain constraint\r\n * @param constraint - The constraint to add\r\n */\r\n addInterChainConstraint(constraint: InterChainConstraint): void {\r\n this._interChainConstraints.push(constraint);\r\n }\r\n\r\n /**\r\n * Creates radial constraints between adjacent chains\r\n * Useful for skirts, capes, and other radial multi-chain structures\r\n * @param options - Configuration options\r\n */\r\n createRadialConstraints(options: {\r\n /** Constraint stiffness [0-1], used by Verlet solver */\r\n stiffness: number;\r\n /** Maximum distance to create constraints (particles further apart are not connected) */\r\n maxDistance: number;\r\n /** Skip first N rows of particles (e.g., anchor points at waist) */\r\n skipRows?: number;\r\n /** Connect to next N chains (default: 1, only adjacent chains) */\r\n connectDistance?: number;\r\n /** XPBD compliance in m/N (default: 0 = rigid). Only used when solver is 'xpbd'. */\r\n compliance?: number;\r\n }): void {\r\n const skipRows = options.skipRows ?? 0;\r\n const connectDistance = options.connectDistance ?? 1;\r\n const compliance = options.compliance ?? 0;\r\n\r\n for (let i = 0; i < this._chains.length; i++) {\r\n for (let offset = 1; offset <= connectDistance; offset++) {\r\n const j = (i + offset) % this._chains.length;\r\n const chainA = this._chains[i];\r\n const chainB = this._chains[j];\r\n\r\n const minLength = Math.min(chainA.particles.length, chainB.particles.length);\r\n\r\n for (let row = skipRows; row < minLength; row++) {\r\n const pA = chainA.particles[row];\r\n const pB = chainB.particles[row];\r\n const distance = Vector3.distance(pA.position, pB.position);\r\n\r\n if (distance <= options.maxDistance) {\r\n this.addInterChainConstraint({\r\n chainAIndex: i,\r\n chainBIndex: j,\r\n particleAIndex: row,\r\n particleBIndex: row,\r\n restLength: distance,\r\n stiffness: options.stiffness,\r\n compliance,\r\n lambda: 0\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Updates the physics simulation for all chains\r\n * @param deltaTime - Time step in seconds\r\n */\r\n update(deltaTime: number): void {\r\n const dt = Math.min(deltaTime, 0.033);\r\n\r\n // Save all particle positions before updating\r\n if (this._enableInertialForces) {\r\n for (const chain of this._chains) {\r\n for (const p of chain.particles) {\r\n p.lastFramePosition.set(p.position);\r\n }\r\n }\r\n }\r\n\r\n this.updateFixedParticles();\r\n\r\n // Calculate global rotation parameters\r\n let rotationCenter: Nullable<Vector3> = null;\r\n let angularVelocity: Nullable<Vector3> = null;\r\n\r\n if (this._enableInertialForces && dt > 0.0001) {\r\n const result = this.calculateGlobalRotation(dt);\r\n rotationCenter = result.center;\r\n angularVelocity = result.omega;\r\n }\r\n\r\n for (const chain of this._chains) {\r\n for (const particle of chain.particles) {\r\n if (particle.fixed) {\r\n continue;\r\n }\r\n\r\n const velocity = Vector3.sub(particle.position, particle.prevPosition, new Vector3());\r\n velocity.scaleBy(particle.damping);\r\n\r\n const acceleration = Vector3.add(this._gravity, this._wind, new Vector3());\r\n\r\n // Apply inertial forces\r\n if (this._enableInertialForces && rotationCenter && angularVelocity) {\r\n const inertialAccel = this.calculateInertialAcceleration(\r\n particle,\r\n rotationCenter,\r\n angularVelocity,\r\n velocity,\r\n this._centrifugalScale,\r\n this._coriolisScale\r\n );\r\n Vector3.add(acceleration, inertialAccel, acceleration);\r\n }\r\n\r\n const positionDelta = Vector3.scale(acceleration, dt * dt, new Vector3());\r\n Vector3.add(velocity, positionDelta, velocity);\r\n\r\n particle.prevPosition.set(particle.position);\r\n Vector3.add(particle.position, velocity, particle.position);\r\n }\r\n }\r\n\r\n if (this._solver === 'xpbd') {\r\n for (const chain of this._chains) {\r\n for (const c of chain.constraints) {\r\n c.lambda = 0;\r\n }\r\n }\r\n for (const c of this._interChainConstraints) {\r\n c.lambda = 0;\r\n }\r\n }\r\n for (let iter = 0; iter < this._iterations; iter++) {\r\n for (const chain of this._chains) {\r\n for (const constraint of chain.constraints) {\r\n if (this._solver === 'xpbd') {\r\n this.solveConstraintXPBD(chain, constraint, dt);\r\n } else {\r\n this.solveConstraint(chain, constraint);\r\n }\r\n }\r\n }\r\n\r\n for (const constraint of this._interChainConstraints) {\r\n if (this._solver === 'xpbd') {\r\n this.solveInterChainConstraintXPBD(constraint, dt);\r\n } else {\r\n this.solveInterChainConstraint(constraint);\r\n }\r\n }\r\n }\r\n }\r\n\r\n private updateFixedParticles(): void {\r\n for (const chain of this._chains) {\r\n for (const particle of chain.particles) {\r\n if (particle.fixed && particle.node) {\r\n const worldPos = new Vector3(\r\n particle.node.worldMatrix.m03,\r\n particle.node.worldMatrix.m13,\r\n particle.node.worldMatrix.m23\r\n );\r\n particle.position.set(worldPos);\r\n particle.prevPosition.set(worldPos);\r\n\r\n // Maintain position history\r\n if (this._enableInertialForces) {\r\n if (!particle.positionHistory) {\r\n particle.positionHistory = [];\r\n }\r\n particle.positionHistory.push(worldPos.clone());\r\n if (particle.positionHistory.length > 5) {\r\n particle.positionHistory.shift();\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n private calculateGlobalRotation(dt: number): { center: Vector3; omega: Vector3 } {\r\n const fixedParticles: any[] = [];\r\n const velocities: Vector3[] = [];\r\n\r\n for (const chain of this._chains) {\r\n for (const p of chain.particles) {\r\n if (!p.fixed) {\r\n continue;\r\n }\r\n\r\n const velocity = Vector3.sub(p.position, p.lastFramePosition, new Vector3());\r\n velocity.scaleBy(1.0 / dt);\r\n\r\n if (velocity.magnitudeSq > 0.001) {\r\n fixedParticles.push(p);\r\n velocities.push(velocity);\r\n }\r\n }\r\n }\r\n\r\n if (fixedParticles.length === 0) {\r\n return { center: new Vector3(0, 0, 0), omega: new Vector3(0, 0, 0) };\r\n }\r\n\r\n // Estimate rotation center\r\n let center: Vector3;\r\n\r\n if (fixedParticles.length === 1) {\r\n center = this.estimateRotationCenterFromHistory(fixedParticles[0], velocities[0]);\r\n } else {\r\n center = new Vector3(0, 0, 0);\r\n for (const p of fixedParticles) {\r\n Vector3.add(center, p.position, center);\r\n }\r\n center.scaleBy(1.0 / fixedParticles.length);\r\n }\r\n\r\n // Estimate angular velocity\r\n let sumOmega = new Vector3(0, 0, 0);\r\n let count = 0;\r\n\r\n for (let i = 0; i < fixedParticles.length; i++) {\r\n const r = Vector3.sub(fixedParticles[i].position, center, new Vector3());\r\n const v = velocities[i];\r\n const rLengthSq = r.magnitudeSq;\r\n\r\n if (rLengthSq > 0.0001) {\r\n const omega = Vector3.cross(r, v, new Vector3());\r\n omega.scaleBy(1.0 / rLengthSq);\r\n Vector3.add(sumOmega, omega, sumOmega);\r\n count++;\r\n }\r\n }\r\n\r\n if (count > 0) {\r\n sumOmega.scaleBy(1.0 / count);\r\n }\r\n\r\n return { center, omega: sumOmega };\r\n }\r\n\r\n private estimateRotationCenterFromHistory(particle: any, currentVelocity: Vector3): Vector3 {\r\n const history = particle.positionHistory;\r\n if (!history || history.length < 3) {\r\n const speed = currentVelocity.magnitude;\r\n if (speed < 0.001) {\r\n return particle.position.clone();\r\n }\r\n\r\n const estimatedRadius = Math.max(0.5, speed * 0.5);\r\n const up = new Vector3(0, 1, 0);\r\n const perpDir = Vector3.cross(currentVelocity, up, new Vector3());\r\n\r\n if (perpDir.magnitudeSq < 0.0001) {\r\n perpDir.set(new Vector3(1, 0, 0));\r\n } else {\r\n Vector3.normalize(perpDir, perpDir);\r\n }\r\n\r\n const center = Vector3.add(\r\n particle.position,\r\n Vector3.scale(perpDir, estimatedRadius, new Vector3()),\r\n new Vector3()\r\n );\r\n return center;\r\n }\r\n\r\n const p1 = history[0];\r\n const p2 = history[Math.floor(history.length / 2)];\r\n const p3 = history[history.length - 1];\r\n\r\n const center = this.calculateCircleCenter(p1, p2, p3);\r\n return center;\r\n }\r\n\r\n private calculateCircleCenter(p1: Vector3, p2: Vector3, p3: Vector3): Vector3 {\r\n const mid12 = Vector3.scale(Vector3.add(p1, p2, new Vector3()), 0.5, new Vector3());\r\n const mid23 = Vector3.scale(Vector3.add(p2, p3, new Vector3()), 0.5, new Vector3());\r\n\r\n const dir12 = Vector3.sub(p2, p1, new Vector3());\r\n const dir23 = Vector3.sub(p3, p2, new Vector3());\r\n\r\n const normal = Vector3.cross(dir12, dir23, new Vector3());\r\n\r\n if (normal.magnitudeSq < 0.0001) {\r\n return Vector3.scale(\r\n Vector3.add(Vector3.add(p1, p2, new Vector3()), p3, new Vector3()),\r\n 1.0 / 3.0,\r\n new Vector3()\r\n );\r\n }\r\n\r\n Vector3.normalize(normal, normal);\r\n\r\n const perp12 = Vector3.cross(dir12, normal, new Vector3());\r\n Vector3.normalize(perp12, perp12);\r\n\r\n const perp23 = Vector3.cross(dir23, normal, new Vector3());\r\n Vector3.normalize(perp23, perp23);\r\n\r\n const diff = Vector3.sub(mid23, mid12, new Vector3());\r\n\r\n const det = perp12.x * perp23.y - perp12.y * perp23.x;\r\n\r\n if (Math.abs(det) > 0.0001) {\r\n const t = (diff.x * perp23.y - diff.y * perp23.x) / det;\r\n const center = Vector3.add(mid12, Vector3.scale(perp12, t, new Vector3()), new Vector3());\r\n return center;\r\n }\r\n\r\n return Vector3.scale(\r\n Vector3.add(Vector3.add(p1, p2, new Vector3()), p3, new Vector3()),\r\n 1.0 / 3.0,\r\n new Vector3()\r\n );\r\n }\r\n\r\n private calculateInertialAcceleration(\r\n particle: any,\r\n rotationCenter: Vector3,\r\n angularVelocity: Vector3,\r\n particleVelocity: Vector3,\r\n centrifugalScale: number,\r\n coriolisScale: number\r\n ): Vector3 {\r\n const r = Vector3.sub(particle.position, rotationCenter, new Vector3());\r\n\r\n const omegaCrossR = Vector3.cross(angularVelocity, r, new Vector3());\r\n const centrifugalAccel = Vector3.cross(angularVelocity, omegaCrossR, new Vector3());\r\n centrifugalAccel.scaleBy(centrifugalScale);\r\n\r\n const coriolisAccel = Vector3.cross(angularVelocity, particleVelocity, new Vector3());\r\n coriolisAccel.scaleBy(-2.0 * coriolisScale);\r\n\r\n const totalAccel = Vector3.add(centrifugalAccel, coriolisAccel, new Vector3());\r\n return totalAccel;\r\n }\r\n\r\n private solveConstraint(chain: SpringChain, constraint: SpringConstraint): void {\r\n const pA = chain.particles[constraint.particleA];\r\n const pB = chain.particles[constraint.particleB];\r\n\r\n const delta = Vector3.sub(pB.position, pA.position, new Vector3());\r\n const currentLength = delta.magnitude;\r\n\r\n if (currentLength < 0.0001) {\r\n return;\r\n }\r\n\r\n const diff = (currentLength - constraint.restLength) / currentLength;\r\n const correction = Vector3.scale(delta, diff * constraint.stiffness * 0.5, new Vector3());\r\n\r\n if (!pA.fixed) {\r\n Vector3.add(pA.position, correction, pA.position);\r\n }\r\n if (!pB.fixed) {\r\n Vector3.sub(pB.position, correction, pB.position);\r\n }\r\n }\r\n\r\n private solveInterChainConstraint(constraint: InterChainConstraint): void {\r\n const chainA = this._chains[constraint.chainAIndex];\r\n const chainB = this._chains[constraint.chainBIndex];\r\n const pA = chainA.particles[constraint.particleAIndex];\r\n const pB = chainB.particles[constraint.particleBIndex];\r\n\r\n const delta = Vector3.sub(pB.position, pA.position, new Vector3());\r\n const currentLength = delta.magnitude;\r\n\r\n if (currentLength < 0.0001) {\r\n return;\r\n }\r\n\r\n const diff = (currentLength - constraint.restLength) / currentLength;\r\n const correction = Vector3.scale(delta, diff * constraint.stiffness * 0.5, new Vector3());\r\n\r\n if (!pA.fixed) {\r\n Vector3.add(pA.position, correction, pA.position);\r\n }\r\n if (!pB.fixed) {\r\n Vector3.sub(pB.position, correction, pB.position);\r\n }\r\n }\r\n\r\n private solveConstraintXPBD(chain: SpringChain, constraint: SpringConstraint, dt: number): void {\r\n const pA = chain.particles[constraint.particleA];\r\n const pB = chain.particles[constraint.particleB];\r\n\r\n const wA = pA.fixed ? 0 : 1.0 / pA.mass;\r\n const wB = pB.fixed ? 0 : 1.0 / pB.mass;\r\n const wSum = wA + wB;\r\n if (wSum < 1e-10) {\r\n return;\r\n }\r\n\r\n const delta = Vector3.sub(pB.position, pA.position, new Vector3());\r\n const currentLength = delta.magnitude;\r\n if (currentLength < 0.0001) {\r\n return;\r\n }\r\n\r\n const C = currentLength - constraint.restLength;\r\n const alphaTilde = constraint.compliance / (dt * dt);\r\n const deltaLambda = (-C - alphaTilde * constraint.lambda) / (wSum + alphaTilde);\r\n constraint.lambda += deltaLambda;\r\n\r\n const n = Vector3.scale(delta, 1.0 / currentLength, new Vector3());\r\n if (!pA.fixed) {\r\n Vector3.add(pA.position, Vector3.scale(n, -wA * deltaLambda, new Vector3()), pA.position);\r\n }\r\n if (!pB.fixed) {\r\n Vector3.add(pB.position, Vector3.scale(n, wB * deltaLambda, new Vector3()), pB.position);\r\n }\r\n }\r\n\r\n private solveInterChainConstraintXPBD(constraint: InterChainConstraint, dt: number): void {\r\n const chainA = this._chains[constraint.chainAIndex];\r\n const chainB = this._chains[constraint.chainBIndex];\r\n const pA = chainA.particles[constraint.particleAIndex];\r\n const pB = chainB.particles[constraint.particleBIndex];\r\n\r\n const wA = pA.fixed ? 0 : 1.0 / pA.mass;\r\n const wB = pB.fixed ? 0 : 1.0 / pB.mass;\r\n const wSum = wA + wB;\r\n if (wSum < 1e-10) {\r\n return;\r\n }\r\n\r\n const delta = Vector3.sub(pB.position, pA.position, new Vector3());\r\n const currentLength = delta.magnitude;\r\n if (currentLength < 0.0001) {\r\n return;\r\n }\r\n\r\n const C = currentLength - constraint.restLength;\r\n const alphaTilde = constraint.compliance / (dt * dt);\r\n const deltaLambda = (-C - alphaTilde * constraint.lambda) / (wSum + alphaTilde);\r\n constraint.lambda += deltaLambda;\r\n\r\n const n = Vector3.scale(delta, 1.0 / currentLength, new Vector3());\r\n if (!pA.fixed) {\r\n Vector3.add(pA.position, Vector3.scale(n, -wA * deltaLambda, new Vector3()), pA.position);\r\n }\r\n if (!pB.fixed) {\r\n Vector3.add(pB.position, Vector3.scale(n, wB * deltaLambda, new Vector3()), pB.position);\r\n }\r\n }\r\n\r\n /**\r\n * Applies simulation results to scene nodes\r\n * @param weight - Blend weight [0-1] (default: 1.0)\r\n */\r\n applyToNodes(weight: number = 1.0): void {\r\n for (const chain of this._chains) {\r\n this.applyChainToNodes(chain, weight);\r\n }\r\n }\r\n\r\n private applyChainToNodes(chain: SpringChain, weight: number): void {\r\n for (let i = 0; i < chain.particles.length - 1; i++) {\r\n const particle = chain.particles[i];\r\n const nextParticle = chain.particles[i + 1];\r\n\r\n if (!particle.node) {\r\n continue;\r\n }\r\n\r\n // Get current bone direction from node's world matrix (before physics)\r\n const currentBonePos = new Vector3(\r\n particle.node.worldMatrix.m03,\r\n particle.node.worldMatrix.m13,\r\n particle.node.worldMatrix.m23\r\n );\r\n\r\n const nextNode = nextParticle.node;\r\n if (!nextNode) {\r\n continue;\r\n }\r\n\r\n const nextBonePos = new Vector3(\r\n nextNode.worldMatrix.m03,\r\n nextNode.worldMatrix.m13,\r\n nextNode.worldMatrix.m23\r\n );\r\n const originalDir = Vector3.sub(nextBonePos, currentBonePos, new Vector3());\r\n\r\n // Get current bone rotation from node's world matrix\r\n const currentBoneRotation = new Quaternion();\r\n particle.node.worldMatrix.decompose(null, currentBoneRotation, null);\r\n\r\n // Calculate new direction from physics simulation\r\n const newDir = Vector3.sub(nextParticle.position, particle.position, new Vector3());\r\n\r\n const deltaRotation = new Quaternion();\r\n IKUtils.fromToRotation(originalDir, newDir, deltaRotation);\r\n\r\n let worldRotation = Quaternion.multiply(deltaRotation, currentBoneRotation, new Quaternion());\r\n\r\n if (weight < 1) {\r\n Quaternion.slerp(currentBoneRotation, worldRotation, weight, worldRotation);\r\n }\r\n\r\n const parent = particle.node.parent;\r\n if (parent) {\r\n const parentWorldRotation = new Quaternion();\r\n parent.worldMatrix.decompose(null, parentWorldRotation, null);\r\n const parentInvRotation = Quaternion.conjugate(parentWorldRotation, new Quaternion());\r\n const localRotation = Quaternion.multiply(parentInvRotation, worldRotation, new Quaternion());\r\n particle.node.rotation = localRotation;\r\n } else {\r\n particle.node.rotation = worldRotation;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Resets the simulation to initial state\r\n */\r\n reset(): void {\r\n for (const chain of this._chains) {\r\n chain.reset();\r\n }\r\n }\r\n\r\n /**\r\n * Gets the spring chains\r\n */\r\n get chains(): SpringChain[] {\r\n return this._chains;\r\n }\r\n\r\n /**\r\n * Gets the inter-chain constraints\r\n */\r\n get interChainConstraints(): InterChainConstraint[] {\r\n return this._interChainConstraints;\r\n }\r\n\r\n /**\r\n * Gets the current gravity\r\n */\r\n get gravity(): Vector3 {\r\n return this._gravity;\r\n }\r\n\r\n set gravity(gravity: Vector3) {\r\n this._gravity.set(gravity);\r\n }\r\n\r\n /**\r\n * Gets the current wind\r\n */\r\n get wind(): Vector3 {\r\n return this._wind;\r\n }\r\n\r\n set wind(wind: Vector3) {\r\n this._wind.set(wind);\r\n }\r\n\r\n /**\r\n * Gets the number of iterations\r\n */\r\n get iterations(): number {\r\n return this._iterations;\r\n }\r\n\r\n set iterations(count: number) {\r\n this._iterations = Math.max(1, count);\r\n }\r\n\r\n /**\r\n * Gets whether inertial forces are enabled\r\n */\r\n get enableInertialForces(): boolean {\r\n return this._enableInertialForces;\r\n }\r\n\r\n set enableInertialForces(enabled: boolean) {\r\n this._enableInertialForces = enabled;\r\n }\r\n\r\n /**\r\n * Gets the centrifugal force scale\r\n */\r\n get centrifugalScale(): number {\r\n return this._centrifugalScale;\r\n }\r\n\r\n set centrifugalScale(scale: number) {\r\n this._centrifugalScale = Math.max(0, scale);\r\n }\r\n\r\n /**\r\n * Gets the Coriolis force scale\r\n */\r\n get coriolisScale(): number {\r\n return this._coriolisScale;\r\n }\r\n\r\n set coriolisScale(scale: number) {\r\n this._coriolisScale = Math.max(0, scale);\r\n }\r\n\r\n get solver(): 'verlet' | 'xpbd' {\r\n return this._solver;\r\n }\r\n\r\n set solver(type: 'verlet' | 'xpbd') {\r\n if (this._solver !== type) {\r\n this._solver = type;\r\n if (type === 'xpbd') {\r\n for (const chain of this._chains) {\r\n for (const c of chain.constraints) {\r\n c.lambda = 0;\r\n }\r\n }\r\n for (const c of this._interChainConstraints) {\r\n c.lambda = 0;\r\n }\r\n }\r\n }\r\n }\r\n}\r\n"],"names":["MultiChainSpringSystem","_chains","_interChainConstraints","_iterations","_gravity","_wind","_enableInertialForces","_centrifugalScale","_coriolisScale","_solver","options","iterations","gravity","clone","Vector3","wind","enableInertialForces","centrifugalScale","coriolisScale","solver","addChain","chain","push","length","addInterChainConstraint","constraint","createRadialConstraints","skipRows","connectDistance","compliance","i","offset","j","chainA","chainB","minLength","Math","min","particles","row","pA","pB","distance","position","maxDistance","chainAIndex","chainBIndex","particleAIndex","particleBIndex","restLength","stiffness","lambda","update","deltaTime","dt","p","lastFramePosition","set","updateFixedParticles","rotationCenter","angularVelocity","result","calculateGlobalRotation","center","omega","particle","fixed","velocity","sub","prevPosition","scaleBy","damping","acceleration","add","inertialAccel","calculateInertialAcceleration","positionDelta","scale","c","constraints","iter","solveConstraintXPBD","solveConstraint","solveInterChainConstraintXPBD","solveInterChainConstraint","node","worldPos","worldMatrix","m03","m13","m23","positionHistory","shift","fixedParticles","velocities","magnitudeSq","estimateRotationCenterFromHistory","sumOmega","count","r","v","rLengthSq","cross","currentVelocity","history","speed","magnitude","estimatedRadius","max","up","perpDir","normalize","p1","p2","floor","p3","calculateCircleCenter","mid12","mid23","dir12","dir23","normal","perp12","perp23","diff","det","x","y","abs","t","particleVelocity","omegaCrossR","centrifugalAccel","coriolisAccel","totalAccel","particleA","particleB","delta","currentLength","correction","wA","mass","wB","wSum","C","alphaTilde","deltaLambda","n","applyToNodes","weight","applyChainToNodes","nextParticle","currentBonePos","nextNode","nextBonePos","originalDir","currentBoneRotation","Quaternion","decompose","newDir","deltaRotation","IKUtils","fromToRotation","worldRotation","multiply","slerp","parent","parentWorldRotation","parentInvRotation","conjugate","localRotation","rotation","reset","chains","interChainConstraints","enabled","type"],"mappings":"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"}
|
|
@@ -32,8 +32,9 @@ import { createSpringConstraint } from './spring_constraint.js';
|
|
|
32
32
|
if (current === endNode) {
|
|
33
33
|
break;
|
|
34
34
|
}
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
const children = current.children;
|
|
36
|
+
if (children.length > 0) {
|
|
37
|
+
current = children[0];
|
|
37
38
|
} else {
|
|
38
39
|
break;
|
|
39
40
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spring_chain.js","sources":["../../../src/animation/spring/spring_chain.ts"],"sourcesContent":["import { Vector3, Quaternion } from '@zephyr3d/base';\r\nimport type { SceneNode } from '../../scene/scene_node';\r\nimport type { SpringParticle } from './spring_particle';\r\nimport { createSpringParticle } from './spring_particle';\r\nimport type { SpringConstraint } from './spring_constraint';\r\nimport { createSpringConstraint } from './spring_constraint';\r\n\r\n/**\r\n * Manages a chain of spring particles and constraints\r\n *\r\n * @public\r\n */\r\nexport class SpringChain {\r\n /** Array of particles in the chain */\r\n particles: SpringParticle[];\r\n /** Array of constraints between particles */\r\n constraints: SpringConstraint[];\r\n\r\n constructor() {\r\n this.particles = [];\r\n this.constraints = [];\r\n }\r\n\r\n /**\r\n * Creates a spring chain from a bone hierarchy\r\n * @param startNode - Root node of the bone chain\r\n * @param endNode - End node of the bone chain (optional, if null uses all descendants)\r\n * @param options - Additional options\r\n * @returns A new SpringChain instance\r\n */\r\n static fromBoneChain(\r\n startNode: SceneNode,\r\n endNode: SceneNode | null = null,\r\n options?: {\r\n mass?: number;\r\n damping?: number;\r\n stiffness?: number;\r\n }\r\n ): SpringChain {\r\n const chain = new SpringChain();\r\n const mass = options?.mass ?? 1.0;\r\n const damping = options?.damping ?? 0.95;\r\n const stiffness = options?.stiffness ?? 0.8;\r\n\r\n // Collect nodes from startNode to endNode\r\n const nodes: SceneNode[] = [];\r\n let current: SceneNode | null = startNode;\r\n\r\n while (current) {\r\n nodes.push(current);\r\n if (current === endNode) {\r\n break;\r\n }\r\n\r\n
|
|
1
|
+
{"version":3,"file":"spring_chain.js","sources":["../../../src/animation/spring/spring_chain.ts"],"sourcesContent":["import { Vector3, Quaternion } from '@zephyr3d/base';\r\nimport type { SceneNode } from '../../scene/scene_node';\r\nimport type { SpringParticle } from './spring_particle';\r\nimport { createSpringParticle } from './spring_particle';\r\nimport type { SpringConstraint } from './spring_constraint';\r\nimport { createSpringConstraint } from './spring_constraint';\r\n\r\n/**\r\n * Manages a chain of spring particles and constraints\r\n *\r\n * @public\r\n */\r\nexport class SpringChain {\r\n /** Array of particles in the chain */\r\n particles: SpringParticle[];\r\n /** Array of constraints between particles */\r\n constraints: SpringConstraint[];\r\n\r\n constructor() {\r\n this.particles = [];\r\n this.constraints = [];\r\n }\r\n\r\n /**\r\n * Creates a spring chain from a bone hierarchy\r\n * @param startNode - Root node of the bone chain\r\n * @param endNode - End node of the bone chain (optional, if null uses all descendants)\r\n * @param options - Additional options\r\n * @returns A new SpringChain instance\r\n */\r\n static fromBoneChain(\r\n startNode: SceneNode,\r\n endNode: SceneNode | null = null,\r\n options?: {\r\n mass?: number;\r\n damping?: number;\r\n stiffness?: number;\r\n }\r\n ): SpringChain {\r\n const chain = new SpringChain();\r\n const mass = options?.mass ?? 1.0;\r\n const damping = options?.damping ?? 0.95;\r\n const stiffness = options?.stiffness ?? 0.8;\r\n\r\n // Collect nodes from startNode to endNode\r\n const nodes: SceneNode[] = [];\r\n let current: SceneNode | null = startNode;\r\n\r\n while (current) {\r\n nodes.push(current);\r\n if (current === endNode) {\r\n break;\r\n }\r\n\r\n const children: SceneNode[] = current.children;\r\n if (children.length > 0) {\r\n current = children[0];\r\n } else {\r\n break;\r\n }\r\n }\r\n\r\n // Create particles for each bone\r\n for (let i = 0; i < nodes.length; i++) {\r\n const node = nodes[i];\r\n const worldPos = new Vector3(node.worldMatrix.m03, node.worldMatrix.m13, node.worldMatrix.m23);\r\n\r\n // Get the original world rotation\r\n const originalRotation = new Quaternion();\r\n node.worldMatrix.decompose(null, originalRotation, null);\r\n\r\n const particle = createSpringParticle(worldPos, {\r\n mass,\r\n damping,\r\n fixed: i === 0, // First particle is fixed (anchor)\r\n node,\r\n originalRotation\r\n });\r\n\r\n const particleIndex = chain.addParticle(particle);\r\n\r\n // Create constraint with previous particle\r\n if (i > 0) {\r\n const prevIndex = particleIndex - 1;\r\n const prevParticle = chain.particles[prevIndex];\r\n const restLength = Vector3.distance(particle.position, prevParticle.position);\r\n\r\n chain.addConstraint(createSpringConstraint(prevIndex, particleIndex, restLength, stiffness));\r\n }\r\n }\r\n\r\n return chain;\r\n }\r\n\r\n /**\r\n * Adds a particle to the chain\r\n * @param particle - The particle to add\r\n * @returns The index of the added particle\r\n */\r\n addParticle(particle: SpringParticle): number {\r\n this.particles.push(particle);\r\n return this.particles.length - 1;\r\n }\r\n\r\n /**\r\n * Adds a constraint to the chain\r\n * @param constraint - The constraint to add\r\n */\r\n addConstraint(constraint: SpringConstraint): void {\r\n this.constraints.push(constraint);\r\n }\r\n\r\n /**\r\n * Adds cross constraints between particles for cloth-like behavior\r\n * @param stiffness - Stiffness of the cross constraints\r\n * @param skipDistance - Distance between particles to connect (default: 2)\r\n */\r\n addCrossConstraints(stiffness: number = 0.6, skipDistance: number = 2): void {\r\n for (let i = 0; i < this.particles.length - skipDistance; i++) {\r\n const pA = this.particles[i];\r\n const pB = this.particles[i + skipDistance];\r\n const restLength = Vector3.distance(pA.position, pB.position);\r\n\r\n this.addConstraint(createSpringConstraint(i, i + skipDistance, restLength, stiffness));\r\n }\r\n }\r\n\r\n /**\r\n * Resets all particles to their original positions\r\n */\r\n reset(): void {\r\n for (const particle of this.particles) {\r\n particle.position.set(particle.originalPosition);\r\n particle.prevPosition.set(particle.originalPosition);\r\n }\r\n }\r\n}\r\n"],"names":["SpringChain","particles","constraints","fromBoneChain","startNode","endNode","options","chain","mass","damping","stiffness","nodes","current","push","children","length","i","node","worldPos","Vector3","worldMatrix","m03","m13","m23","originalRotation","Quaternion","decompose","particle","createSpringParticle","fixed","particleIndex","addParticle","prevIndex","prevParticle","restLength","distance","position","addConstraint","createSpringConstraint","constraint","addCrossConstraints","skipDistance","pA","pB","reset","set","originalPosition","prevPosition"],"mappings":"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"}
|
|
@@ -11,11 +11,13 @@ import { Vector3 } from '@zephyr3d/base';
|
|
|
11
11
|
if (node) {
|
|
12
12
|
// If node is provided, treat centerOrOffset as local offset
|
|
13
13
|
const worldMatrix = node.worldMatrix;
|
|
14
|
-
const worldCenter =
|
|
14
|
+
const worldCenter = worldMatrix.transformPointAffine(centerOrOffset, new Vector3());
|
|
15
15
|
return {
|
|
16
16
|
type: 'sphere',
|
|
17
17
|
center: worldCenter,
|
|
18
18
|
radius,
|
|
19
|
+
localRadius: radius,
|
|
20
|
+
localRadiusScaleRef: getUniformScale(worldMatrix),
|
|
19
21
|
node,
|
|
20
22
|
enabled: true,
|
|
21
23
|
localOffset: centerOrOffset.clone()
|
|
@@ -43,13 +45,15 @@ import { Vector3 } from '@zephyr3d/base';
|
|
|
43
45
|
if (node) {
|
|
44
46
|
// If node is provided, treat as local offsets
|
|
45
47
|
const worldMatrix = node.worldMatrix;
|
|
46
|
-
const worldStart =
|
|
47
|
-
const worldEnd =
|
|
48
|
+
const worldStart = worldMatrix.transformPointAffine(startOrOffset, new Vector3());
|
|
49
|
+
const worldEnd = worldMatrix.transformPointAffine(endOrOffset, new Vector3());
|
|
48
50
|
return {
|
|
49
51
|
type: 'capsule',
|
|
50
52
|
start: worldStart,
|
|
51
53
|
end: worldEnd,
|
|
52
54
|
radius,
|
|
55
|
+
localRadius: radius,
|
|
56
|
+
localRadiusScaleRef: getPerpendicularScale(worldMatrix, Vector3.sub(endOrOffset, startOrOffset, new Vector3())),
|
|
53
57
|
node,
|
|
54
58
|
enabled: true,
|
|
55
59
|
localStartOffset: startOrOffset.clone(),
|
|
@@ -80,7 +84,7 @@ import { Vector3 } from '@zephyr3d/base';
|
|
|
80
84
|
if (node) {
|
|
81
85
|
// If node is provided, treat as local offset
|
|
82
86
|
const worldMatrix = node.worldMatrix;
|
|
83
|
-
const worldPoint =
|
|
87
|
+
const worldPoint = worldMatrix.transformPointAffine(pointOrOffset, new Vector3());
|
|
84
88
|
return {
|
|
85
89
|
type: 'plane',
|
|
86
90
|
point: worldPoint,
|
|
@@ -196,6 +200,11 @@ import { Vector3 } from '@zephyr3d/base';
|
|
|
196
200
|
case 'sphere':
|
|
197
201
|
{
|
|
198
202
|
const sphere = collider;
|
|
203
|
+
if (sphere.localRadius !== undefined) {
|
|
204
|
+
const currentScale = getUniformScale(worldMatrix);
|
|
205
|
+
const refScale = Math.max(1e-6, sphere.localRadiusScaleRef ?? 1);
|
|
206
|
+
sphere.radius = sphere.localRadius * (currentScale / refScale);
|
|
207
|
+
}
|
|
199
208
|
if (sphere.localOffset) {
|
|
200
209
|
// Transform local offset to world space
|
|
201
210
|
worldMatrix.transformPointAffine(sphere.localOffset, sphere.center);
|
|
@@ -210,6 +219,12 @@ import { Vector3 } from '@zephyr3d/base';
|
|
|
210
219
|
case 'capsule':
|
|
211
220
|
{
|
|
212
221
|
const capsule = collider;
|
|
222
|
+
if (capsule.localRadius !== undefined) {
|
|
223
|
+
const axisLocal = capsule.localStartOffset && capsule.localEndOffset ? Vector3.sub(capsule.localEndOffset, capsule.localStartOffset, new Vector3()) : Vector3.axisPY();
|
|
224
|
+
const currentScale = getPerpendicularScale(worldMatrix, axisLocal);
|
|
225
|
+
const refScale = Math.max(1e-6, capsule.localRadiusScaleRef ?? 1);
|
|
226
|
+
capsule.radius = capsule.localRadius * (currentScale / refScale);
|
|
227
|
+
}
|
|
213
228
|
if (capsule.localStartOffset && capsule.localEndOffset) {
|
|
214
229
|
// Transform local offsets to world space
|
|
215
230
|
worldMatrix.transformPointAffine(capsule.localStartOffset, capsule.start);
|
|
@@ -236,12 +251,27 @@ import { Vector3 } from '@zephyr3d/base';
|
|
|
236
251
|
}
|
|
237
252
|
if (plane.localNormal) {
|
|
238
253
|
// Transform local normal to world space (rotation only)
|
|
239
|
-
worldMatrix.transformVectorAffine(plane.localNormal, plane.normal).inplaceNormalize;
|
|
254
|
+
worldMatrix.transformVectorAffine(plane.localNormal, plane.normal).inplaceNormalize();
|
|
240
255
|
}
|
|
241
256
|
break;
|
|
242
257
|
}
|
|
243
258
|
}
|
|
244
259
|
}
|
|
260
|
+
function getUniformScale(worldMatrix) {
|
|
261
|
+
const sx = worldMatrix.transformVectorAffine(Vector3.axisPX(), new Vector3()).magnitude;
|
|
262
|
+
const sy = worldMatrix.transformVectorAffine(Vector3.axisPY(), new Vector3()).magnitude;
|
|
263
|
+
const sz = worldMatrix.transformVectorAffine(Vector3.axisPZ(), new Vector3()).magnitude;
|
|
264
|
+
return Math.max(1e-6, (sx + sy + sz) / 3);
|
|
265
|
+
}
|
|
266
|
+
function getPerpendicularScale(worldMatrix, axisLocal) {
|
|
267
|
+
const axis = axisLocal.magnitudeSq > 1e-8 ? axisLocal.clone().inplaceNormalize() : Vector3.axisPY();
|
|
268
|
+
const helper = Math.abs(axis.y) < 0.99 ? Vector3.axisPY() : Vector3.axisPX();
|
|
269
|
+
const u = Vector3.cross(axis, helper, new Vector3()).inplaceNormalize();
|
|
270
|
+
const v = Vector3.cross(axis, u, new Vector3()).inplaceNormalize();
|
|
271
|
+
const su = worldMatrix.transformVectorAffine(u, new Vector3()).magnitude;
|
|
272
|
+
const sv = worldMatrix.transformVectorAffine(v, new Vector3()).magnitude;
|
|
273
|
+
return Math.max(1e-6, (su + sv) * 0.5);
|
|
274
|
+
}
|
|
245
275
|
|
|
246
276
|
export { createCapsuleCollider, createPlaneCollider, createSphereCollider, resolveCapsuleCollision, resolvePlaneCollision, resolveSphereCollision, updateColliderFromNode };
|
|
247
277
|
//# sourceMappingURL=spring_collider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spring_collider.js","sources":["../../../src/animation/spring/spring_collider.ts"],"sourcesContent":["import type { Nullable } from '@zephyr3d/base';\r\nimport { Vector3 } from '@zephyr3d/base';\r\nimport type { SceneNode } from '../../scene/scene_node';\r\n\r\n/**\r\n * Base interface for spring collision shapes\r\n *\r\n * @public\r\n */\r\nexport interface SpringCollider {\r\n /** Type of collider */\r\n type: 'sphere' | 'capsule' | 'plane';\r\n /** Associated scene node (optional, for dynamic colliders) */\r\n node?: Nullable<SceneNode>;\r\n /** Whether this collider is enabled */\r\n enabled: boolean;\r\n}\r\n\r\n/**\r\n * Sphere collider for spring collision detection\r\n *\r\n * @public\r\n */\r\nexport interface SphereCollider extends SpringCollider {\r\n type: 'sphere';\r\n /** Center position in world space */\r\n center: Vector3;\r\n /** Radius of the sphere */\r\n radius: number;\r\n /** Local offset from node (if node is set) */\r\n localOffset?: Vector3;\r\n}\r\n\r\n/**\r\n * Capsule collider for spring collision detection\r\n *\r\n * @public\r\n */\r\nexport interface CapsuleCollider extends SpringCollider {\r\n type: 'capsule';\r\n /** Start point of the capsule axis in world space */\r\n start: Vector3;\r\n /** End point of the capsule axis in world space */\r\n end: Vector3;\r\n /** Radius of the capsule */\r\n radius: number;\r\n /** Local start offset from node (if node is set) */\r\n localStartOffset?: Vector3;\r\n /** Local end offset from node (if node is set) */\r\n localEndOffset?: Vector3;\r\n}\r\n\r\n/**\r\n * Plane collider for spring collision detection\r\n *\r\n * @public\r\n */\r\nexport interface PlaneCollider extends SpringCollider {\r\n type: 'plane';\r\n /** Point on the plane in world space */\r\n point: Vector3;\r\n /** Normal vector of the plane (should be normalized) */\r\n normal: Vector3;\r\n /** Local point offset from node (if node is set) */\r\n localPointOffset?: Vector3;\r\n /** Local normal direction (if node is set) */\r\n localNormal?: Vector3;\r\n}\r\n\r\n/**\r\n * Creates a sphere collider\r\n * @param centerOrOffset - Center position in world space, or local offset if node is provided\r\n * @param radius - Radius of the sphere\r\n * @param node - Optional scene node to attach to (if provided, centerOrOffset is treated as local offset)\r\n *\r\n * @public\r\n */\r\nexport function createSphereCollider(\r\n centerOrOffset: Vector3,\r\n radius: number,\r\n node?: SceneNode\r\n): SphereCollider {\r\n if (node) {\r\n // If node is provided, treat centerOrOffset as local offset\r\n const worldMatrix = node.worldMatrix;\r\n const worldCenter = new Vector3(\r\n worldMatrix.m03 + centerOrOffset.x,\r\n worldMatrix.m13 + centerOrOffset.y,\r\n worldMatrix.m23 + centerOrOffset.z\r\n );\r\n\r\n return {\r\n type: 'sphere',\r\n center: worldCenter,\r\n radius,\r\n node,\r\n enabled: true,\r\n localOffset: centerOrOffset.clone()\r\n };\r\n } else {\r\n // No node, use as world position\r\n return {\r\n type: 'sphere',\r\n center: centerOrOffset.clone(),\r\n radius,\r\n node: null,\r\n enabled: true\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Creates a capsule collider\r\n * @param startOrOffset - Start point in world space, or local offset if node is provided\r\n * @param endOrOffset - End point in world space, or local offset if node is provided\r\n * @param radius - Radius of the capsule\r\n * @param node - Optional scene node to attach to (if provided, offsets are treated as local)\r\n *\r\n * @public\r\n */\r\nexport function createCapsuleCollider(\r\n startOrOffset: Vector3,\r\n endOrOffset: Vector3,\r\n radius: number,\r\n node?: SceneNode\r\n): CapsuleCollider {\r\n if (node) {\r\n // If node is provided, treat as local offsets\r\n const worldMatrix = node.worldMatrix;\r\n const worldStart = new Vector3(\r\n worldMatrix.m03 + startOrOffset.x,\r\n worldMatrix.m13 + startOrOffset.y,\r\n worldMatrix.m23 + startOrOffset.z\r\n );\r\n const worldEnd = new Vector3(\r\n worldMatrix.m03 + endOrOffset.x,\r\n worldMatrix.m13 + endOrOffset.y,\r\n worldMatrix.m23 + endOrOffset.z\r\n );\r\n\r\n return {\r\n type: 'capsule',\r\n start: worldStart,\r\n end: worldEnd,\r\n radius,\r\n node,\r\n enabled: true,\r\n localStartOffset: startOrOffset.clone(),\r\n localEndOffset: endOrOffset.clone()\r\n };\r\n } else {\r\n // No node, use as world positions\r\n return {\r\n type: 'capsule',\r\n start: startOrOffset.clone(),\r\n end: endOrOffset.clone(),\r\n radius,\r\n node: null,\r\n enabled: true\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Creates a plane collider\r\n * @param pointOrOffset - Point on plane in world space, or local offset if node is provided\r\n * @param normal - Normal vector (will be normalized)\r\n * @param node - Optional scene node to attach to (if provided, pointOrOffset is treated as local offset)\r\n *\r\n * @public\r\n */\r\nexport function createPlaneCollider(\r\n pointOrOffset: Vector3,\r\n normal: Vector3,\r\n node?: SceneNode\r\n): PlaneCollider {\r\n const normalizedNormal = new Vector3();\r\n Vector3.normalize(normal, normalizedNormal);\r\n\r\n if (node) {\r\n // If node is provided, treat as local offset\r\n const worldMatrix = node.worldMatrix;\r\n const worldPoint = new Vector3(\r\n worldMatrix.m03 + pointOrOffset.x,\r\n worldMatrix.m13 + pointOrOffset.y,\r\n worldMatrix.m23 + pointOrOffset.z\r\n );\r\n\r\n return {\r\n type: 'plane',\r\n point: worldPoint,\r\n normal: normalizedNormal.clone(),\r\n node,\r\n enabled: true,\r\n localPointOffset: pointOrOffset.clone(),\r\n localNormal: normalizedNormal.clone()\r\n };\r\n } else {\r\n // No node, use as world position\r\n return {\r\n type: 'plane',\r\n point: pointOrOffset.clone(),\r\n normal: normalizedNormal,\r\n node: null,\r\n enabled: true\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Resolves collision between a particle and a sphere collider\r\n * @returns true if collision occurred\r\n *\r\n * @public\r\n */\r\nexport function resolveSphereCollision(particlePos: Vector3, collider: SphereCollider): boolean {\r\n const toParticle = Vector3.sub(particlePos, collider.center, new Vector3());\r\n const distSq = toParticle.magnitudeSq;\r\n const radiusSq = collider.radius * collider.radius;\r\n\r\n if (distSq < radiusSq && distSq > 0.0001) {\r\n // Particle is inside sphere, push it out\r\n const dist = Math.sqrt(distSq);\r\n const penetration = collider.radius - dist;\r\n\r\n // Push particle to sphere surface\r\n Vector3.normalize(toParticle, toParticle);\r\n toParticle.scaleBy(penetration);\r\n Vector3.add(particlePos, toParticle, particlePos);\r\n\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Resolves collision between a particle and a capsule collider\r\n * @returns true if collision occurred\r\n *\r\n * @public\r\n */\r\nexport function resolveCapsuleCollision(particlePos: Vector3, collider: CapsuleCollider): boolean {\r\n // Find closest point on capsule axis\r\n const axis = Vector3.sub(collider.end, collider.start, new Vector3());\r\n const axisLength = axis.magnitude;\r\n\r\n if (axisLength < 0.0001) {\r\n // Degenerate capsule, treat as sphere\r\n const toParticle = Vector3.sub(particlePos, collider.start, new Vector3());\r\n const distSq = toParticle.magnitudeSq;\r\n const radiusSq = collider.radius * collider.radius;\r\n\r\n if (distSq < radiusSq && distSq > 0.0001) {\r\n const dist = Math.sqrt(distSq);\r\n const penetration = collider.radius - dist;\r\n Vector3.normalize(toParticle, toParticle);\r\n toParticle.scaleBy(penetration);\r\n Vector3.add(particlePos, toParticle, particlePos);\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n Vector3.normalize(axis, axis);\r\n\r\n const toParticle = Vector3.sub(particlePos, collider.start, new Vector3());\r\n const projection = Vector3.dot(toParticle, axis);\r\n\r\n // Clamp projection to capsule length\r\n const t = Math.max(0, Math.min(axisLength, projection));\r\n\r\n // Closest point on capsule axis\r\n const closestPoint = Vector3.add(collider.start, Vector3.scale(axis, t, new Vector3()), new Vector3());\r\n\r\n // Check distance from closest point\r\n const toParticleFromAxis = Vector3.sub(particlePos, closestPoint, new Vector3());\r\n const distSq = toParticleFromAxis.magnitudeSq;\r\n const radiusSq = collider.radius * collider.radius;\r\n\r\n if (distSq < radiusSq && distSq > 0.0001) {\r\n const dist = Math.sqrt(distSq);\r\n const penetration = collider.radius - dist;\r\n Vector3.normalize(toParticleFromAxis, toParticleFromAxis);\r\n toParticleFromAxis.scaleBy(penetration);\r\n Vector3.add(particlePos, toParticleFromAxis, particlePos);\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Resolves collision between a particle and a plane collider\r\n * @returns true if collision occurred\r\n *\r\n * @public\r\n */\r\nexport function resolvePlaneCollision(particlePos: Vector3, collider: PlaneCollider): boolean {\r\n const toParticle = Vector3.sub(particlePos, collider.point, new Vector3());\r\n const distance = Vector3.dot(toParticle, collider.normal);\r\n\r\n if (distance < 0) {\r\n // Particle is below plane, push it up\r\n const correction = Vector3.scale(collider.normal, -distance, new Vector3());\r\n Vector3.add(particlePos, correction, particlePos);\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Updates collider position from its associated node\r\n *\r\n * @public\r\n */\r\nexport function updateColliderFromNode(collider: SpringCollider): void {\r\n if (!collider.node || !collider.enabled) {\r\n return;\r\n }\r\n\r\n const worldMatrix = collider.node.worldMatrix;\r\n\r\n switch (collider.type) {\r\n case 'sphere': {\r\n const sphere = collider as SphereCollider;\r\n if (sphere.localOffset) {\r\n // Transform local offset to world space\r\n worldMatrix.transformPointAffine(sphere.localOffset, sphere.center);\r\n } else {\r\n // No local offset, just use node position\r\n sphere.center.x = worldMatrix.m03;\r\n sphere.center.y = worldMatrix.m13;\r\n sphere.center.z = worldMatrix.m23;\r\n }\r\n break;\r\n }\r\n\r\n case 'capsule': {\r\n const capsule = collider as CapsuleCollider;\r\n if (capsule.localStartOffset && capsule.localEndOffset) {\r\n // Transform local offsets to world space\r\n worldMatrix.transformPointAffine(capsule.localStartOffset, capsule.start);\r\n worldMatrix.transformPointAffine(capsule.localEndOffset, capsule.end);\r\n } else {\r\n // No local offsets, just use node position for start\r\n capsule.start.x = worldMatrix.m03;\r\n capsule.start.y = worldMatrix.m13;\r\n capsule.start.z = worldMatrix.m23;\r\n }\r\n break;\r\n }\r\n\r\n case 'plane': {\r\n const plane = collider as PlaneCollider;\r\n if (plane.localPointOffset) {\r\n // Transform local offset to world space\r\n worldMatrix.transformPointAffine(plane.localPointOffset, plane.point);\r\n } else {\r\n // No local offset, just use node position\r\n plane.point.x = worldMatrix.m03;\r\n plane.point.y = worldMatrix.m13;\r\n plane.point.z = worldMatrix.m23;\r\n }\r\n\r\n if (plane.localNormal) {\r\n // Transform local normal to world space (rotation only)\r\n worldMatrix.transformVectorAffine(plane.localNormal, plane.normal).inplaceNormalize;\r\n }\r\n break;\r\n }\r\n }\r\n}\r\n"],"names":["createSphereCollider","centerOrOffset","radius","node","worldMatrix","worldCenter","Vector3","m03","x","m13","y","m23","z","type","center","enabled","localOffset","clone","createCapsuleCollider","startOrOffset","endOrOffset","worldStart","worldEnd","start","end","localStartOffset","localEndOffset","createPlaneCollider","pointOrOffset","normal","normalizedNormal","normalize","worldPoint","point","localPointOffset","localNormal","resolveSphereCollision","particlePos","collider","toParticle","sub","distSq","magnitudeSq","radiusSq","dist","Math","sqrt","penetration","scaleBy","add","resolveCapsuleCollision","axis","axisLength","magnitude","projection","dot","t","max","min","closestPoint","scale","toParticleFromAxis","resolvePlaneCollision","distance","correction","updateColliderFromNode","sphere","transformPointAffine","capsule","plane","transformVectorAffine","inplaceNormalize"],"mappings":";;AAqEA;;;;;;;AAOC,IACM,SAASA,oBAAAA,CACdC,cAAuB,EACvBC,MAAc,EACdC,IAAgB,EAAA;AAEhB,IAAA,IAAIA,IAAM,EAAA;;QAER,MAAMC,WAAAA,GAAcD,KAAKC,WAAW;AACpC,QAAA,MAAMC,cAAc,IAAIC,OAAAA,CACtBF,YAAYG,GAAG,GAAGN,eAAeO,CAAC,EAClCJ,YAAYK,GAAG,GAAGR,eAAeS,CAAC,EAClCN,YAAYO,GAAG,GAAGV,eAAeW,CAAC,CAAA;QAGpC,OAAO;YACLC,IAAM,EAAA,QAAA;YACNC,MAAQT,EAAAA,WAAAA;AACRH,YAAAA,MAAAA;AACAC,YAAAA,IAAAA;YACAY,OAAS,EAAA,IAAA;AACTC,YAAAA,WAAAA,EAAaf,eAAegB,KAAK;AACnC,SAAA;KACK,MAAA;;QAEL,OAAO;YACLJ,IAAM,EAAA,QAAA;AACNC,YAAAA,MAAAA,EAAQb,eAAegB,KAAK,EAAA;AAC5Bf,YAAAA,MAAAA;YACAC,IAAM,EAAA,IAAA;YACNY,OAAS,EAAA;AACX,SAAA;AACF;AACF;AAEA;;;;;;;;IASO,SAASG,qBACdC,CAAAA,aAAsB,EACtBC,WAAoB,EACpBlB,MAAc,EACdC,IAAgB,EAAA;AAEhB,IAAA,IAAIA,IAAM,EAAA;;QAER,MAAMC,WAAAA,GAAcD,KAAKC,WAAW;AACpC,QAAA,MAAMiB,aAAa,IAAIf,OAAAA,CACrBF,YAAYG,GAAG,GAAGY,cAAcX,CAAC,EACjCJ,YAAYK,GAAG,GAAGU,cAAcT,CAAC,EACjCN,YAAYO,GAAG,GAAGQ,cAAcP,CAAC,CAAA;AAEnC,QAAA,MAAMU,WAAW,IAAIhB,OAAAA,CACnBF,YAAYG,GAAG,GAAGa,YAAYZ,CAAC,EAC/BJ,YAAYK,GAAG,GAAGW,YAAYV,CAAC,EAC/BN,YAAYO,GAAG,GAAGS,YAAYR,CAAC,CAAA;QAGjC,OAAO;YACLC,IAAM,EAAA,SAAA;YACNU,KAAOF,EAAAA,UAAAA;YACPG,GAAKF,EAAAA,QAAAA;AACLpB,YAAAA,MAAAA;AACAC,YAAAA,IAAAA;YACAY,OAAS,EAAA,IAAA;AACTU,YAAAA,gBAAAA,EAAkBN,cAAcF,KAAK,EAAA;AACrCS,YAAAA,cAAAA,EAAgBN,YAAYH,KAAK;AACnC,SAAA;KACK,MAAA;;QAEL,OAAO;YACLJ,IAAM,EAAA,SAAA;AACNU,YAAAA,KAAAA,EAAOJ,cAAcF,KAAK,EAAA;AAC1BO,YAAAA,GAAAA,EAAKJ,YAAYH,KAAK,EAAA;AACtBf,YAAAA,MAAAA;YACAC,IAAM,EAAA,IAAA;YACNY,OAAS,EAAA;AACX,SAAA;AACF;AACF;AAEA;;;;;;;AAOC,IACM,SAASY,mBAAAA,CACdC,aAAsB,EACtBC,MAAe,EACf1B,IAAgB,EAAA;AAEhB,IAAA,MAAM2B,mBAAmB,IAAIxB,OAAAA,EAAAA;IAC7BA,OAAQyB,CAAAA,SAAS,CAACF,MAAQC,EAAAA,gBAAAA,CAAAA;AAE1B,IAAA,IAAI3B,IAAM,EAAA;;QAER,MAAMC,WAAAA,GAAcD,KAAKC,WAAW;AACpC,QAAA,MAAM4B,aAAa,IAAI1B,OAAAA,CACrBF,YAAYG,GAAG,GAAGqB,cAAcpB,CAAC,EACjCJ,YAAYK,GAAG,GAAGmB,cAAclB,CAAC,EACjCN,YAAYO,GAAG,GAAGiB,cAAchB,CAAC,CAAA;QAGnC,OAAO;YACLC,IAAM,EAAA,OAAA;YACNoB,KAAOD,EAAAA,UAAAA;AACPH,YAAAA,MAAAA,EAAQC,iBAAiBb,KAAK,EAAA;AAC9Bd,YAAAA,IAAAA;YACAY,OAAS,EAAA,IAAA;AACTmB,YAAAA,gBAAAA,EAAkBN,cAAcX,KAAK,EAAA;AACrCkB,YAAAA,WAAAA,EAAaL,iBAAiBb,KAAK;AACrC,SAAA;KACK,MAAA;;QAEL,OAAO;YACLJ,IAAM,EAAA,OAAA;AACNoB,YAAAA,KAAAA,EAAOL,cAAcX,KAAK,EAAA;YAC1BY,MAAQC,EAAAA,gBAAAA;YACR3B,IAAM,EAAA,IAAA;YACNY,OAAS,EAAA;AACX,SAAA;AACF;AACF;AAEA;;;;;AAKC,IACM,SAASqB,sBAAuBC,CAAAA,WAAoB,EAAEC,QAAwB,EAAA;IACnF,MAAMC,UAAAA,GAAajC,QAAQkC,GAAG,CAACH,aAAaC,QAASxB,CAAAA,MAAM,EAAE,IAAIR,OAAAA,EAAAA,CAAAA;IACjE,MAAMmC,MAAAA,GAASF,WAAWG,WAAW;AACrC,IAAA,MAAMC,QAAWL,GAAAA,QAAAA,CAASpC,MAAM,GAAGoC,SAASpC,MAAM;IAElD,IAAIuC,MAAAA,GAASE,QAAYF,IAAAA,MAAAA,GAAS,MAAQ,EAAA;;QAExC,MAAMG,IAAAA,GAAOC,IAAKC,CAAAA,IAAI,CAACL,MAAAA,CAAAA;QACvB,MAAMM,WAAAA,GAAcT,QAASpC,CAAAA,MAAM,GAAG0C,IAAAA;;QAGtCtC,OAAQyB,CAAAA,SAAS,CAACQ,UAAYA,EAAAA,UAAAA,CAAAA;AAC9BA,QAAAA,UAAAA,CAAWS,OAAO,CAACD,WAAAA,CAAAA;QACnBzC,OAAQ2C,CAAAA,GAAG,CAACZ,WAAAA,EAAaE,UAAYF,EAAAA,WAAAA,CAAAA;QAErC,OAAO,IAAA;AACT;IAEA,OAAO,KAAA;AACT;AAEA;;;;;AAKC,IACM,SAASa,uBAAwBb,CAAAA,WAAoB,EAAEC,QAAyB,EAAA;;IAErF,MAAMa,IAAAA,GAAO7C,OAAQkC,CAAAA,GAAG,CAACF,QAAAA,CAASd,GAAG,EAAEc,QAAAA,CAASf,KAAK,EAAE,IAAIjB,OAAAA,EAAAA,CAAAA;IAC3D,MAAM8C,UAAAA,GAAaD,KAAKE,SAAS;AAEjC,IAAA,IAAID,aAAa,MAAQ,EAAA;;QAEvB,MAAMb,UAAAA,GAAajC,QAAQkC,GAAG,CAACH,aAAaC,QAASf,CAAAA,KAAK,EAAE,IAAIjB,OAAAA,EAAAA,CAAAA;QAChE,MAAMmC,MAAAA,GAASF,WAAWG,WAAW;AACrC,QAAA,MAAMC,QAAWL,GAAAA,QAAAA,CAASpC,MAAM,GAAGoC,SAASpC,MAAM;QAElD,IAAIuC,MAAAA,GAASE,QAAYF,IAAAA,MAAAA,GAAS,MAAQ,EAAA;YACxC,MAAMG,IAAAA,GAAOC,IAAKC,CAAAA,IAAI,CAACL,MAAAA,CAAAA;YACvB,MAAMM,WAAAA,GAAcT,QAASpC,CAAAA,MAAM,GAAG0C,IAAAA;YACtCtC,OAAQyB,CAAAA,SAAS,CAACQ,UAAYA,EAAAA,UAAAA,CAAAA;AAC9BA,YAAAA,UAAAA,CAAWS,OAAO,CAACD,WAAAA,CAAAA;YACnBzC,OAAQ2C,CAAAA,GAAG,CAACZ,WAAAA,EAAaE,UAAYF,EAAAA,WAAAA,CAAAA;YACrC,OAAO,IAAA;AACT;QACA,OAAO,KAAA;AACT;IAEA/B,OAAQyB,CAAAA,SAAS,CAACoB,IAAMA,EAAAA,IAAAA,CAAAA;IAExB,MAAMZ,UAAAA,GAAajC,QAAQkC,GAAG,CAACH,aAAaC,QAASf,CAAAA,KAAK,EAAE,IAAIjB,OAAAA,EAAAA,CAAAA;AAChE,IAAA,MAAMgD,UAAahD,GAAAA,OAAAA,CAAQiD,GAAG,CAAChB,UAAYY,EAAAA,IAAAA,CAAAA;;IAG3C,MAAMK,CAAAA,GAAIX,KAAKY,GAAG,CAAC,GAAGZ,IAAKa,CAAAA,GAAG,CAACN,UAAYE,EAAAA,UAAAA,CAAAA,CAAAA;;AAG3C,IAAA,MAAMK,YAAerD,GAAAA,OAAAA,CAAQ2C,GAAG,CAACX,SAASf,KAAK,EAAEjB,OAAQsD,CAAAA,KAAK,CAACT,IAAAA,EAAMK,CAAG,EAAA,IAAIlD,YAAY,IAAIA,OAAAA,EAAAA,CAAAA;;AAG5F,IAAA,MAAMuD,qBAAqBvD,OAAQkC,CAAAA,GAAG,CAACH,WAAAA,EAAasB,cAAc,IAAIrD,OAAAA,EAAAA,CAAAA;IACtE,MAAMmC,MAAAA,GAASoB,mBAAmBnB,WAAW;AAC7C,IAAA,MAAMC,QAAWL,GAAAA,QAAAA,CAASpC,MAAM,GAAGoC,SAASpC,MAAM;IAElD,IAAIuC,MAAAA,GAASE,QAAYF,IAAAA,MAAAA,GAAS,MAAQ,EAAA;QACxC,MAAMG,IAAAA,GAAOC,IAAKC,CAAAA,IAAI,CAACL,MAAAA,CAAAA;QACvB,MAAMM,WAAAA,GAAcT,QAASpC,CAAAA,MAAM,GAAG0C,IAAAA;QACtCtC,OAAQyB,CAAAA,SAAS,CAAC8B,kBAAoBA,EAAAA,kBAAAA,CAAAA;AACtCA,QAAAA,kBAAAA,CAAmBb,OAAO,CAACD,WAAAA,CAAAA;QAC3BzC,OAAQ2C,CAAAA,GAAG,CAACZ,WAAAA,EAAawB,kBAAoBxB,EAAAA,WAAAA,CAAAA;QAC7C,OAAO,IAAA;AACT;IAEA,OAAO,KAAA;AACT;AAEA;;;;;AAKC,IACM,SAASyB,qBAAsBzB,CAAAA,WAAoB,EAAEC,QAAuB,EAAA;IACjF,MAAMC,UAAAA,GAAajC,QAAQkC,GAAG,CAACH,aAAaC,QAASL,CAAAA,KAAK,EAAE,IAAI3B,OAAAA,EAAAA,CAAAA;AAChE,IAAA,MAAMyD,WAAWzD,OAAQiD,CAAAA,GAAG,CAAChB,UAAAA,EAAYD,SAAST,MAAM,CAAA;AAExD,IAAA,IAAIkC,WAAW,CAAG,EAAA;;QAEhB,MAAMC,UAAAA,GAAa1D,QAAQsD,KAAK,CAACtB,SAAST,MAAM,EAAE,CAACkC,QAAAA,EAAU,IAAIzD,OAAAA,EAAAA,CAAAA;QACjEA,OAAQ2C,CAAAA,GAAG,CAACZ,WAAAA,EAAa2B,UAAY3B,EAAAA,WAAAA,CAAAA;QACrC,OAAO,IAAA;AACT;IAEA,OAAO,KAAA;AACT;AAEA;;;;IAKO,SAAS4B,sBAAAA,CAAuB3B,QAAwB,EAAA;AAC7D,IAAA,IAAI,CAACA,QAASnC,CAAAA,IAAI,IAAI,CAACmC,QAAAA,CAASvB,OAAO,EAAE;AACvC,QAAA;AACF;AAEA,IAAA,MAAMX,WAAckC,GAAAA,QAAAA,CAASnC,IAAI,CAACC,WAAW;AAE7C,IAAA,OAAQkC,SAASzB,IAAI;QACnB,KAAK,QAAA;AAAU,YAAA;AACb,gBAAA,MAAMqD,MAAS5B,GAAAA,QAAAA;gBACf,IAAI4B,MAAAA,CAAOlD,WAAW,EAAE;;AAEtBZ,oBAAAA,WAAAA,CAAY+D,oBAAoB,CAACD,MAAAA,CAAOlD,WAAW,EAAEkD,OAAOpD,MAAM,CAAA;iBAC7D,MAAA;;AAELoD,oBAAAA,MAAAA,CAAOpD,MAAM,CAACN,CAAC,GAAGJ,YAAYG,GAAG;AACjC2D,oBAAAA,MAAAA,CAAOpD,MAAM,CAACJ,CAAC,GAAGN,YAAYK,GAAG;AACjCyD,oBAAAA,MAAAA,CAAOpD,MAAM,CAACF,CAAC,GAAGR,YAAYO,GAAG;AACnC;AACA,gBAAA;AACF;QAEA,KAAK,SAAA;AAAW,YAAA;AACd,gBAAA,MAAMyD,OAAU9B,GAAAA,QAAAA;AAChB,gBAAA,IAAI8B,OAAQ3C,CAAAA,gBAAgB,IAAI2C,OAAAA,CAAQ1C,cAAc,EAAE;;AAEtDtB,oBAAAA,WAAAA,CAAY+D,oBAAoB,CAACC,OAAAA,CAAQ3C,gBAAgB,EAAE2C,QAAQ7C,KAAK,CAAA;AACxEnB,oBAAAA,WAAAA,CAAY+D,oBAAoB,CAACC,OAAAA,CAAQ1C,cAAc,EAAE0C,QAAQ5C,GAAG,CAAA;iBAC/D,MAAA;;AAEL4C,oBAAAA,OAAAA,CAAQ7C,KAAK,CAACf,CAAC,GAAGJ,YAAYG,GAAG;AACjC6D,oBAAAA,OAAAA,CAAQ7C,KAAK,CAACb,CAAC,GAAGN,YAAYK,GAAG;AACjC2D,oBAAAA,OAAAA,CAAQ7C,KAAK,CAACX,CAAC,GAAGR,YAAYO,GAAG;AACnC;AACA,gBAAA;AACF;QAEA,KAAK,OAAA;AAAS,YAAA;AACZ,gBAAA,MAAM0D,KAAQ/B,GAAAA,QAAAA;gBACd,IAAI+B,KAAAA,CAAMnC,gBAAgB,EAAE;;AAE1B9B,oBAAAA,WAAAA,CAAY+D,oBAAoB,CAACE,KAAAA,CAAMnC,gBAAgB,EAAEmC,MAAMpC,KAAK,CAAA;iBAC/D,MAAA;;AAELoC,oBAAAA,KAAAA,CAAMpC,KAAK,CAACzB,CAAC,GAAGJ,YAAYG,GAAG;AAC/B8D,oBAAAA,KAAAA,CAAMpC,KAAK,CAACvB,CAAC,GAAGN,YAAYK,GAAG;AAC/B4D,oBAAAA,KAAAA,CAAMpC,KAAK,CAACrB,CAAC,GAAGR,YAAYO,GAAG;AACjC;gBAEA,IAAI0D,KAAAA,CAAMlC,WAAW,EAAE;;oBAErB/B,WAAYkE,CAAAA,qBAAqB,CAACD,KAAMlC,CAAAA,WAAW,EAAEkC,KAAMxC,CAAAA,MAAM,EAAE0C,gBAAgB;AACrF;AACA,gBAAA;AACF;AACF;AACF;;;;"}
|
|
1
|
+
{"version":3,"file":"spring_collider.js","sources":["../../../src/animation/spring/spring_collider.ts"],"sourcesContent":["import type { Nullable } from '@zephyr3d/base';\r\nimport { Vector3 } from '@zephyr3d/base';\r\nimport type { SceneNode } from '../../scene/scene_node';\r\n\r\n/**\r\n * Base interface for spring collision shapes\r\n *\r\n * @public\r\n */\r\nexport interface SpringCollider {\r\n /** Type of collider */\r\n type: 'sphere' | 'capsule' | 'plane';\r\n /** Associated scene node (optional, for dynamic colliders) */\r\n node?: Nullable<SceneNode>;\r\n /** Whether this collider is enabled */\r\n enabled: boolean;\r\n}\r\n\r\n/**\r\n * Sphere collider for spring collision detection\r\n *\r\n * @public\r\n */\r\nexport interface SphereCollider extends SpringCollider {\r\n type: 'sphere';\r\n /** Center position in world space */\r\n center: Vector3;\r\n /** Radius of the sphere */\r\n radius: number;\r\n /** Authoring-space radius before node scaling (if node is set) */\r\n localRadius?: number;\r\n /** Baseline world scale captured at creation for backward compatibility */\r\n localRadiusScaleRef?: number;\r\n /** Local offset from node (if node is set) */\r\n localOffset?: Vector3;\r\n}\r\n\r\n/**\r\n * Capsule collider for spring collision detection\r\n *\r\n * @public\r\n */\r\nexport interface CapsuleCollider extends SpringCollider {\r\n type: 'capsule';\r\n /** Start point of the capsule axis in world space */\r\n start: Vector3;\r\n /** End point of the capsule axis in world space */\r\n end: Vector3;\r\n /** Radius of the capsule */\r\n radius: number;\r\n /** Authoring-space radius before node scaling (if node is set) */\r\n localRadius?: number;\r\n /** Baseline perpendicular scale captured at creation for backward compatibility */\r\n localRadiusScaleRef?: number;\r\n /** Local start offset from node (if node is set) */\r\n localStartOffset?: Vector3;\r\n /** Local end offset from node (if node is set) */\r\n localEndOffset?: Vector3;\r\n}\r\n\r\n/**\r\n * Plane collider for spring collision detection\r\n *\r\n * @public\r\n */\r\nexport interface PlaneCollider extends SpringCollider {\r\n type: 'plane';\r\n /** Point on the plane in world space */\r\n point: Vector3;\r\n /** Normal vector of the plane (should be normalized) */\r\n normal: Vector3;\r\n /** Local point offset from node (if node is set) */\r\n localPointOffset?: Vector3;\r\n /** Local normal direction (if node is set) */\r\n localNormal?: Vector3;\r\n}\r\n\r\n/**\r\n * Creates a sphere collider\r\n * @param centerOrOffset - Center position in world space, or local offset if node is provided\r\n * @param radius - Radius of the sphere\r\n * @param node - Optional scene node to attach to (if provided, centerOrOffset is treated as local offset)\r\n *\r\n * @public\r\n */\r\nexport function createSphereCollider(\r\n centerOrOffset: Vector3,\r\n radius: number,\r\n node?: SceneNode\r\n): SphereCollider {\r\n if (node) {\r\n // If node is provided, treat centerOrOffset as local offset\r\n const worldMatrix = node.worldMatrix;\r\n const worldCenter = worldMatrix.transformPointAffine(centerOrOffset, new Vector3());\r\n\r\n return {\r\n type: 'sphere',\r\n center: worldCenter,\r\n radius,\r\n localRadius: radius,\r\n localRadiusScaleRef: getUniformScale(worldMatrix),\r\n node,\r\n enabled: true,\r\n localOffset: centerOrOffset.clone()\r\n };\r\n } else {\r\n // No node, use as world position\r\n return {\r\n type: 'sphere',\r\n center: centerOrOffset.clone(),\r\n radius,\r\n node: null,\r\n enabled: true\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Creates a capsule collider\r\n * @param startOrOffset - Start point in world space, or local offset if node is provided\r\n * @param endOrOffset - End point in world space, or local offset if node is provided\r\n * @param radius - Radius of the capsule\r\n * @param node - Optional scene node to attach to (if provided, offsets are treated as local)\r\n *\r\n * @public\r\n */\r\nexport function createCapsuleCollider(\r\n startOrOffset: Vector3,\r\n endOrOffset: Vector3,\r\n radius: number,\r\n node?: SceneNode\r\n): CapsuleCollider {\r\n if (node) {\r\n // If node is provided, treat as local offsets\r\n const worldMatrix = node.worldMatrix;\r\n const worldStart = worldMatrix.transformPointAffine(startOrOffset, new Vector3());\r\n const worldEnd = worldMatrix.transformPointAffine(endOrOffset, new Vector3());\r\n\r\n return {\r\n type: 'capsule',\r\n start: worldStart,\r\n end: worldEnd,\r\n radius,\r\n localRadius: radius,\r\n localRadiusScaleRef: getPerpendicularScale(\r\n worldMatrix,\r\n Vector3.sub(endOrOffset, startOrOffset, new Vector3())\r\n ),\r\n node,\r\n enabled: true,\r\n localStartOffset: startOrOffset.clone(),\r\n localEndOffset: endOrOffset.clone()\r\n };\r\n } else {\r\n // No node, use as world positions\r\n return {\r\n type: 'capsule',\r\n start: startOrOffset.clone(),\r\n end: endOrOffset.clone(),\r\n radius,\r\n node: null,\r\n enabled: true\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Creates a plane collider\r\n * @param pointOrOffset - Point on plane in world space, or local offset if node is provided\r\n * @param normal - Normal vector (will be normalized)\r\n * @param node - Optional scene node to attach to (if provided, pointOrOffset is treated as local offset)\r\n *\r\n * @public\r\n */\r\nexport function createPlaneCollider(\r\n pointOrOffset: Vector3,\r\n normal: Vector3,\r\n node?: SceneNode\r\n): PlaneCollider {\r\n const normalizedNormal = new Vector3();\r\n Vector3.normalize(normal, normalizedNormal);\r\n\r\n if (node) {\r\n // If node is provided, treat as local offset\r\n const worldMatrix = node.worldMatrix;\r\n const worldPoint = worldMatrix.transformPointAffine(pointOrOffset, new Vector3());\r\n\r\n return {\r\n type: 'plane',\r\n point: worldPoint,\r\n normal: normalizedNormal.clone(),\r\n node,\r\n enabled: true,\r\n localPointOffset: pointOrOffset.clone(),\r\n localNormal: normalizedNormal.clone()\r\n };\r\n } else {\r\n // No node, use as world position\r\n return {\r\n type: 'plane',\r\n point: pointOrOffset.clone(),\r\n normal: normalizedNormal,\r\n node: null,\r\n enabled: true\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Resolves collision between a particle and a sphere collider\r\n * @returns true if collision occurred\r\n *\r\n * @public\r\n */\r\nexport function resolveSphereCollision(particlePos: Vector3, collider: SphereCollider): boolean {\r\n const toParticle = Vector3.sub(particlePos, collider.center, new Vector3());\r\n const distSq = toParticle.magnitudeSq;\r\n const radiusSq = collider.radius * collider.radius;\r\n\r\n if (distSq < radiusSq && distSq > 0.0001) {\r\n // Particle is inside sphere, push it out\r\n const dist = Math.sqrt(distSq);\r\n const penetration = collider.radius - dist;\r\n\r\n // Push particle to sphere surface\r\n Vector3.normalize(toParticle, toParticle);\r\n toParticle.scaleBy(penetration);\r\n Vector3.add(particlePos, toParticle, particlePos);\r\n\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Resolves collision between a particle and a capsule collider\r\n * @returns true if collision occurred\r\n *\r\n * @public\r\n */\r\nexport function resolveCapsuleCollision(particlePos: Vector3, collider: CapsuleCollider): boolean {\r\n // Find closest point on capsule axis\r\n const axis = Vector3.sub(collider.end, collider.start, new Vector3());\r\n const axisLength = axis.magnitude;\r\n\r\n if (axisLength < 0.0001) {\r\n // Degenerate capsule, treat as sphere\r\n const toParticle = Vector3.sub(particlePos, collider.start, new Vector3());\r\n const distSq = toParticle.magnitudeSq;\r\n const radiusSq = collider.radius * collider.radius;\r\n\r\n if (distSq < radiusSq && distSq > 0.0001) {\r\n const dist = Math.sqrt(distSq);\r\n const penetration = collider.radius - dist;\r\n Vector3.normalize(toParticle, toParticle);\r\n toParticle.scaleBy(penetration);\r\n Vector3.add(particlePos, toParticle, particlePos);\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n Vector3.normalize(axis, axis);\r\n\r\n const toParticle = Vector3.sub(particlePos, collider.start, new Vector3());\r\n const projection = Vector3.dot(toParticle, axis);\r\n\r\n // Clamp projection to capsule length\r\n const t = Math.max(0, Math.min(axisLength, projection));\r\n\r\n // Closest point on capsule axis\r\n const closestPoint = Vector3.add(collider.start, Vector3.scale(axis, t, new Vector3()), new Vector3());\r\n\r\n // Check distance from closest point\r\n const toParticleFromAxis = Vector3.sub(particlePos, closestPoint, new Vector3());\r\n const distSq = toParticleFromAxis.magnitudeSq;\r\n const radiusSq = collider.radius * collider.radius;\r\n\r\n if (distSq < radiusSq && distSq > 0.0001) {\r\n const dist = Math.sqrt(distSq);\r\n const penetration = collider.radius - dist;\r\n Vector3.normalize(toParticleFromAxis, toParticleFromAxis);\r\n toParticleFromAxis.scaleBy(penetration);\r\n Vector3.add(particlePos, toParticleFromAxis, particlePos);\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Resolves collision between a particle and a plane collider\r\n * @returns true if collision occurred\r\n *\r\n * @public\r\n */\r\nexport function resolvePlaneCollision(particlePos: Vector3, collider: PlaneCollider): boolean {\r\n const toParticle = Vector3.sub(particlePos, collider.point, new Vector3());\r\n const distance = Vector3.dot(toParticle, collider.normal);\r\n\r\n if (distance < 0) {\r\n // Particle is below plane, push it up\r\n const correction = Vector3.scale(collider.normal, -distance, new Vector3());\r\n Vector3.add(particlePos, correction, particlePos);\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Updates collider position from its associated node\r\n *\r\n * @public\r\n */\r\nexport function updateColliderFromNode(collider: SpringCollider): void {\r\n if (!collider.node || !collider.enabled) {\r\n return;\r\n }\r\n\r\n const worldMatrix = collider.node.worldMatrix;\r\n\r\n switch (collider.type) {\r\n case 'sphere': {\r\n const sphere = collider as SphereCollider;\r\n if (sphere.localRadius !== undefined) {\r\n const currentScale = getUniformScale(worldMatrix);\r\n const refScale = Math.max(1e-6, sphere.localRadiusScaleRef ?? 1);\r\n sphere.radius = sphere.localRadius * (currentScale / refScale);\r\n }\r\n if (sphere.localOffset) {\r\n // Transform local offset to world space\r\n worldMatrix.transformPointAffine(sphere.localOffset, sphere.center);\r\n } else {\r\n // No local offset, just use node position\r\n sphere.center.x = worldMatrix.m03;\r\n sphere.center.y = worldMatrix.m13;\r\n sphere.center.z = worldMatrix.m23;\r\n }\r\n break;\r\n }\r\n\r\n case 'capsule': {\r\n const capsule = collider as CapsuleCollider;\r\n if (capsule.localRadius !== undefined) {\r\n const axisLocal =\r\n capsule.localStartOffset && capsule.localEndOffset\r\n ? Vector3.sub(capsule.localEndOffset, capsule.localStartOffset, new Vector3())\r\n : Vector3.axisPY();\r\n const currentScale = getPerpendicularScale(worldMatrix, axisLocal);\r\n const refScale = Math.max(1e-6, capsule.localRadiusScaleRef ?? 1);\r\n capsule.radius = capsule.localRadius * (currentScale / refScale);\r\n }\r\n if (capsule.localStartOffset && capsule.localEndOffset) {\r\n // Transform local offsets to world space\r\n worldMatrix.transformPointAffine(capsule.localStartOffset, capsule.start);\r\n worldMatrix.transformPointAffine(capsule.localEndOffset, capsule.end);\r\n } else {\r\n // No local offsets, just use node position for start\r\n capsule.start.x = worldMatrix.m03;\r\n capsule.start.y = worldMatrix.m13;\r\n capsule.start.z = worldMatrix.m23;\r\n }\r\n break;\r\n }\r\n\r\n case 'plane': {\r\n const plane = collider as PlaneCollider;\r\n if (plane.localPointOffset) {\r\n // Transform local offset to world space\r\n worldMatrix.transformPointAffine(plane.localPointOffset, plane.point);\r\n } else {\r\n // No local offset, just use node position\r\n plane.point.x = worldMatrix.m03;\r\n plane.point.y = worldMatrix.m13;\r\n plane.point.z = worldMatrix.m23;\r\n }\r\n\r\n if (plane.localNormal) {\r\n // Transform local normal to world space (rotation only)\r\n worldMatrix.transformVectorAffine(plane.localNormal, plane.normal).inplaceNormalize();\r\n }\r\n break;\r\n }\r\n }\r\n}\r\n\r\nfunction getUniformScale(worldMatrix: any): number {\r\n const sx = worldMatrix.transformVectorAffine(Vector3.axisPX(), new Vector3()).magnitude;\r\n const sy = worldMatrix.transformVectorAffine(Vector3.axisPY(), new Vector3()).magnitude;\r\n const sz = worldMatrix.transformVectorAffine(Vector3.axisPZ(), new Vector3()).magnitude;\r\n return Math.max(1e-6, (sx + sy + sz) / 3);\r\n}\r\n\r\nfunction getPerpendicularScale(worldMatrix: any, axisLocal: Vector3): number {\r\n const axis = axisLocal.magnitudeSq > 1e-8 ? axisLocal.clone().inplaceNormalize() : Vector3.axisPY();\r\n const helper = Math.abs(axis.y) < 0.99 ? Vector3.axisPY() : Vector3.axisPX();\r\n const u = Vector3.cross(axis, helper, new Vector3()).inplaceNormalize();\r\n const v = Vector3.cross(axis, u, new Vector3()).inplaceNormalize();\r\n const su = worldMatrix.transformVectorAffine(u, new Vector3()).magnitude;\r\n const sv = worldMatrix.transformVectorAffine(v, new Vector3()).magnitude;\r\n return Math.max(1e-6, (su + sv) * 0.5);\r\n}\r\n"],"names":["createSphereCollider","centerOrOffset","radius","node","worldMatrix","worldCenter","transformPointAffine","Vector3","type","center","localRadius","localRadiusScaleRef","getUniformScale","enabled","localOffset","clone","createCapsuleCollider","startOrOffset","endOrOffset","worldStart","worldEnd","start","end","getPerpendicularScale","sub","localStartOffset","localEndOffset","createPlaneCollider","pointOrOffset","normal","normalizedNormal","normalize","worldPoint","point","localPointOffset","localNormal","resolveSphereCollision","particlePos","collider","toParticle","distSq","magnitudeSq","radiusSq","dist","Math","sqrt","penetration","scaleBy","add","resolveCapsuleCollision","axis","axisLength","magnitude","projection","dot","t","max","min","closestPoint","scale","toParticleFromAxis","resolvePlaneCollision","distance","correction","updateColliderFromNode","sphere","undefined","currentScale","refScale","x","m03","y","m13","z","m23","capsule","axisLocal","axisPY","plane","transformVectorAffine","inplaceNormalize","sx","axisPX","sy","sz","axisPZ","helper","abs","u","cross","v","su","sv"],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
position: position.clone(),
|
|
8
8
|
prevPosition: position.clone(),
|
|
9
9
|
originalPosition: position.clone(),
|
|
10
|
+
animPosition: position.clone(),
|
|
10
11
|
originalRotation: options?.originalRotation?.clone() ?? null,
|
|
11
12
|
mass: options?.mass ?? 1.0,
|
|
12
13
|
damping: options?.damping ?? 0.95,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spring_particle.js","sources":["../../../src/animation/spring/spring_particle.ts"],"sourcesContent":["import type { Vector3, Quaternion, Nullable } from '@zephyr3d/base';\r\nimport type { SceneNode } from '../../scene/scene_node';\r\n\r\n/**\r\n * Represents a particle in the spring system\r\n *\r\n * @public\r\n */\r\nexport interface SpringParticle {\r\n /** Current position in world space */\r\n position: Vector3;\r\n /** Previous position for Verlet integration */\r\n prevPosition: Vector3;\r\n /** Original position for reset */\r\n originalPosition: Vector3;\r\n /** Original world rotation (for calculating rotation delta) */\r\n originalRotation: Quaternion | null;\r\n /** Mass of the particle (affects inertia) */\r\n mass: number;\r\n /** Damping coefficient [0-1] (0 = no damping, 1 = full damping) */\r\n damping: number;\r\n /** Whether this particle is fixed (anchor point) */\r\n fixed: boolean;\r\n /** Associated scene node (optional) */\r\n node: Nullable<SceneNode>;\r\n /** Previous frame position (used to calculate velocity for inertial forces) */\r\n lastFramePosition: Vector3;\r\n /** Position history for rotation center estimation (for fixed particles) */\r\n positionHistory?: Vector3[];\r\n}\r\n\r\n/**\r\n * Creates a new spring particle\r\n *\r\n * @public\r\n */\r\nexport function createSpringParticle(\r\n position: Vector3,\r\n options?: {\r\n mass?: number;\r\n damping?: number;\r\n fixed?: boolean;\r\n node?: SceneNode;\r\n originalRotation?: Quaternion;\r\n }\r\n): SpringParticle {\r\n return {\r\n position: position.clone(),\r\n prevPosition: position.clone(),\r\n originalPosition: position.clone(),\r\n originalRotation: options?.originalRotation?.clone() ?? null,\r\n mass: options?.mass ?? 1.0,\r\n damping: options?.damping ?? 0.95,\r\n fixed: options?.fixed ?? false,\r\n node: options?.node ?? null,\r\n lastFramePosition: position.clone()\r\n };\r\n}\r\n"],"names":["createSpringParticle","position","options","clone","prevPosition","originalPosition","originalRotation","mass","damping","fixed","node","lastFramePosition"],"mappings":"
|
|
1
|
+
{"version":3,"file":"spring_particle.js","sources":["../../../src/animation/spring/spring_particle.ts"],"sourcesContent":["import type { Vector3, Quaternion, Nullable } from '@zephyr3d/base';\r\nimport type { SceneNode } from '../../scene/scene_node';\r\n\r\n/**\r\n * Represents a particle in the spring system\r\n *\r\n * @public\r\n */\r\nexport interface SpringParticle {\r\n /** Current position in world space */\r\n position: Vector3;\r\n /** Previous position for Verlet integration */\r\n prevPosition: Vector3;\r\n /** Original position for reset */\r\n originalPosition: Vector3;\r\n /** Animated (target) position for pose preservation */\r\n animPosition: Vector3;\r\n /** Original world rotation (for calculating rotation delta) */\r\n originalRotation: Quaternion | null;\r\n /** Mass of the particle (affects inertia) */\r\n mass: number;\r\n /** Damping coefficient [0-1] (0 = no damping, 1 = full damping) */\r\n damping: number;\r\n /** Whether this particle is fixed (anchor point) */\r\n fixed: boolean;\r\n /** Associated scene node (optional) */\r\n node: Nullable<SceneNode>;\r\n /** Previous frame position (used to calculate velocity for inertial forces) */\r\n lastFramePosition: Vector3;\r\n /** Position history for rotation center estimation (for fixed particles) */\r\n positionHistory?: Vector3[];\r\n}\r\n\r\n/**\r\n * Creates a new spring particle\r\n *\r\n * @public\r\n */\r\nexport function createSpringParticle(\r\n position: Vector3,\r\n options?: {\r\n mass?: number;\r\n damping?: number;\r\n fixed?: boolean;\r\n node?: SceneNode;\r\n originalRotation?: Quaternion;\r\n }\r\n): SpringParticle {\r\n return {\r\n position: position.clone(),\r\n prevPosition: position.clone(),\r\n originalPosition: position.clone(),\r\n animPosition: position.clone(),\r\n originalRotation: options?.originalRotation?.clone() ?? null,\r\n mass: options?.mass ?? 1.0,\r\n damping: options?.damping ?? 0.95,\r\n fixed: options?.fixed ?? false,\r\n node: options?.node ?? null,\r\n lastFramePosition: position.clone()\r\n };\r\n}\r\n"],"names":["createSpringParticle","position","options","clone","prevPosition","originalPosition","animPosition","originalRotation","mass","damping","fixed","node","lastFramePosition"],"mappings":"AAiCA;;;;AAIC,IACM,SAASA,oBACdC,CAAAA,QAAiB,EACjBC,OAMC,EAAA;IAED,OAAO;AACLD,QAAAA,QAAAA,EAAUA,SAASE,KAAK,EAAA;AACxBC,QAAAA,YAAAA,EAAcH,SAASE,KAAK,EAAA;AAC5BE,QAAAA,gBAAAA,EAAkBJ,SAASE,KAAK,EAAA;AAChCG,QAAAA,YAAAA,EAAcL,SAASE,KAAK,EAAA;QAC5BI,gBAAkBL,EAAAA,OAAAA,EAASK,kBAAkBJ,KAAW,EAAA,IAAA,IAAA;AACxDK,QAAAA,IAAAA,EAAMN,SAASM,IAAQ,IAAA,GAAA;AACvBC,QAAAA,OAAAA,EAASP,SAASO,OAAW,IAAA,IAAA;AAC7BC,QAAAA,KAAAA,EAAOR,SAASQ,KAAS,IAAA,KAAA;AACzBC,QAAAA,IAAAA,EAAMT,SAASS,IAAQ,IAAA,IAAA;AACvBC,QAAAA,iBAAAA,EAAmBX,SAASE,KAAK;AACnC,KAAA;AACF;;;;"}
|