@triforge/particle-core 0.1.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/core/BaseEmitter.d.ts +50 -0
- package/dist/core/BaseEmitter.d.ts.map +1 -0
- package/dist/core/BaseEmitter.js +53 -0
- package/dist/core/BaseEmitter.js.map +1 -0
- package/dist/core/BaseForce.d.ts +21 -0
- package/dist/core/BaseForce.d.ts.map +1 -0
- package/dist/core/BaseForce.js +15 -0
- package/dist/core/BaseForce.js.map +1 -0
- package/dist/core/BaseRenderer.d.ts +96 -0
- package/dist/core/BaseRenderer.d.ts.map +1 -0
- package/dist/core/BaseRenderer.js +190 -0
- package/dist/core/BaseRenderer.js.map +1 -0
- package/dist/core/DeflectorCollider.d.ts +46 -0
- package/dist/core/DeflectorCollider.d.ts.map +1 -0
- package/dist/core/DeflectorCollider.js +113 -0
- package/dist/core/DeflectorCollider.js.map +1 -0
- package/dist/core/Particle.d.ts +29 -0
- package/dist/core/Particle.d.ts.map +1 -0
- package/dist/core/Particle.js +41 -0
- package/dist/core/Particle.js.map +1 -0
- package/dist/core/ParticleCache.d.ts +73 -0
- package/dist/core/ParticleCache.d.ts.map +1 -0
- package/dist/core/ParticleCache.js +206 -0
- package/dist/core/ParticleCache.js.map +1 -0
- package/dist/core/ParticleSystem.d.ts +192 -0
- package/dist/core/ParticleSystem.d.ts.map +1 -0
- package/dist/core/ParticleSystem.js +484 -0
- package/dist/core/ParticleSystem.js.map +1 -0
- package/dist/core/SeededRandom.d.ts +17 -0
- package/dist/core/SeededRandom.d.ts.map +1 -0
- package/dist/core/SeededRandom.js +27 -0
- package/dist/core/SeededRandom.js.map +1 -0
- package/dist/emitters/EdgeEmitter.d.ts +43 -0
- package/dist/emitters/EdgeEmitter.d.ts.map +1 -0
- package/dist/emitters/EdgeEmitter.js +78 -0
- package/dist/emitters/EdgeEmitter.js.map +1 -0
- package/dist/emitters/MeshEmitter.d.ts +83 -0
- package/dist/emitters/MeshEmitter.d.ts.map +1 -0
- package/dist/emitters/MeshEmitter.js +240 -0
- package/dist/emitters/MeshEmitter.js.map +1 -0
- package/dist/emitters/PointEmitter.d.ts +22 -0
- package/dist/emitters/PointEmitter.d.ts.map +1 -0
- package/dist/emitters/PointEmitter.js +26 -0
- package/dist/emitters/PointEmitter.js.map +1 -0
- package/dist/forces/BoidField.d.ts +58 -0
- package/dist/forces/BoidField.d.ts.map +1 -0
- package/dist/forces/BoidField.js +82 -0
- package/dist/forces/BoidField.js.map +1 -0
- package/dist/forces/BoidForce.d.ts +54 -0
- package/dist/forces/BoidForce.d.ts.map +1 -0
- package/dist/forces/BoidForce.js +233 -0
- package/dist/forces/BoidForce.js.map +1 -0
- package/dist/forces/ChargeForce.d.ts +22 -0
- package/dist/forces/ChargeForce.d.ts.map +1 -0
- package/dist/forces/ChargeForce.js +35 -0
- package/dist/forces/ChargeForce.js.map +1 -0
- package/dist/forces/CurveGuideForce.d.ts +43 -0
- package/dist/forces/CurveGuideForce.d.ts.map +1 -0
- package/dist/forces/CurveGuideForce.js +118 -0
- package/dist/forces/CurveGuideForce.js.map +1 -0
- package/dist/forces/DragForce.d.ts +19 -0
- package/dist/forces/DragForce.d.ts.map +1 -0
- package/dist/forces/DragForce.js +31 -0
- package/dist/forces/DragForce.js.map +1 -0
- package/dist/forces/FlowFieldForce.d.ts +72 -0
- package/dist/forces/FlowFieldForce.d.ts.map +1 -0
- package/dist/forces/FlowFieldForce.js +68 -0
- package/dist/forces/FlowFieldForce.js.map +1 -0
- package/dist/forces/ForceField.d.ts +26 -0
- package/dist/forces/ForceField.d.ts.map +1 -0
- package/dist/forces/ForceField.js +41 -0
- package/dist/forces/ForceField.js.map +1 -0
- package/dist/forces/GravityForce.d.ts +9 -0
- package/dist/forces/GravityForce.d.ts.map +1 -0
- package/dist/forces/GravityForce.js +12 -0
- package/dist/forces/GravityForce.js.map +1 -0
- package/dist/forces/HarmonicForce.d.ts +22 -0
- package/dist/forces/HarmonicForce.d.ts.map +1 -0
- package/dist/forces/HarmonicForce.js +31 -0
- package/dist/forces/HarmonicForce.js.map +1 -0
- package/dist/forces/LennardJonesForce.d.ts +23 -0
- package/dist/forces/LennardJonesForce.d.ts.map +1 -0
- package/dist/forces/LennardJonesForce.js +38 -0
- package/dist/forces/LennardJonesForce.js.map +1 -0
- package/dist/forces/MagneticForce.d.ts +21 -0
- package/dist/forces/MagneticForce.d.ts.map +1 -0
- package/dist/forces/MagneticForce.js +30 -0
- package/dist/forces/MagneticForce.js.map +1 -0
- package/dist/forces/TextureForce.d.ts +37 -0
- package/dist/forces/TextureForce.d.ts.map +1 -0
- package/dist/forces/TextureForce.js +56 -0
- package/dist/forces/TextureForce.js.map +1 -0
- package/dist/forces/TurbulenceForce.d.ts +21 -0
- package/dist/forces/TurbulenceForce.d.ts.map +1 -0
- package/dist/forces/TurbulenceForce.js +39 -0
- package/dist/forces/TurbulenceForce.js.map +1 -0
- package/dist/forces/VortexForce.d.ts +21 -0
- package/dist/forces/VortexForce.d.ts.map +1 -0
- package/dist/forces/VortexForce.js +29 -0
- package/dist/forces/VortexForce.js.map +1 -0
- package/dist/forces/WindForce.d.ts +21 -0
- package/dist/forces/WindForce.d.ts.map +1 -0
- package/dist/forces/WindForce.js +29 -0
- package/dist/forces/WindForce.js.map +1 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/physics/KeyedPhysics.d.ts +43 -0
- package/dist/physics/KeyedPhysics.d.ts.map +1 -0
- package/dist/physics/KeyedPhysics.js +73 -0
- package/dist/physics/KeyedPhysics.js.map +1 -0
- package/dist/physics/SPHPhysics.d.ts +27 -0
- package/dist/physics/SPHPhysics.d.ts.map +1 -0
- package/dist/physics/SPHPhysics.js +119 -0
- package/dist/physics/SPHPhysics.js.map +1 -0
- package/dist/renderers/BillboardRenderer.d.ts +75 -0
- package/dist/renderers/BillboardRenderer.d.ts.map +1 -0
- package/dist/renderers/BillboardRenderer.js +106 -0
- package/dist/renderers/BillboardRenderer.js.map +1 -0
- package/dist/renderers/CollectionRenderer.d.ts +83 -0
- package/dist/renderers/CollectionRenderer.d.ts.map +1 -0
- package/dist/renderers/CollectionRenderer.js +161 -0
- package/dist/renderers/CollectionRenderer.js.map +1 -0
- package/dist/renderers/HaloRenderer.d.ts +3 -0
- package/dist/renderers/HaloRenderer.d.ts.map +1 -0
- package/dist/renderers/HaloRenderer.js +4 -0
- package/dist/renderers/HaloRenderer.js.map +1 -0
- package/dist/renderers/InstanceRenderer.d.ts +70 -0
- package/dist/renderers/InstanceRenderer.d.ts.map +1 -0
- package/dist/renderers/InstanceRenderer.js +86 -0
- package/dist/renderers/InstanceRenderer.js.map +1 -0
- package/dist/renderers/LineRenderer.d.ts +52 -0
- package/dist/renderers/LineRenderer.d.ts.map +1 -0
- package/dist/renderers/LineRenderer.js +96 -0
- package/dist/renderers/LineRenderer.js.map +1 -0
- package/dist/renderers/NoneRenderer.d.ts +19 -0
- package/dist/renderers/NoneRenderer.d.ts.map +1 -0
- package/dist/renderers/NoneRenderer.js +24 -0
- package/dist/renderers/NoneRenderer.js.map +1 -0
- package/dist/renderers/ObjectRenderer.d.ts +3 -0
- package/dist/renderers/ObjectRenderer.d.ts.map +1 -0
- package/dist/renderers/ObjectRenderer.js +4 -0
- package/dist/renderers/ObjectRenderer.js.map +1 -0
- package/dist/renderers/StrandRenderer.d.ts +169 -0
- package/dist/renderers/StrandRenderer.d.ts.map +1 -0
- package/dist/renderers/StrandRenderer.js +235 -0
- package/dist/renderers/StrandRenderer.js.map +1 -0
- package/dist/renderers/TrailRenderer.d.ts +54 -0
- package/dist/renderers/TrailRenderer.d.ts.map +1 -0
- package/dist/renderers/TrailRenderer.js +114 -0
- package/dist/renderers/TrailRenderer.js.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Vector3, BufferGeometry } from 'three';
|
|
2
|
+
import type { Particle } from './Particle.js';
|
|
3
|
+
import type { SeededRandom } from './SeededRandom.js';
|
|
4
|
+
export type EmitFrom = 'verts' | 'faces' | 'volume';
|
|
5
|
+
export interface BaseEmitterOptions {
|
|
6
|
+
/** Velocity along face/vertex normal (Blender: Normal) */
|
|
7
|
+
normalVelocity?: number;
|
|
8
|
+
/** Velocity along surface tangent (Blender: Tangent) */
|
|
9
|
+
tangentVelocity?: number;
|
|
10
|
+
/** Tangent rotation offset in radians (Blender: Tangent Phase) */
|
|
11
|
+
tangentPhase?: number;
|
|
12
|
+
/** Velocity along emitter object X axis (Blender: Object Align X) */
|
|
13
|
+
objectVelocityX?: number;
|
|
14
|
+
/** Velocity along emitter object Y axis (Blender: Object Align Y) */
|
|
15
|
+
objectVelocityY?: number;
|
|
16
|
+
/** Velocity along emitter object Z axis (Blender: Object Align Z) */
|
|
17
|
+
objectVelocityZ?: number;
|
|
18
|
+
/** Fraction of emitter object velocity inherited (Blender: Object Velocity) */
|
|
19
|
+
objectInherit?: number;
|
|
20
|
+
/** Random velocity magnitude (Blender: Randomise) */
|
|
21
|
+
randomVelocity?: number;
|
|
22
|
+
/** Where on the mesh to emit from (Blender: Emit From) */
|
|
23
|
+
emitFrom?: EmitFrom;
|
|
24
|
+
/** Distribute evenly across surface area (Blender: Even Distribution) */
|
|
25
|
+
evenDistribution?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Abstract base — knows how to sample a spawn point from a geometry
|
|
29
|
+
* and write initial position/velocity onto a Particle.
|
|
30
|
+
*
|
|
31
|
+
* Concrete subclasses: PointEmitter, MeshEmitter, EdgeEmitter.
|
|
32
|
+
*/
|
|
33
|
+
export declare abstract class BaseEmitter {
|
|
34
|
+
/** Blender-matched public parameters — GSAP / keyframe compatible */
|
|
35
|
+
parameters: Record<string, number>;
|
|
36
|
+
/**
|
|
37
|
+
* World-space velocity of the emitter object (set externally each frame).
|
|
38
|
+
* Blender: Velocity → Object Velocity — particles inherit this × objectInherit.
|
|
39
|
+
*/
|
|
40
|
+
worldVelocity: Vector3;
|
|
41
|
+
constructor(opts?: BaseEmitterOptions);
|
|
42
|
+
/**
|
|
43
|
+
* Write spawn position and initial velocity onto the particle.
|
|
44
|
+
* Called by ParticleSystem each time a particle is born.
|
|
45
|
+
*/
|
|
46
|
+
abstract spawn(particle: Particle, geometry: BufferGeometry | null, rng: SeededRandom): void;
|
|
47
|
+
/** Apply velocity parameters after spawn point is set */
|
|
48
|
+
protected applyVelocity(particle: Particle, normal: Vector3, tangent: Vector3, rng: SeededRandom): void;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=BaseEmitter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseEmitter.d.ts","sourceRoot":"","sources":["../../src/core/BaseEmitter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAC/C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGrD,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEnD,MAAM,WAAW,kBAAkB;IACjC,0DAA0D;IAC1D,cAAc,CAAC,EAAI,MAAM,CAAA;IACzB,wDAAwD;IACxD,eAAe,CAAC,EAAG,MAAM,CAAA;IACzB,kEAAkE;IAClE,YAAY,CAAC,EAAM,MAAM,CAAA;IACzB,qEAAqE;IACrE,eAAe,CAAC,EAAG,MAAM,CAAA;IACzB,qEAAqE;IACrE,eAAe,CAAC,EAAG,MAAM,CAAA;IACzB,qEAAqE;IACrE,eAAe,CAAC,EAAG,MAAM,CAAA;IACzB,+EAA+E;IAC/E,aAAa,CAAC,EAAK,MAAM,CAAA;IACzB,qDAAqD;IACrD,cAAc,CAAC,EAAI,MAAM,CAAA;IACzB,0DAA0D;IAC1D,QAAQ,CAAC,EAAU,QAAQ,CAAA;IAC3B,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED;;;;;GAKG;AACH,8BAAsB,WAAW;IAC/B,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAElC;;;OAGG;IACH,aAAa,EAAE,OAAO,CAAgB;gBAE1B,IAAI,GAAE,kBAAuB;IAgBzC;;;OAGG;IACH,QAAQ,CAAC,KAAK,CACZ,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,cAAc,GAAG,IAAI,EAC/B,GAAG,EAAE,YAAY,GAChB,IAAI;IAEP,yDAAyD;IACzD,SAAS,CAAC,aAAa,CACrB,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,YAAY,GAChB,IAAI;CA2BR"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Vector3 } from 'three';
|
|
2
|
+
/**
|
|
3
|
+
* Abstract base — knows how to sample a spawn point from a geometry
|
|
4
|
+
* and write initial position/velocity onto a Particle.
|
|
5
|
+
*
|
|
6
|
+
* Concrete subclasses: PointEmitter, MeshEmitter, EdgeEmitter.
|
|
7
|
+
*/
|
|
8
|
+
export class BaseEmitter {
|
|
9
|
+
constructor(opts = {}) {
|
|
10
|
+
/**
|
|
11
|
+
* World-space velocity of the emitter object (set externally each frame).
|
|
12
|
+
* Blender: Velocity → Object Velocity — particles inherit this × objectInherit.
|
|
13
|
+
*/
|
|
14
|
+
this.worldVelocity = new Vector3();
|
|
15
|
+
this.parameters = {
|
|
16
|
+
normalVelocity: opts.normalVelocity ?? 0,
|
|
17
|
+
tangentVelocity: opts.tangentVelocity ?? 0,
|
|
18
|
+
tangentPhase: opts.tangentPhase ?? 0,
|
|
19
|
+
objectVelocityX: opts.objectVelocityX ?? 0,
|
|
20
|
+
objectVelocityY: opts.objectVelocityY ?? 0,
|
|
21
|
+
objectVelocityZ: opts.objectVelocityZ ?? 0,
|
|
22
|
+
objectInherit: opts.objectInherit ?? 0,
|
|
23
|
+
randomVelocity: opts.randomVelocity ?? 0,
|
|
24
|
+
// emitFrom stored as 0=verts, 1=faces, 2=volume
|
|
25
|
+
emitFrom: opts.emitFrom === 'faces' ? 1 : opts.emitFrom === 'volume' ? 2 : 0,
|
|
26
|
+
evenDistribution: opts.evenDistribution ? 1 : 0,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** Apply velocity parameters after spawn point is set */
|
|
30
|
+
applyVelocity(particle, normal, tangent, rng) {
|
|
31
|
+
const p = this.parameters;
|
|
32
|
+
// Normal component
|
|
33
|
+
particle.velocity.addScaledVector(normal, p.normalVelocity);
|
|
34
|
+
// Tangent component (rotated by tangentPhase)
|
|
35
|
+
const t = tangent.clone().applyAxisAngle(normal, p.tangentPhase);
|
|
36
|
+
particle.velocity.addScaledVector(t, p.tangentVelocity);
|
|
37
|
+
// Object-axis components
|
|
38
|
+
particle.velocity.x += p.objectVelocityX;
|
|
39
|
+
particle.velocity.y += p.objectVelocityY;
|
|
40
|
+
particle.velocity.z += p.objectVelocityZ;
|
|
41
|
+
// Random component
|
|
42
|
+
if (p.randomVelocity > 0) {
|
|
43
|
+
particle.velocity.x += rng.signed() * p.randomVelocity;
|
|
44
|
+
particle.velocity.y += rng.signed() * p.randomVelocity;
|
|
45
|
+
particle.velocity.z += rng.signed() * p.randomVelocity;
|
|
46
|
+
}
|
|
47
|
+
// Emitter object velocity inheritance (Blender: Object Velocity)
|
|
48
|
+
if (p.objectInherit !== 0) {
|
|
49
|
+
particle.velocity.addScaledVector(this.worldVelocity, p.objectInherit);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=BaseEmitter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseEmitter.js","sourceRoot":"","sources":["../../src/core/BaseEmitter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAkB,MAAM,OAAO,CAAA;AA8B/C;;;;;GAKG;AACH,MAAM,OAAgB,WAAW;IAU/B,YAAY,OAA2B,EAAE;QANzC;;;WAGG;QACH,kBAAa,GAAY,IAAI,OAAO,EAAE,CAAA;QAGpC,IAAI,CAAC,UAAU,GAAG;YAChB,cAAc,EAAI,IAAI,CAAC,cAAc,IAAK,CAAC;YAC3C,eAAe,EAAG,IAAI,CAAC,eAAe,IAAI,CAAC;YAC3C,YAAY,EAAM,IAAI,CAAC,YAAY,IAAO,CAAC;YAC3C,eAAe,EAAG,IAAI,CAAC,eAAe,IAAI,CAAC;YAC3C,eAAe,EAAG,IAAI,CAAC,eAAe,IAAI,CAAC;YAC3C,eAAe,EAAG,IAAI,CAAC,eAAe,IAAI,CAAC;YAC3C,aAAa,EAAK,IAAI,CAAC,aAAa,IAAM,CAAC;YAC3C,cAAc,EAAI,IAAI,CAAC,cAAc,IAAK,CAAC;YAC3C,gDAAgD;YAChD,QAAQ,EAAU,IAAI,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACpF,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SAChD,CAAA;IACH,CAAC;IAYD,yDAAyD;IAC/C,aAAa,CACrB,QAAkB,EAClB,MAAe,EACf,OAAgB,EAChB,GAAiB;QAEjB,MAAM,CAAC,GAAG,IAAI,CAAC,UAAU,CAAA;QAEzB,mBAAmB;QACnB,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,cAAc,CAAC,CAAA;QAE3D,8CAA8C;QAC9C,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,YAAY,CAAC,CAAA;QAChE,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,eAAe,CAAC,CAAA;QAEvD,yBAAyB;QACzB,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,eAAe,CAAA;QACxC,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,eAAe,CAAA;QACxC,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,eAAe,CAAA;QAExC,mBAAmB;QACnB,IAAI,CAAC,CAAC,cAAc,GAAG,CAAC,EAAE,CAAC;YACzB,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,cAAc,CAAA;YACtD,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,cAAc,CAAA;YACtD,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,cAAc,CAAA;QACxD,CAAC;QAED,iEAAiE;QACjE,IAAI,CAAC,CAAC,aAAa,KAAK,CAAC,EAAE,CAAC;YAC1B,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,aAAa,CAAC,CAAA;QACxE,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Particle } from './Particle.js';
|
|
2
|
+
/**
|
|
3
|
+
* Abstract base for all force field effectors.
|
|
4
|
+
* Each force receives a particle and a dt, and mutates particle.velocity.
|
|
5
|
+
*
|
|
6
|
+
* Concrete subclasses: GravityForce, WindForce, VortexForce, DragForce,
|
|
7
|
+
* TurbulenceForce, MagneticForce, HarmonicForce, ChargeForce,
|
|
8
|
+
* LennardJonesForce, TextureForce, DragFieldForce.
|
|
9
|
+
*/
|
|
10
|
+
export declare abstract class BaseForce {
|
|
11
|
+
/** Whether this force is currently active */
|
|
12
|
+
enabled: boolean;
|
|
13
|
+
/** Blender-matched public parameters — GSAP / keyframe compatible */
|
|
14
|
+
abstract parameters: Record<string, number>;
|
|
15
|
+
/**
|
|
16
|
+
* Apply force to a single particle for one timestep.
|
|
17
|
+
* Mutates particle.velocity only — never position.
|
|
18
|
+
*/
|
|
19
|
+
abstract apply(particle: Particle, dt: number): void;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=BaseForce.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseForce.d.ts","sourceRoot":"","sources":["../../src/core/BaseForce.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAE7C;;;;;;;GAOG;AACH,8BAAsB,SAAS;IAC7B,6CAA6C;IAC7C,OAAO,UAAO;IAEd,qEAAqE;IACrE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAE3C;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;CACrD"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract base for all force field effectors.
|
|
3
|
+
* Each force receives a particle and a dt, and mutates particle.velocity.
|
|
4
|
+
*
|
|
5
|
+
* Concrete subclasses: GravityForce, WindForce, VortexForce, DragForce,
|
|
6
|
+
* TurbulenceForce, MagneticForce, HarmonicForce, ChargeForce,
|
|
7
|
+
* LennardJonesForce, TextureForce, DragFieldForce.
|
|
8
|
+
*/
|
|
9
|
+
export class BaseForce {
|
|
10
|
+
constructor() {
|
|
11
|
+
/** Whether this force is currently active */
|
|
12
|
+
this.enabled = true;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=BaseForce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseForce.js","sourceRoot":"","sources":["../../src/core/BaseForce.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,OAAgB,SAAS;IAA/B;QACE,6CAA6C;QAC7C,YAAO,GAAG,IAAI,CAAA;IAUhB,CAAC;CAAA"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { Object3D } from 'three';
|
|
2
|
+
import type { SeededRandom } from './SeededRandom.js';
|
|
3
|
+
/**
|
|
4
|
+
* Structural interface satisfied by both Particle and the pre-allocated
|
|
5
|
+
* child draw-buffer entries. Renderers iterate this instead of Particle[]
|
|
6
|
+
* so children (which are not real pool particles) can pass through the same
|
|
7
|
+
* draw loop.
|
|
8
|
+
*/
|
|
9
|
+
export interface ParticleLike {
|
|
10
|
+
position: {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
13
|
+
z: number;
|
|
14
|
+
};
|
|
15
|
+
velocity: {
|
|
16
|
+
x: number;
|
|
17
|
+
y: number;
|
|
18
|
+
z: number;
|
|
19
|
+
};
|
|
20
|
+
rotation: {
|
|
21
|
+
x: number;
|
|
22
|
+
y: number;
|
|
23
|
+
z: number;
|
|
24
|
+
};
|
|
25
|
+
size: number;
|
|
26
|
+
normalised: number;
|
|
27
|
+
alive: boolean;
|
|
28
|
+
lifetime: number;
|
|
29
|
+
age: number;
|
|
30
|
+
emitterIndex: number;
|
|
31
|
+
}
|
|
32
|
+
/** Pre-allocated draw-buffer entry — also carries the parent pool index. */
|
|
33
|
+
interface DrawEntry extends ParticleLike {
|
|
34
|
+
poolIdx: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Abstract base for all particle renderers.
|
|
38
|
+
* A renderer owns a Three.js Object3D and updates it each tick
|
|
39
|
+
* from the live particle array.
|
|
40
|
+
*
|
|
41
|
+
* Concrete subclasses: BillboardRenderer, InstanceRenderer, LineRenderer.
|
|
42
|
+
*/
|
|
43
|
+
export declare abstract class BaseRenderer {
|
|
44
|
+
/** The Three.js object to add to the scene */
|
|
45
|
+
abstract readonly object3D: Object3D;
|
|
46
|
+
/**
|
|
47
|
+
* Show or hide the particle helper geometry.
|
|
48
|
+
* In Blender this is the viewport dot/sphere representation —
|
|
49
|
+
* hidden in final renders. Set false to see only the resulting
|
|
50
|
+
* mesh/material assigned to the particles, not the placeholders.
|
|
51
|
+
*/
|
|
52
|
+
get visible(): boolean;
|
|
53
|
+
set visible(v: boolean);
|
|
54
|
+
/**
|
|
55
|
+
* Called once per frame with the full particle pool.
|
|
56
|
+
* Update GPU buffers here — no allocations allowed inside this method.
|
|
57
|
+
*
|
|
58
|
+
* params and childRng are optional so that legacy callers (unit tests) that
|
|
59
|
+
* pass only (particles, aliveCount) still work — children are disabled when
|
|
60
|
+
* params is omitted or params.childCount is 0.
|
|
61
|
+
*/
|
|
62
|
+
abstract update(particles: ParticleLike[], aliveCount: number, params?: Record<string, number>, childRng?: SeededRandom): void;
|
|
63
|
+
/** Free GPU resources */
|
|
64
|
+
abstract dispose(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Pre-allocated draw buffer — filled each frame by expandWithChildren().
|
|
67
|
+
* Concrete constructors must call _allocDrawBuf(maxCount) to initialise it.
|
|
68
|
+
*/
|
|
69
|
+
protected _drawBuf: DrawEntry[];
|
|
70
|
+
/**
|
|
71
|
+
* Pre-allocated alive-particle scratch list — filled inside expandWithChildren
|
|
72
|
+
* for the interpolated pass without heap allocations.
|
|
73
|
+
*/
|
|
74
|
+
protected _aliveBuf: ParticleLike[];
|
|
75
|
+
/**
|
|
76
|
+
* Allocate both pre-allocated buffers.
|
|
77
|
+
* Call once from each concrete renderer's constructor, passing maxCount.
|
|
78
|
+
*/
|
|
79
|
+
protected _allocDrawBuf(max: number): void;
|
|
80
|
+
/**
|
|
81
|
+
* Expand the particle pool with children and write the result into _drawBuf.
|
|
82
|
+
* Returns the number of entries written (≤ maxCount).
|
|
83
|
+
*
|
|
84
|
+
* When childCount === 0 or childType === 0 this copies only alive parents —
|
|
85
|
+
* the caller's draw loop then iterates _drawBuf[0..n] instead of pool,
|
|
86
|
+
* skipping dead slots for free.
|
|
87
|
+
*
|
|
88
|
+
* childType: 0 = none (parents only)
|
|
89
|
+
* 1 = simple (random sphere scatter)
|
|
90
|
+
* 2 = interpolated (between consecutive parents)
|
|
91
|
+
*/
|
|
92
|
+
protected expandWithChildren(pool: ParticleLike[], _aliveCount: number, childCount: number, childType: number, childSpread: number, rng: SeededRandom | null, maxCount: number): number;
|
|
93
|
+
private _copyToEntry;
|
|
94
|
+
}
|
|
95
|
+
export {};
|
|
96
|
+
//# sourceMappingURL=BaseRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseRenderer.d.ts","sourceRoot":"","sources":["../../src/core/BaseRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACrC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAErD;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAI;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC/C,QAAQ,EAAI;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC/C,QAAQ,EAAI;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC/C,IAAI,EAAQ,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAO,OAAO,CAAA;IACnB,QAAQ,EAAI,MAAM,CAAA;IAClB,GAAG,EAAS,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,4EAA4E;AAC5E,UAAU,SAAU,SAAQ,YAAY;IACtC,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;GAMG;AACH,8BAAsB,YAAY;IAChC,8CAA8C;IAC9C,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAEpC;;;;;OAKG;IACH,IAAI,OAAO,IAAI,OAAO,CAAiC;IACvD,IAAI,OAAO,CAAC,CAAC,EAAE,OAAO,EAA+B;IAErD;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,CACb,SAAS,EAAE,YAAY,EAAE,EACzB,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACjC,QAAQ,CAAC,EAAE,YAAY,GACtB,IAAI;IAEP,yBAAyB;IACzB,QAAQ,CAAC,OAAO,IAAI,IAAI;IAIxB;;;OAGG;IACH,SAAS,CAAC,QAAQ,EAAE,SAAS,EAAE,CAAK;IAEpC;;;OAGG;IACH,SAAS,CAAC,SAAS,EAAE,YAAY,EAAE,CAAK;IAExC;;;OAGG;IACH,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAiB1C;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,kBAAkB,CAC1B,IAAI,EAAS,YAAY,EAAE,EAC3B,WAAW,EAAE,MAAM,EACnB,UAAU,EAAG,MAAM,EACnB,SAAS,EAAI,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,GAAG,EAAU,YAAY,GAAG,IAAI,EAChC,QAAQ,EAAK,MAAM,GAClB,MAAM;IAkHT,OAAO,CAAC,YAAY;CAkBrB"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract base for all particle renderers.
|
|
3
|
+
* A renderer owns a Three.js Object3D and updates it each tick
|
|
4
|
+
* from the live particle array.
|
|
5
|
+
*
|
|
6
|
+
* Concrete subclasses: BillboardRenderer, InstanceRenderer, LineRenderer.
|
|
7
|
+
*/
|
|
8
|
+
export class BaseRenderer {
|
|
9
|
+
constructor() {
|
|
10
|
+
// ── Children expansion infrastructure ────────────────────────────────────
|
|
11
|
+
/**
|
|
12
|
+
* Pre-allocated draw buffer — filled each frame by expandWithChildren().
|
|
13
|
+
* Concrete constructors must call _allocDrawBuf(maxCount) to initialise it.
|
|
14
|
+
*/
|
|
15
|
+
this._drawBuf = [];
|
|
16
|
+
/**
|
|
17
|
+
* Pre-allocated alive-particle scratch list — filled inside expandWithChildren
|
|
18
|
+
* for the interpolated pass without heap allocations.
|
|
19
|
+
*/
|
|
20
|
+
this._aliveBuf = [];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Show or hide the particle helper geometry.
|
|
24
|
+
* In Blender this is the viewport dot/sphere representation —
|
|
25
|
+
* hidden in final renders. Set false to see only the resulting
|
|
26
|
+
* mesh/material assigned to the particles, not the placeholders.
|
|
27
|
+
*/
|
|
28
|
+
get visible() { return this.object3D.visible; }
|
|
29
|
+
set visible(v) { this.object3D.visible = v; }
|
|
30
|
+
/**
|
|
31
|
+
* Allocate both pre-allocated buffers.
|
|
32
|
+
* Call once from each concrete renderer's constructor, passing maxCount.
|
|
33
|
+
*/
|
|
34
|
+
_allocDrawBuf(max) {
|
|
35
|
+
this._drawBuf = Array.from({ length: max }, () => ({
|
|
36
|
+
position: { x: 0, y: 0, z: 0 },
|
|
37
|
+
velocity: { x: 0, y: 0, z: 0 },
|
|
38
|
+
rotation: { x: 0, y: 0, z: 0 },
|
|
39
|
+
size: 1,
|
|
40
|
+
normalised: 0,
|
|
41
|
+
alive: true,
|
|
42
|
+
lifetime: 1,
|
|
43
|
+
age: 0,
|
|
44
|
+
emitterIndex: 0,
|
|
45
|
+
poolIdx: 0,
|
|
46
|
+
}));
|
|
47
|
+
// _aliveBuf only needs room for alive particles, worst case = max
|
|
48
|
+
this._aliveBuf = new Array(max);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Expand the particle pool with children and write the result into _drawBuf.
|
|
52
|
+
* Returns the number of entries written (≤ maxCount).
|
|
53
|
+
*
|
|
54
|
+
* When childCount === 0 or childType === 0 this copies only alive parents —
|
|
55
|
+
* the caller's draw loop then iterates _drawBuf[0..n] instead of pool,
|
|
56
|
+
* skipping dead slots for free.
|
|
57
|
+
*
|
|
58
|
+
* childType: 0 = none (parents only)
|
|
59
|
+
* 1 = simple (random sphere scatter)
|
|
60
|
+
* 2 = interpolated (between consecutive parents)
|
|
61
|
+
*/
|
|
62
|
+
expandWithChildren(pool, _aliveCount, childCount, childType, childSpread, rng, maxCount) {
|
|
63
|
+
const cc = Math.round(Math.max(0, childCount));
|
|
64
|
+
const ct = Math.round(childType);
|
|
65
|
+
// ── No children — copy alive parents only ─────────────────────────────
|
|
66
|
+
if (cc === 0 || ct === 0) {
|
|
67
|
+
let n = 0;
|
|
68
|
+
for (let pi = 0; pi < pool.length; pi++) {
|
|
69
|
+
const p = pool[pi];
|
|
70
|
+
if (!p.alive)
|
|
71
|
+
continue;
|
|
72
|
+
if (n >= maxCount)
|
|
73
|
+
break;
|
|
74
|
+
this._copyToEntry(this._drawBuf[n], p, pi);
|
|
75
|
+
n++;
|
|
76
|
+
}
|
|
77
|
+
return n;
|
|
78
|
+
}
|
|
79
|
+
// ── Build alive list (no allocations — writes into _aliveBuf) ─────────
|
|
80
|
+
let an = 0;
|
|
81
|
+
for (let pi = 0; pi < pool.length; pi++) {
|
|
82
|
+
const p = pool[pi];
|
|
83
|
+
if (p.alive) {
|
|
84
|
+
this._aliveBuf[an] = p;
|
|
85
|
+
// stash pool index in the drawbuf slot we'll use later; easiest to
|
|
86
|
+
// track it separately via a parallel index trick below
|
|
87
|
+
an++;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Also need pool indices for each alive particle — re-scan is cheap
|
|
91
|
+
let n = 0;
|
|
92
|
+
if (ct === 1) {
|
|
93
|
+
// ── Simple children — random sphere around each parent ───────────────
|
|
94
|
+
// Re-scan pool to preserve pool indices without extra allocation
|
|
95
|
+
let ai = 0;
|
|
96
|
+
for (let pi = 0; pi < pool.length; pi++) {
|
|
97
|
+
const p = pool[pi];
|
|
98
|
+
if (!p.alive)
|
|
99
|
+
continue;
|
|
100
|
+
if (n >= maxCount)
|
|
101
|
+
break;
|
|
102
|
+
// Write parent
|
|
103
|
+
this._copyToEntry(this._drawBuf[n], p, pi);
|
|
104
|
+
n++;
|
|
105
|
+
ai++;
|
|
106
|
+
// Write children
|
|
107
|
+
for (let ci = 0; ci < cc; ci++) {
|
|
108
|
+
if (n >= maxCount)
|
|
109
|
+
break;
|
|
110
|
+
const d = this._drawBuf[n];
|
|
111
|
+
this._copyToEntry(d, p, pi);
|
|
112
|
+
if (childSpread > 0 && rng !== null) {
|
|
113
|
+
// Uniform sphere placement — 3 rng calls per child, no loops
|
|
114
|
+
const theta = rng.next() * 6.283185307;
|
|
115
|
+
const phi = Math.acos(1 - 2 * rng.next());
|
|
116
|
+
const r = childSpread * Math.cbrt(rng.next());
|
|
117
|
+
d.position.x = p.position.x + r * Math.sin(phi) * Math.cos(theta);
|
|
118
|
+
d.position.y = p.position.y + r * Math.sin(phi) * Math.sin(theta);
|
|
119
|
+
d.position.z = p.position.z + r * Math.cos(phi);
|
|
120
|
+
}
|
|
121
|
+
n++;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
// ── Interpolated children — lerp between consecutive alive parents ───
|
|
127
|
+
if (an === 0)
|
|
128
|
+
return 0;
|
|
129
|
+
let ai = 0;
|
|
130
|
+
for (let pi = 0; pi < pool.length; pi++) {
|
|
131
|
+
const p = pool[pi];
|
|
132
|
+
if (!p.alive)
|
|
133
|
+
continue;
|
|
134
|
+
if (n >= maxCount)
|
|
135
|
+
break;
|
|
136
|
+
// Write parent
|
|
137
|
+
this._copyToEntry(this._drawBuf[n], p, pi);
|
|
138
|
+
n++;
|
|
139
|
+
const nextAi = (ai + 1) % an;
|
|
140
|
+
const p1 = this._aliveBuf[nextAi];
|
|
141
|
+
// Write children interpolated between p and p1
|
|
142
|
+
for (let ci = 0; ci < cc; ci++) {
|
|
143
|
+
if (n >= maxCount)
|
|
144
|
+
break;
|
|
145
|
+
const t = (ci + 1) / (cc + 1);
|
|
146
|
+
const d = this._drawBuf[n];
|
|
147
|
+
d.position.x = p.position.x + (p1.position.x - p.position.x) * t;
|
|
148
|
+
d.position.y = p.position.y + (p1.position.y - p.position.y) * t;
|
|
149
|
+
d.position.z = p.position.z + (p1.position.z - p.position.z) * t;
|
|
150
|
+
d.velocity.x = p.velocity.x + (p1.velocity.x - p.velocity.x) * t;
|
|
151
|
+
d.velocity.y = p.velocity.y + (p1.velocity.y - p.velocity.y) * t;
|
|
152
|
+
d.velocity.z = p.velocity.z + (p1.velocity.z - p.velocity.z) * t;
|
|
153
|
+
d.rotation.x = p.rotation.x;
|
|
154
|
+
d.rotation.y = p.rotation.y;
|
|
155
|
+
d.rotation.z = p.rotation.z;
|
|
156
|
+
d.size = p.size + (p1.size - p.size) * t;
|
|
157
|
+
d.normalised = p.normalised + (p1.normalised - p.normalised) * t;
|
|
158
|
+
d.alive = true;
|
|
159
|
+
d.lifetime = p.lifetime;
|
|
160
|
+
d.age = p.age;
|
|
161
|
+
d.emitterIndex = p.emitterIndex;
|
|
162
|
+
d.poolIdx = pi;
|
|
163
|
+
n++;
|
|
164
|
+
}
|
|
165
|
+
ai++;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return n;
|
|
169
|
+
}
|
|
170
|
+
// ── Private helpers ───────────────────────────────────────────────────────
|
|
171
|
+
_copyToEntry(d, p, poolIdx) {
|
|
172
|
+
d.position.x = p.position.x;
|
|
173
|
+
d.position.y = p.position.y;
|
|
174
|
+
d.position.z = p.position.z;
|
|
175
|
+
d.velocity.x = p.velocity.x;
|
|
176
|
+
d.velocity.y = p.velocity.y;
|
|
177
|
+
d.velocity.z = p.velocity.z;
|
|
178
|
+
d.rotation.x = p.rotation.x;
|
|
179
|
+
d.rotation.y = p.rotation.y;
|
|
180
|
+
d.rotation.z = p.rotation.z;
|
|
181
|
+
d.size = p.size;
|
|
182
|
+
d.normalised = p.normalised;
|
|
183
|
+
d.alive = true;
|
|
184
|
+
d.lifetime = p.lifetime;
|
|
185
|
+
d.age = p.age;
|
|
186
|
+
d.emitterIndex = p.emitterIndex;
|
|
187
|
+
d.poolIdx = poolIdx;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=BaseRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseRenderer.js","sourceRoot":"","sources":["../../src/core/BaseRenderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { BufferGeometry, Vector3 } from 'three';
|
|
2
|
+
export interface DeflectorColliderOptions {
|
|
3
|
+
friction?: number;
|
|
4
|
+
damping?: number;
|
|
5
|
+
stiffness?: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* DeflectorCollider — mesh surface that bounces or kills particles on contact.
|
|
9
|
+
* (Blender: Physics → Collision panel)
|
|
10
|
+
*
|
|
11
|
+
* buildBVH() precomputes a flat triangle list (vertex A + face normal per tri).
|
|
12
|
+
* Called automatically on first use.
|
|
13
|
+
*/
|
|
14
|
+
export declare class DeflectorCollider {
|
|
15
|
+
/** All scalar inputs — GSAP / keyframe compatible (Blender-matched names) */
|
|
16
|
+
parameters: {
|
|
17
|
+
friction: number;
|
|
18
|
+
damping: number;
|
|
19
|
+
stiffness: number;
|
|
20
|
+
};
|
|
21
|
+
private _triangles;
|
|
22
|
+
private _triCount;
|
|
23
|
+
private _geometry;
|
|
24
|
+
private _built;
|
|
25
|
+
constructor(geometry: BufferGeometry, opts?: DeflectorColliderOptions);
|
|
26
|
+
/** Precompute triangle planes from geometry. Called automatically on first use. */
|
|
27
|
+
buildBVH(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Find the closest triangle plane to (px, py, pz).
|
|
30
|
+
* Returns true if any triangle is within parameters.stiffness × 0.5 world units.
|
|
31
|
+
*/
|
|
32
|
+
closestPoint(px: number, py: number, pz: number, out: {
|
|
33
|
+
point: Vector3;
|
|
34
|
+
normal: Vector3;
|
|
35
|
+
dist: number;
|
|
36
|
+
}): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Test whether the particle segment (prev → curr) crosses any triangle plane.
|
|
39
|
+
* radius (default 0) offsets the plane by the particle's collision radius so
|
|
40
|
+
* particles bounce before touching the surface (Blender: Size Deflect).
|
|
41
|
+
* Writes face normal and contact point to outNormal/outPoint on hit.
|
|
42
|
+
* Returns true if a crossing was detected.
|
|
43
|
+
*/
|
|
44
|
+
checkCrossing(prevX: number, prevY: number, prevZ: number, currX: number, currY: number, currZ: number, outNormal: Vector3, outPoint: Vector3, radius?: number): boolean;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=DeflectorCollider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeflectorCollider.d.ts","sourceRoot":"","sources":["../../src/core/DeflectorCollider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAE/C,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAG,MAAM,CAAA;IAClB,OAAO,CAAC,EAAI,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;GAMG;AACH,qBAAa,iBAAiB;IAC5B,6EAA6E;IAC7E,UAAU,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;IAEpE,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,SAAS,CAAI;IACrB,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,MAAM,CAAQ;gBAEV,QAAQ,EAAE,cAAc,EAAE,IAAI,GAAE,wBAA6B;IASzE,mFAAmF;IACnF,QAAQ,IAAI,IAAI;IA8ChB;;;OAGG;IACH,YAAY,CACV,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAClC,GAAG,EAAE;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GACrD,OAAO;IA2BV;;;;;;OAMG;IACH,aAAa,CACX,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAC3C,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAC3C,SAAS,EAAE,OAAO,EAClB,QAAQ,EAAG,OAAO,EAClB,MAAM,SAAI,GACT,OAAO;CAyBX"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { Vector3 } from 'three';
|
|
2
|
+
/**
|
|
3
|
+
* DeflectorCollider — mesh surface that bounces or kills particles on contact.
|
|
4
|
+
* (Blender: Physics → Collision panel)
|
|
5
|
+
*
|
|
6
|
+
* buildBVH() precomputes a flat triangle list (vertex A + face normal per tri).
|
|
7
|
+
* Called automatically on first use.
|
|
8
|
+
*/
|
|
9
|
+
export class DeflectorCollider {
|
|
10
|
+
constructor(geometry, opts = {}) {
|
|
11
|
+
this._triangles = new Float32Array(0); // [ax,ay,az,nx,ny,nz] per tri
|
|
12
|
+
this._triCount = 0;
|
|
13
|
+
this._built = false;
|
|
14
|
+
this._geometry = geometry;
|
|
15
|
+
this.parameters = {
|
|
16
|
+
friction: opts.friction ?? 0,
|
|
17
|
+
damping: opts.damping ?? 0.5,
|
|
18
|
+
stiffness: opts.stiffness ?? 1,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/** Precompute triangle planes from geometry. Called automatically on first use. */
|
|
22
|
+
buildBVH() {
|
|
23
|
+
const geo = this._geometry;
|
|
24
|
+
const pos = geo.getAttribute('position');
|
|
25
|
+
const idx = geo.getIndex();
|
|
26
|
+
if (!pos)
|
|
27
|
+
return;
|
|
28
|
+
let triCount;
|
|
29
|
+
let getVerts;
|
|
30
|
+
if (idx) {
|
|
31
|
+
triCount = Math.floor(idx.count / 3);
|
|
32
|
+
getVerts = (i) => [idx.getX(i * 3), idx.getX(i * 3 + 1), idx.getX(i * 3 + 2)];
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
triCount = Math.floor(pos.count / 3);
|
|
36
|
+
getVerts = (i) => [i * 3, i * 3 + 1, i * 3 + 2];
|
|
37
|
+
}
|
|
38
|
+
// 6 floats per triangle: vertex A (x,y,z) + face normal (x,y,z)
|
|
39
|
+
this._triangles = new Float32Array(triCount * 6);
|
|
40
|
+
this._triCount = triCount;
|
|
41
|
+
const vA = new Vector3(), vB = new Vector3(), vC = new Vector3();
|
|
42
|
+
const e1 = new Vector3(), e2 = new Vector3();
|
|
43
|
+
for (let i = 0; i < triCount; i++) {
|
|
44
|
+
const [a, b, c] = getVerts(i);
|
|
45
|
+
vA.fromBufferAttribute(pos, a);
|
|
46
|
+
vB.fromBufferAttribute(pos, b);
|
|
47
|
+
vC.fromBufferAttribute(pos, c);
|
|
48
|
+
e1.subVectors(vB, vA);
|
|
49
|
+
e2.subVectors(vC, vA);
|
|
50
|
+
const n = new Vector3().crossVectors(e1, e2).normalize();
|
|
51
|
+
const o = i * 6;
|
|
52
|
+
this._triangles[o] = vA.x;
|
|
53
|
+
this._triangles[o + 1] = vA.y;
|
|
54
|
+
this._triangles[o + 2] = vA.z;
|
|
55
|
+
this._triangles[o + 3] = n.x;
|
|
56
|
+
this._triangles[o + 4] = n.y;
|
|
57
|
+
this._triangles[o + 5] = n.z;
|
|
58
|
+
}
|
|
59
|
+
this._built = true;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Find the closest triangle plane to (px, py, pz).
|
|
63
|
+
* Returns true if any triangle is within parameters.stiffness × 0.5 world units.
|
|
64
|
+
*/
|
|
65
|
+
closestPoint(px, py, pz, out) {
|
|
66
|
+
if (!this._built)
|
|
67
|
+
this.buildBVH();
|
|
68
|
+
const threshold = this.parameters.stiffness * 0.5;
|
|
69
|
+
let minDist = Infinity;
|
|
70
|
+
let found = false;
|
|
71
|
+
for (let i = 0; i < this._triCount; i++) {
|
|
72
|
+
const o = i * 6;
|
|
73
|
+
const ax = this._triangles[o], ay = this._triangles[o + 1], az = this._triangles[o + 2];
|
|
74
|
+
const nx = this._triangles[o + 3], ny = this._triangles[o + 4], nz = this._triangles[o + 5];
|
|
75
|
+
const d = (px - ax) * nx + (py - ay) * ny + (pz - az) * nz;
|
|
76
|
+
const dist = Math.abs(d);
|
|
77
|
+
if (dist < threshold && dist < minDist) {
|
|
78
|
+
minDist = dist;
|
|
79
|
+
out.point.set(px - d * nx, py - d * ny, pz - d * nz);
|
|
80
|
+
out.normal.set(nx, ny, nz);
|
|
81
|
+
out.dist = dist;
|
|
82
|
+
found = true;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return found;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Test whether the particle segment (prev → curr) crosses any triangle plane.
|
|
89
|
+
* radius (default 0) offsets the plane by the particle's collision radius so
|
|
90
|
+
* particles bounce before touching the surface (Blender: Size Deflect).
|
|
91
|
+
* Writes face normal and contact point to outNormal/outPoint on hit.
|
|
92
|
+
* Returns true if a crossing was detected.
|
|
93
|
+
*/
|
|
94
|
+
checkCrossing(prevX, prevY, prevZ, currX, currY, currZ, outNormal, outPoint, radius = 0) {
|
|
95
|
+
if (!this._built)
|
|
96
|
+
this.buildBVH();
|
|
97
|
+
for (let i = 0; i < this._triCount; i++) {
|
|
98
|
+
const o = i * 6;
|
|
99
|
+
const ax = this._triangles[o], ay = this._triangles[o + 1], az = this._triangles[o + 2];
|
|
100
|
+
const nx = this._triangles[o + 3], ny = this._triangles[o + 4], nz = this._triangles[o + 5];
|
|
101
|
+
const dPrev = (prevX - ax) * nx + (prevY - ay) * ny + (prevZ - az) * nz;
|
|
102
|
+
const dCurr = (currX - ax) * nx + (currY - ay) * ny + (currZ - az) * nz;
|
|
103
|
+
if (dPrev >= radius && dCurr < radius) {
|
|
104
|
+
outNormal.set(nx, ny, nz);
|
|
105
|
+
// Project current position back to the offset contact plane
|
|
106
|
+
outPoint.set(currX - (dCurr - radius) * nx, currY - (dCurr - radius) * ny, currZ - (dCurr - radius) * nz);
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=DeflectorCollider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeflectorCollider.js","sourceRoot":"","sources":["../../src/core/DeflectorCollider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,OAAO,EAAE,MAAM,OAAO,CAAA;AAQ/C;;;;;;GAMG;AACH,MAAM,OAAO,iBAAiB;IAS5B,YAAY,QAAwB,EAAE,OAAiC,EAAE;QALjE,eAAU,GAAiB,IAAI,YAAY,CAAC,CAAC,CAAC,CAAA,CAAE,8BAA8B;QAC9E,cAAS,GAAG,CAAC,CAAA;QAEb,WAAM,GAAG,KAAK,CAAA;QAGpB,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAA;QACzB,IAAI,CAAC,UAAU,GAAG;YAChB,QAAQ,EAAG,IAAI,CAAC,QAAQ,IAAK,CAAC;YAC9B,OAAO,EAAI,IAAI,CAAC,OAAO,IAAM,GAAG;YAChC,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,CAAC;SAC/B,CAAA;IACH,CAAC;IAED,mFAAmF;IACnF,QAAQ;QACN,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAA;QAC1B,MAAM,GAAG,GAAG,GAAG,CAAC,YAAY,CAAC,UAAU,CAAC,CAAA;QACxC,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAA;QAC1B,IAAI,CAAC,GAAG;YAAE,OAAM;QAEhB,IAAI,QAAgB,CAAA;QACpB,IAAI,QAAiD,CAAA;QAErD,IAAI,GAAG,EAAE,CAAC;YACR,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;YACpC,QAAQ,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QAC/E,CAAC;aAAM,CAAC;YACN,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;YACpC,QAAQ,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;QACjD,CAAC;QAED,gEAAgE;QAChE,IAAI,CAAC,UAAU,GAAG,IAAI,YAAY,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAA;QAChD,IAAI,CAAC,SAAS,GAAI,QAAQ,CAAA;QAE1B,MAAM,EAAE,GAAG,IAAI,OAAO,EAAE,EAAE,EAAE,GAAG,IAAI,OAAO,EAAE,EAAE,EAAE,GAAG,IAAI,OAAO,EAAE,CAAA;QAChE,MAAM,EAAE,GAAI,IAAI,OAAO,EAAE,EAAE,EAAE,GAAI,IAAI,OAAO,EAAE,CAAA;QAE9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;YAClC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;YAC7B,EAAE,CAAC,mBAAmB,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;YAC9B,EAAE,CAAC,mBAAmB,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;YAC9B,EAAE,CAAC,mBAAmB,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;YAE9B,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;YACrB,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;YACrB,MAAM,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC,YAAY,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,SAAS,EAAE,CAAA;YAExD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACf,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAO,EAAE,CAAC,CAAC,CAAA;YAC7B,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;YAC7B,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;YAC7B,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;YAC5B,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;YAC5B,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QAC9B,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;IACpB,CAAC;IAED;;;OAGG;IACH,YAAY,CACV,EAAU,EAAE,EAAU,EAAE,EAAU,EAClC,GAAsD;QAEtD,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,QAAQ,EAAE,CAAA;QAEjC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,GAAG,GAAG,CAAA;QACjD,IAAI,OAAO,GAAG,QAAQ,CAAA;QACtB,IAAI,KAAK,GAAK,KAAK,CAAA;QAEnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,CAAC,GAAI,CAAC,GAAG,CAAC,CAAA;YAChB,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAM,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YAC3F,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YAE3F,MAAM,CAAC,GAAM,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,CAAA;YAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;YAExB,IAAI,IAAI,GAAG,SAAS,IAAI,IAAI,GAAG,OAAO,EAAE,CAAC;gBACvC,OAAO,GAAG,IAAI,CAAA;gBACd,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,GAAG,EAAE,EAAE,EAAE,GAAG,CAAC,GAAG,EAAE,EAAE,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,CAAA;gBACpD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;gBAC1B,GAAG,CAAC,IAAI,GAAG,IAAI,CAAA;gBACf,KAAK,GAAG,IAAI,CAAA;YACd,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAA;IACd,CAAC;IAED;;;;;;OAMG;IACH,aAAa,CACX,KAAa,EAAE,KAAa,EAAE,KAAa,EAC3C,KAAa,EAAE,KAAa,EAAE,KAAa,EAC3C,SAAkB,EAClB,QAAkB,EAClB,MAAM,GAAG,CAAC;QAEV,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,QAAQ,EAAE,CAAA;QAEjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,CAAC,GAAI,CAAC,GAAG,CAAC,CAAA;YAChB,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAM,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YAC3F,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YAE3F,MAAM,KAAK,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,EAAE,CAAA;YACvE,MAAM,KAAK,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,EAAE,CAAA;YAEvE,IAAI,KAAK,IAAI,MAAM,IAAI,KAAK,GAAG,MAAM,EAAE,CAAC;gBACtC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;gBACzB,4DAA4D;gBAC5D,QAAQ,CAAC,GAAG,CACV,KAAK,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,EAAE,EAC7B,KAAK,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,EAAE,EAC7B,KAAK,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,EAAE,CAC9B,CAAA;gBACD,OAAO,IAAI,CAAA;YACb,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAA;IACd,CAAC;CACF"}
|