@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,96 @@
|
|
|
1
|
+
import { LineSegments, BufferGeometry, BufferAttribute, LineBasicMaterial, Color, } from 'three';
|
|
2
|
+
import { BaseRenderer } from '../core/BaseRenderer.js';
|
|
3
|
+
/**
|
|
4
|
+
* LineRenderer — renders each particle as a velocity-aligned line segment.
|
|
5
|
+
* (Blender: Render → Line)
|
|
6
|
+
*/
|
|
7
|
+
export class LineRenderer extends BaseRenderer {
|
|
8
|
+
constructor(opts = {}) {
|
|
9
|
+
super();
|
|
10
|
+
const max = opts.maxCount ?? 10000;
|
|
11
|
+
this._maxCount = max;
|
|
12
|
+
const low = opts.colourLow ?? [1, 0, 0];
|
|
13
|
+
const high = opts.colourHigh ?? [0, 0, 1];
|
|
14
|
+
this.parameters = {
|
|
15
|
+
lengthScale: opts.lengthScale ?? 0.1,
|
|
16
|
+
opacity: 1,
|
|
17
|
+
colourMode: opts.colourMode ?? 0,
|
|
18
|
+
colourLowR: low[0], colourLowG: low[1], colourLowB: low[2],
|
|
19
|
+
colourHighR: high[0], colourHighG: high[1], colourHighB: high[2],
|
|
20
|
+
velocityMax: opts.velocityMax ?? 10,
|
|
21
|
+
};
|
|
22
|
+
// Each line = 2 vertices × 3 floats
|
|
23
|
+
this._positions = new Float32Array(max * 6);
|
|
24
|
+
this._colors = new Float32Array(max * 6); // 2 vertices × RGB
|
|
25
|
+
const geo = new BufferGeometry();
|
|
26
|
+
this._posAttr = new BufferAttribute(this._positions, 3).setUsage(35048);
|
|
27
|
+
this._colorAttr = new BufferAttribute(this._colors, 3).setUsage(35048);
|
|
28
|
+
geo.setAttribute('position', this._posAttr);
|
|
29
|
+
geo.setAttribute('color', this._colorAttr);
|
|
30
|
+
geo.setDrawRange(0, 0);
|
|
31
|
+
const mat = new LineBasicMaterial({
|
|
32
|
+
color: new Color(opts.color ?? 0xffffff),
|
|
33
|
+
transparent: true,
|
|
34
|
+
depthWrite: false,
|
|
35
|
+
});
|
|
36
|
+
this.object3D = new LineSegments(geo, mat);
|
|
37
|
+
this.object3D.frustumCulled = false;
|
|
38
|
+
this._allocDrawBuf(max);
|
|
39
|
+
}
|
|
40
|
+
update(particles, aliveCount, params, childRng) {
|
|
41
|
+
const childCount = params ? Math.round(Math.max(0, params.childCount ?? 0)) : 0;
|
|
42
|
+
const childType = params ? Math.round(params.childType ?? 0) : 0;
|
|
43
|
+
const childSpread = params ? (params.childSpread ?? 0.5) : 0.5;
|
|
44
|
+
const rawCount = this.expandWithChildren(particles, aliveCount, childCount, childType, childSpread, childRng ?? null, this._maxCount);
|
|
45
|
+
const displayAmount = params ? Math.min(1, Math.max(0, params.displayAmount ?? 1)) : 1;
|
|
46
|
+
const drawCount = displayAmount >= 1 ? rawCount : Math.round(rawCount * displayAmount);
|
|
47
|
+
const pr = this.parameters;
|
|
48
|
+
const ls = pr.lengthScale;
|
|
49
|
+
const mode = Math.round(pr.colourMode);
|
|
50
|
+
for (let i = 0; i < drawCount; i++) {
|
|
51
|
+
const p = this._drawBuf[i];
|
|
52
|
+
const i6 = i * 6;
|
|
53
|
+
// Tail (velocity direction behind particle)
|
|
54
|
+
this._positions[i6] = p.position.x - p.velocity.x * ls;
|
|
55
|
+
this._positions[i6 + 1] = p.position.y - p.velocity.y * ls;
|
|
56
|
+
this._positions[i6 + 2] = p.position.z - p.velocity.z * ls;
|
|
57
|
+
// Head (current position)
|
|
58
|
+
this._positions[i6 + 3] = p.position.x;
|
|
59
|
+
this._positions[i6 + 4] = p.position.y;
|
|
60
|
+
this._positions[i6 + 5] = p.position.z;
|
|
61
|
+
if (mode > 0) {
|
|
62
|
+
let t;
|
|
63
|
+
if (mode === 1) {
|
|
64
|
+
const spd = Math.sqrt(p.velocity.x * p.velocity.x +
|
|
65
|
+
p.velocity.y * p.velocity.y +
|
|
66
|
+
p.velocity.z * p.velocity.z);
|
|
67
|
+
t = Math.min(1, spd / Math.max(pr.velocityMax, 0.0001));
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
t = p.normalised;
|
|
71
|
+
}
|
|
72
|
+
const r = pr.colourLowR + (pr.colourHighR - pr.colourLowR) * t;
|
|
73
|
+
const g = pr.colourLowG + (pr.colourHighG - pr.colourLowG) * t;
|
|
74
|
+
const b = pr.colourLowB + (pr.colourHighB - pr.colourLowB) * t;
|
|
75
|
+
// Both tail and head vertices get the same colour
|
|
76
|
+
this._colors[i6] = r;
|
|
77
|
+
this._colors[i6 + 1] = g;
|
|
78
|
+
this._colors[i6 + 2] = b;
|
|
79
|
+
this._colors[i6 + 3] = r;
|
|
80
|
+
this._colors[i6 + 4] = g;
|
|
81
|
+
this._colors[i6 + 5] = b;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const mat = this.object3D.material;
|
|
85
|
+
mat.vertexColors = mode > 0;
|
|
86
|
+
this._posAttr.needsUpdate = true;
|
|
87
|
+
if (mode > 0)
|
|
88
|
+
this._colorAttr.needsUpdate = true;
|
|
89
|
+
this.object3D.geometry.setDrawRange(0, drawCount * 2);
|
|
90
|
+
}
|
|
91
|
+
dispose() {
|
|
92
|
+
this.object3D.geometry.dispose();
|
|
93
|
+
this.object3D.material.dispose();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=LineRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LineRenderer.js","sourceRoot":"","sources":["../../src/renderers/LineRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAAE,cAAc,EAAE,eAAe,EAC7C,iBAAiB,EAAE,KAAK,GACzB,MAAM,OAAO,CAAA;AACd,OAAO,EAAE,YAAY,EAAE,MAAY,yBAAyB,CAAA;AAmB5D;;;GAGG;AACH,MAAM,OAAO,YAAa,SAAQ,YAAY;IAuB5C,YAAY,OAA4B,EAAE;QACxC,KAAK,EAAE,CAAA;QACP,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAA;QAClC,IAAI,CAAC,SAAS,GAAG,GAAG,CAAA;QAEpB,MAAM,GAAG,GAAI,IAAI,CAAC,SAAS,IAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QAEzC,IAAI,CAAC,UAAU,GAAG;YAChB,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,GAAG;YACpC,OAAO,EAAM,CAAC;YACd,UAAU,EAAG,IAAI,CAAC,UAAU,IAAI,CAAC;YACjC,UAAU,EAAG,GAAG,CAAC,CAAC,CAAC,EAAG,UAAU,EAAG,GAAG,CAAC,CAAC,CAAC,EAAG,UAAU,EAAG,GAAG,CAAC,CAAC,CAAC;YAC/D,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;YAChE,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,EAAE;SACpC,CAAA;QAED,oCAAoC;QACpC,IAAI,CAAC,UAAU,GAAG,IAAI,YAAY,CAAC,GAAG,GAAG,CAAC,CAAC,CAAA;QAC3C,IAAI,CAAC,OAAO,GAAM,IAAI,YAAY,CAAC,GAAG,GAAG,CAAC,CAAC,CAAA,CAAG,mBAAmB;QACjE,MAAM,GAAG,GAAG,IAAI,cAAc,EAAE,CAAA;QAChC,IAAI,CAAC,QAAQ,GAAK,IAAI,eAAe,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;QACzE,IAAI,CAAC,UAAU,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,OAAO,EAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;QACzE,GAAG,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QAC3C,GAAG,CAAC,YAAY,CAAC,OAAO,EAAK,IAAI,CAAC,UAAU,CAAC,CAAA;QAC7C,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;QAEtB,MAAM,GAAG,GAAG,IAAI,iBAAiB,CAAC;YAChC,KAAK,EAAQ,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC;YAC9C,WAAW,EAAE,IAAI;YACjB,UAAU,EAAG,KAAK;SACnB,CAAC,CAAA;QAEF,IAAI,CAAC,QAAQ,GAAG,IAAI,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;QAC1C,IAAI,CAAC,QAAQ,CAAC,aAAa,GAAG,KAAK,CAAA;QAEnC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAA;IACzB,CAAC;IAED,MAAM,CACJ,SAAyB,EACzB,UAAkB,EAClB,MAAkC,EAClC,QAAwB;QAExB,MAAM,UAAU,GAAI,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,UAAU,IAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QACjF,MAAM,SAAS,GAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,IAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QACpE,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;QAE9D,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CACtC,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EACzD,QAAQ,IAAI,IAAI,EAAE,IAAI,CAAC,SAAS,CACjC,CAAA;QAED,MAAM,aAAa,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,aAAa,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QACtF,MAAM,SAAS,GAAG,aAAa,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,aAAa,CAAC,CAAA;QAEtF,MAAM,EAAE,GAAK,IAAI,CAAC,UAAU,CAAA;QAC5B,MAAM,EAAE,GAAK,EAAE,CAAC,WAAW,CAAA;QAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,UAAU,CAAC,CAAA;QAEtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;YACnC,MAAM,CAAC,GAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;YAC3B,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAA;YAChB,4CAA4C;YAC5C,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,GAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAA;YAC1D,IAAI,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAA;YAC1D,IAAI,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAA;YAC1D,0BAA0B;YAC1B,IAAI,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAA;YACtC,IAAI,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAA;YACtC,IAAI,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAA;YAEtC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;gBACb,IAAI,CAAS,CAAA;gBACb,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;oBACf,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CACnB,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;wBAC3B,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;wBAC3B,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAC5B,CAAA;oBACD,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAA;gBACzD,CAAC;qBAAM,CAAC;oBACN,CAAC,GAAG,CAAC,CAAC,UAAU,CAAA;gBAClB,CAAC;gBACD,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC,WAAW,GAAG,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;gBAC9D,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC,WAAW,GAAG,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;gBAC9D,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC,WAAW,GAAG,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;gBAC9D,kDAAkD;gBAClD,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,GAAO,CAAC,CAAC;gBAAC,IAAI,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;gBAAC,IAAI,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAA;gBAC5E,IAAI,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;gBAAC,IAAI,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;gBAAC,IAAI,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAA;YAC9E,CAAC;QACH,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,QAA6B,CAAA;QACvD,GAAG,CAAC,YAAY,GAAG,IAAI,GAAG,CAAC,CAAA;QAE3B,IAAI,CAAC,QAAQ,CAAC,WAAW,GAAG,IAAI,CAAA;QAChC,IAAI,IAAI,GAAG,CAAC;YAAE,IAAI,CAAC,UAAU,CAAC,WAAW,GAAG,IAAI,CAC/C;QAAC,IAAI,CAAC,QAAQ,CAAC,QAA2B,CAAC,YAAY,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,CAAA;IAC5E,CAAC;IAED,OAAO;QACL,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,CAC/B;QAAC,IAAI,CAAC,QAAQ,CAAC,QAA8B,CAAC,OAAO,EAAE,CAAA;IAC1D,CAAC;CACF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Object3D } from 'three';
|
|
2
|
+
import { BaseRenderer } from '../core/BaseRenderer.js';
|
|
3
|
+
import type { ParticleLike } from '../core/BaseRenderer.js';
|
|
4
|
+
import type { SeededRandom } from '../core/SeededRandom.js';
|
|
5
|
+
/**
|
|
6
|
+
* NoneRenderer — invisible particle renderer.
|
|
7
|
+
* Blender: Render → None.
|
|
8
|
+
*
|
|
9
|
+
* Useful when particles drive physics/emitters but should not be drawn,
|
|
10
|
+
* e.g. when particles spawn child systems or are consumed by a fluid sim.
|
|
11
|
+
*/
|
|
12
|
+
export declare class NoneRenderer extends BaseRenderer {
|
|
13
|
+
readonly object3D: Object3D;
|
|
14
|
+
parameters: Record<string, number>;
|
|
15
|
+
constructor();
|
|
16
|
+
update(_particles: ParticleLike[], _aliveCount: number, _params?: Record<string, number>, _rng?: SeededRandom): void;
|
|
17
|
+
dispose(): void;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=NoneRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NoneRenderer.d.ts","sourceRoot":"","sources":["../../src/renderers/NoneRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAS,OAAO,CAAA;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAE3D;;;;;;GAMG;AACH,qBAAa,YAAa,SAAQ,YAAY;IAC5C,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAiB;IAC5C,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAK;;IAOvC,MAAM,CAAC,UAAU,EAAE,YAAY,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,IAAI;IAIpH,OAAO,IAAI,IAAI;CAGhB"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Object3D } from 'three';
|
|
2
|
+
import { BaseRenderer } from '../core/BaseRenderer.js';
|
|
3
|
+
/**
|
|
4
|
+
* NoneRenderer — invisible particle renderer.
|
|
5
|
+
* Blender: Render → None.
|
|
6
|
+
*
|
|
7
|
+
* Useful when particles drive physics/emitters but should not be drawn,
|
|
8
|
+
* e.g. when particles spawn child systems or are consumed by a fluid sim.
|
|
9
|
+
*/
|
|
10
|
+
export class NoneRenderer extends BaseRenderer {
|
|
11
|
+
constructor() {
|
|
12
|
+
super();
|
|
13
|
+
this.object3D = new Object3D();
|
|
14
|
+
this.parameters = {};
|
|
15
|
+
this.object3D.visible = false;
|
|
16
|
+
}
|
|
17
|
+
update(_particles, _aliveCount, _params, _rng) {
|
|
18
|
+
// intentionally empty — no visual output
|
|
19
|
+
}
|
|
20
|
+
dispose() {
|
|
21
|
+
// nothing to clean up
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=NoneRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NoneRenderer.js","sourceRoot":"","sources":["../../src/renderers/NoneRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAS,OAAO,CAAA;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAItD;;;;;;GAMG;AACH,MAAM,OAAO,YAAa,SAAQ,YAAY;IAI5C;QACE,KAAK,EAAE,CAAA;QAJA,aAAQ,GAAa,IAAI,QAAQ,EAAE,CAAA;QAC5C,eAAU,GAA2B,EAAE,CAAA;QAIrC,IAAI,CAAC,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAA;IAC/B,CAAC;IAED,MAAM,CAAC,UAA0B,EAAE,WAAmB,EAAE,OAAgC,EAAE,IAAmB;QAC3G,yCAAyC;IAC3C,CAAC;IAED,OAAO;QACL,sBAAsB;IACxB,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ObjectRenderer.d.ts","sourceRoot":"","sources":["../../src/renderers/ObjectRenderer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,IAAI,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAC1E,YAAY,EAAE,uBAAuB,IAAI,qBAAqB,EAAE,MAAM,uBAAuB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ObjectRenderer.js","sourceRoot":"","sources":["../../src/renderers/ObjectRenderer.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,2EAA2E;AAC3E,OAAO,EAAE,gBAAgB,IAAI,cAAc,EAAE,MAAM,uBAAuB,CAAA"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { Group, LineBasicMaterial, MeshBasicMaterial } from 'three';
|
|
2
|
+
import { BaseRenderer } from '../core/BaseRenderer.js';
|
|
3
|
+
import type { ParticleLike } from '../core/BaseRenderer.js';
|
|
4
|
+
import type { SeededRandom } from '../core/SeededRandom.js';
|
|
5
|
+
/** Source geometry with optional vertex-group float attributes. */
|
|
6
|
+
export interface StrandSourceGeometry {
|
|
7
|
+
getAttribute(name: string): {
|
|
8
|
+
getX(i: number): number;
|
|
9
|
+
} | undefined;
|
|
10
|
+
}
|
|
11
|
+
export type StrandCurveFn = (particle: ParticleLike, t: number, // 0 = root, 1 = tip
|
|
12
|
+
index: number) => {
|
|
13
|
+
x: number;
|
|
14
|
+
y: number;
|
|
15
|
+
z: number;
|
|
16
|
+
};
|
|
17
|
+
export type StrandRenderMode = 'line' | 'tube';
|
|
18
|
+
export interface StrandRendererOptions {
|
|
19
|
+
/**
|
|
20
|
+
* Maximum number of live strands. Default 1000.
|
|
21
|
+
* Set to the particle system's `count` for best results.
|
|
22
|
+
*/
|
|
23
|
+
maxCount?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Number of segments per strand. Default 8.
|
|
26
|
+
* More segments = smoother curves, higher GPU cost.
|
|
27
|
+
*/
|
|
28
|
+
segments?: number;
|
|
29
|
+
/**
|
|
30
|
+
* Strand cross-section radius for 'tube' mode. Default 0.02.
|
|
31
|
+
* Blender: Hair Shape → Diameter Root
|
|
32
|
+
*/
|
|
33
|
+
thickness?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Tip taper factor [0–1]. 1 = uniform, 0 = taper to point. Default 0.5.
|
|
36
|
+
* Blender: Hair Shape → Taper
|
|
37
|
+
*/
|
|
38
|
+
taper?: number;
|
|
39
|
+
/**
|
|
40
|
+
* How strands are rendered.
|
|
41
|
+
* 'line' (default) — fast LineSegments, thickness controlled by material.
|
|
42
|
+
* 'tube' — mesh tube, supports lighting. Heavier, best for hero strands.
|
|
43
|
+
*/
|
|
44
|
+
mode?: StrandRenderMode;
|
|
45
|
+
/**
|
|
46
|
+
* Function that returns a world-space point along the strand at normalised t ∈ [0,1].
|
|
47
|
+
* t=0 = root (particle position), t=1 = tip.
|
|
48
|
+
*
|
|
49
|
+
* Default: straight strand drooping 1 world unit downward along gravity.
|
|
50
|
+
*
|
|
51
|
+
* To connect with st-hair-core:
|
|
52
|
+
* const gen = new StrandGenerator({ ... })
|
|
53
|
+
* renderer = new StrandRenderer({
|
|
54
|
+
* strandCurve: (p, t) => gen.evaluateAt(p.position, p.velocity, t)
|
|
55
|
+
* })
|
|
56
|
+
*/
|
|
57
|
+
strandCurve?: StrandCurveFn;
|
|
58
|
+
/** Material for the strands. Default: white LineBasicMaterial or MeshBasicMaterial. */
|
|
59
|
+
material?: LineBasicMaterial | MeshBasicMaterial;
|
|
60
|
+
/**
|
|
61
|
+
* Source geometry to read vertex-group float attributes from.
|
|
62
|
+
* The particle's `poolIdx` is used as the vertex index.
|
|
63
|
+
* Blender: Vertex Groups → Strand panel.
|
|
64
|
+
*/
|
|
65
|
+
sourceGeometry?: StrandSourceGeometry;
|
|
66
|
+
/**
|
|
67
|
+
* Name of a float vertex attribute on `sourceGeometry` whose value [0–1]
|
|
68
|
+
* scales each strand's length multiplier. 0 = no strand, 1 = full length.
|
|
69
|
+
* Blender: Vertex Groups → Length.
|
|
70
|
+
*/
|
|
71
|
+
lengthAttribute?: string;
|
|
72
|
+
/**
|
|
73
|
+
* Name of a float vertex attribute on `sourceGeometry` whose value [0–1]
|
|
74
|
+
* offsets the strand root toward the emitter surface centre (clumping).
|
|
75
|
+
* Blender: Vertex Groups → Clump.
|
|
76
|
+
*/
|
|
77
|
+
clumpAttribute?: string;
|
|
78
|
+
/**
|
|
79
|
+
* Name of a float vertex attribute on `sourceGeometry` whose value [0–1]
|
|
80
|
+
* scales the kink amplitude for this strand.
|
|
81
|
+
* Blender: Vertex Groups → Roughness.
|
|
82
|
+
*/
|
|
83
|
+
roughnessAttribute?: string;
|
|
84
|
+
/**
|
|
85
|
+
* Viewport display fraction [0–1]. Default 1 (show all).
|
|
86
|
+
* 0.5 shows 50% of strands in the viewport without affecting simulation.
|
|
87
|
+
* Blender: Display panel → Display Amount.
|
|
88
|
+
*/
|
|
89
|
+
displayAmount?: number;
|
|
90
|
+
/**
|
|
91
|
+
* Optional callback that returns the world-space tangent direction at
|
|
92
|
+
* a normalised position t along the strand.
|
|
93
|
+
* Used to drive anisotropic shading in tube mode (e.g. PrincipledHair node).
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* // Connect with st-hair-core StrandGenerator
|
|
97
|
+
* const gen = new StrandGenerator({ ... })
|
|
98
|
+
* new StrandRenderer({
|
|
99
|
+
* tangentFn: (particle, t) => gen.tangentAt(particle.position, particle.velocity, t)
|
|
100
|
+
* })
|
|
101
|
+
*/
|
|
102
|
+
tangentFn?: (particle: ParticleLike, t: number) => {
|
|
103
|
+
x: number;
|
|
104
|
+
y: number;
|
|
105
|
+
z: number;
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* StrandRenderer — Blender: Hair / Path render type on a particle system.
|
|
110
|
+
*
|
|
111
|
+
* Renders each alive particle as a strand (hair, grass, fur).
|
|
112
|
+
* The strand shape is defined by a `strandCurve` callback — this allows
|
|
113
|
+
* integration with st-hair-core's StrandGenerator without a hard import.
|
|
114
|
+
*
|
|
115
|
+
* Usage:
|
|
116
|
+
* ```typescript
|
|
117
|
+
* const renderer = new StrandRenderer({
|
|
118
|
+
* maxCount: 500,
|
|
119
|
+
* segments: 8,
|
|
120
|
+
* strandCurve: (p, t) => ({
|
|
121
|
+
* x: p.position.x,
|
|
122
|
+
* y: p.position.y + t * 0.3,
|
|
123
|
+
* z: p.position.z,
|
|
124
|
+
* })
|
|
125
|
+
* })
|
|
126
|
+
* sys.setRenderer(renderer)
|
|
127
|
+
* scene.add(renderer.object3D)
|
|
128
|
+
* ```
|
|
129
|
+
*
|
|
130
|
+
* To use st-hair-core strand shapes, pass a generator callback:
|
|
131
|
+
* ```typescript
|
|
132
|
+
* // Outside st-particle-core — no import restriction applies here
|
|
133
|
+
* import { StrandGenerator } from 'st-hair-core'
|
|
134
|
+
* const gen = new StrandGenerator({ length: 0.4, gravity: 0.3 })
|
|
135
|
+
* const renderer = new StrandRenderer({
|
|
136
|
+
* strandCurve: (p, t) => gen.samplePoint(p.position, p.velocity, t)
|
|
137
|
+
* })
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
export declare class StrandRenderer extends BaseRenderer {
|
|
141
|
+
parameters: Record<string, number>;
|
|
142
|
+
readonly object3D: Group;
|
|
143
|
+
private readonly _segments;
|
|
144
|
+
private readonly _maxCount;
|
|
145
|
+
private readonly _mode;
|
|
146
|
+
private readonly _strandCurve;
|
|
147
|
+
private readonly _material;
|
|
148
|
+
private readonly _sourceGeo;
|
|
149
|
+
private readonly _lengthAttrName;
|
|
150
|
+
private readonly _clumpAttrName;
|
|
151
|
+
private readonly _roughnessAttrName;
|
|
152
|
+
private readonly _tangentFn;
|
|
153
|
+
private _lineGeo;
|
|
154
|
+
private _lineSegs;
|
|
155
|
+
private _linePosArr;
|
|
156
|
+
private _tubeMeshes;
|
|
157
|
+
private _tubeInScene;
|
|
158
|
+
constructor(opts?: StrandRendererOptions);
|
|
159
|
+
update(particles: ParticleLike[], aliveCount: number, params?: Record<string, number>, childRng?: SeededRandom): void;
|
|
160
|
+
dispose(): void;
|
|
161
|
+
private _initLineGeometry;
|
|
162
|
+
private _updateLine;
|
|
163
|
+
private _initTubePool;
|
|
164
|
+
private _updateTubes;
|
|
165
|
+
/** Read a float attribute value at vertex index `vi`; returns 1 if unavailable. */
|
|
166
|
+
private _attrVal;
|
|
167
|
+
private static _defaultCurve;
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=StrandRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StrandRenderer.d.ts","sourceRoot":"","sources":["../../src/renderers/StrandRenderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { Group, LineSegments, LineBasicMaterial, BufferGeometry, BufferAttribute, MeshBasicMaterial, Mesh, TubeGeometry, CatmullRomCurve3, Vector3, } from 'three';
|
|
2
|
+
import { BaseRenderer } from '../core/BaseRenderer.js';
|
|
3
|
+
/**
|
|
4
|
+
* StrandRenderer — Blender: Hair / Path render type on a particle system.
|
|
5
|
+
*
|
|
6
|
+
* Renders each alive particle as a strand (hair, grass, fur).
|
|
7
|
+
* The strand shape is defined by a `strandCurve` callback — this allows
|
|
8
|
+
* integration with st-hair-core's StrandGenerator without a hard import.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const renderer = new StrandRenderer({
|
|
13
|
+
* maxCount: 500,
|
|
14
|
+
* segments: 8,
|
|
15
|
+
* strandCurve: (p, t) => ({
|
|
16
|
+
* x: p.position.x,
|
|
17
|
+
* y: p.position.y + t * 0.3,
|
|
18
|
+
* z: p.position.z,
|
|
19
|
+
* })
|
|
20
|
+
* })
|
|
21
|
+
* sys.setRenderer(renderer)
|
|
22
|
+
* scene.add(renderer.object3D)
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* To use st-hair-core strand shapes, pass a generator callback:
|
|
26
|
+
* ```typescript
|
|
27
|
+
* // Outside st-particle-core — no import restriction applies here
|
|
28
|
+
* import { StrandGenerator } from 'st-hair-core'
|
|
29
|
+
* const gen = new StrandGenerator({ length: 0.4, gravity: 0.3 })
|
|
30
|
+
* const renderer = new StrandRenderer({
|
|
31
|
+
* strandCurve: (p, t) => gen.samplePoint(p.position, p.velocity, t)
|
|
32
|
+
* })
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export class StrandRenderer extends BaseRenderer {
|
|
36
|
+
constructor(opts = {}) {
|
|
37
|
+
super();
|
|
38
|
+
// Line mode geometry — one pre-allocated geometry updated in place
|
|
39
|
+
this._lineGeo = null;
|
|
40
|
+
this._lineSegs = null;
|
|
41
|
+
this._linePosArr = null;
|
|
42
|
+
// Tube mode — one Mesh per strand, pooled
|
|
43
|
+
this._tubeMeshes = [];
|
|
44
|
+
this._tubeInScene = [];
|
|
45
|
+
this._maxCount = opts.maxCount ?? 1000;
|
|
46
|
+
this._segments = opts.segments ?? 8;
|
|
47
|
+
this._mode = opts.mode ?? 'line';
|
|
48
|
+
this._strandCurve = opts.strandCurve ?? StrandRenderer._defaultCurve;
|
|
49
|
+
this._sourceGeo = opts.sourceGeometry ?? null;
|
|
50
|
+
this._lengthAttrName = opts.lengthAttribute ?? null;
|
|
51
|
+
this._clumpAttrName = opts.clumpAttribute ?? null;
|
|
52
|
+
this._roughnessAttrName = opts.roughnessAttribute ?? null;
|
|
53
|
+
this._tangentFn = opts.tangentFn ?? null;
|
|
54
|
+
this._material = opts.material ?? (this._mode === 'tube'
|
|
55
|
+
? new MeshBasicMaterial({ color: 0xccaa77 })
|
|
56
|
+
: new LineBasicMaterial({ color: 0xccaa77 }));
|
|
57
|
+
this._allocDrawBuf(this._maxCount);
|
|
58
|
+
this.object3D = new Group();
|
|
59
|
+
this.parameters = {
|
|
60
|
+
thickness: opts.thickness ?? 0.02,
|
|
61
|
+
taper: opts.taper ?? 0.5,
|
|
62
|
+
segments: this._segments,
|
|
63
|
+
kinkAmplitude: 0, // wave displacement — Blender: Kink → Amplitude
|
|
64
|
+
kinkFrequency: 1, // waves per strand — Blender: Kink → Frequency
|
|
65
|
+
densityThreshold: 0, // skip strands where particle.size < this value
|
|
66
|
+
displayAmount: opts.displayAmount ?? 1.0, // fraction of strands shown [0–1]
|
|
67
|
+
};
|
|
68
|
+
if (this._mode === 'line') {
|
|
69
|
+
this._initLineGeometry();
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
this._initTubePool();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
update(particles, aliveCount, params, childRng) {
|
|
76
|
+
const n = this.expandWithChildren(particles, aliveCount, params?.childCount ?? 0, params?.childType ?? 0, params?.childSpread ?? 0.5, childRng ?? null, this._maxCount);
|
|
77
|
+
if (this._mode === 'line') {
|
|
78
|
+
this._updateLine(n);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
this._updateTubes(n);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
dispose() {
|
|
85
|
+
this._lineGeo?.dispose();
|
|
86
|
+
this._material.dispose();
|
|
87
|
+
for (const m of this._tubeMeshes)
|
|
88
|
+
m.geometry.dispose();
|
|
89
|
+
}
|
|
90
|
+
// ── Line mode ─────────────────────────────────────────────────────────────
|
|
91
|
+
_initLineGeometry() {
|
|
92
|
+
// Each strand = _segments segments = _segments+1 points = _segments*2 line endpoints
|
|
93
|
+
const pointsPerStrand = this._segments + 1;
|
|
94
|
+
const totalPoints = this._maxCount * pointsPerStrand;
|
|
95
|
+
this._linePosArr = new Float32Array(totalPoints * 3);
|
|
96
|
+
this._lineGeo = new BufferGeometry();
|
|
97
|
+
this._lineGeo.setAttribute('position', new BufferAttribute(this._linePosArr, 3));
|
|
98
|
+
// Build index: pairs of consecutive points per strand
|
|
99
|
+
const indices = [];
|
|
100
|
+
for (let s = 0; s < this._maxCount; s++) {
|
|
101
|
+
const base = s * pointsPerStrand;
|
|
102
|
+
for (let seg = 0; seg < this._segments; seg++) {
|
|
103
|
+
indices.push(base + seg, base + seg + 1);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
this._lineGeo.setIndex(indices);
|
|
107
|
+
this._lineSegs = new LineSegments(this._lineGeo, this._material);
|
|
108
|
+
this.object3D.add(this._lineSegs);
|
|
109
|
+
}
|
|
110
|
+
_updateLine(count) {
|
|
111
|
+
const arr = this._linePosArr;
|
|
112
|
+
const segs = this._segments;
|
|
113
|
+
const pps = segs + 1; // points per strand
|
|
114
|
+
const threshold = this.parameters.densityThreshold;
|
|
115
|
+
const displayMax = Math.round(count * Math.max(0, Math.min(1, this.parameters.displayAmount)));
|
|
116
|
+
for (let i = 0; i < count; i++) {
|
|
117
|
+
const d = this._drawBuf[i];
|
|
118
|
+
const base = i * pps * 3;
|
|
119
|
+
// Skip beyond displayAmount or low-weight strands
|
|
120
|
+
if (i >= displayMax || (threshold > 0 && d.size < threshold)) {
|
|
121
|
+
for (let j = 0; j < pps * 3; j++)
|
|
122
|
+
arr[base + j] = 0;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
const lengthScale = this._attrVal(this._lengthAttrName, d.poolIdx);
|
|
126
|
+
const clumpScale = this._attrVal(this._clumpAttrName, d.poolIdx);
|
|
127
|
+
const roughnessScale = this._attrVal(this._roughnessAttrName, d.poolIdx);
|
|
128
|
+
const kinkAmp = this.parameters.kinkAmplitude * roughnessScale;
|
|
129
|
+
const kinkFreq = this.parameters.kinkFrequency;
|
|
130
|
+
for (let j = 0; j <= segs; j++) {
|
|
131
|
+
const t = (j / segs) * lengthScale;
|
|
132
|
+
const pt = this._strandCurve(d, t, d.poolIdx);
|
|
133
|
+
const kink = kinkAmp > 0 ? Math.sin(t * kinkFreq * Math.PI * 2) * kinkAmp * t : 0;
|
|
134
|
+
const clumpX = (d.position.x - pt.x) * (1 - clumpScale);
|
|
135
|
+
const clumpZ = (d.position.z - pt.z) * (1 - clumpScale);
|
|
136
|
+
const off = base + j * 3;
|
|
137
|
+
arr[off] = pt.x + kink + clumpX;
|
|
138
|
+
arr[off + 1] = pt.y;
|
|
139
|
+
arr[off + 2] = pt.z + kink * 0.5 + clumpZ;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Zero out unused strands
|
|
143
|
+
for (let i = count; i < this._maxCount; i++) {
|
|
144
|
+
const base = i * pps * 3;
|
|
145
|
+
for (let j = 0; j < pps * 3; j++)
|
|
146
|
+
arr[base + j] = 0;
|
|
147
|
+
}
|
|
148
|
+
this._lineGeo.getAttribute('position').needsUpdate = true;
|
|
149
|
+
this._lineGeo.computeBoundingSphere();
|
|
150
|
+
}
|
|
151
|
+
// ── Tube mode ─────────────────────────────────────────────────────────────
|
|
152
|
+
_initTubePool() {
|
|
153
|
+
for (let i = 0; i < this._maxCount; i++) {
|
|
154
|
+
// Placeholder geometry — replaced each update
|
|
155
|
+
const geo = new BufferGeometry();
|
|
156
|
+
const mesh = new Mesh(geo, this._material);
|
|
157
|
+
mesh.visible = false;
|
|
158
|
+
this._tubeMeshes.push(mesh);
|
|
159
|
+
this._tubeInScene.push(false);
|
|
160
|
+
this.object3D.add(mesh);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
_updateTubes(count) {
|
|
164
|
+
const segs = this._segments;
|
|
165
|
+
const thickness = this.parameters.thickness;
|
|
166
|
+
const taper = this.parameters.taper;
|
|
167
|
+
const threshold = this.parameters.densityThreshold;
|
|
168
|
+
const displayMax = Math.round(count * Math.max(0, Math.min(1, this.parameters.displayAmount)));
|
|
169
|
+
for (let i = 0; i < count; i++) {
|
|
170
|
+
const d = this._drawBuf[i];
|
|
171
|
+
const mesh = this._tubeMeshes[i];
|
|
172
|
+
if (i >= displayMax || (threshold > 0 && d.size < threshold)) {
|
|
173
|
+
mesh.visible = false;
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
const lengthScale = this._attrVal(this._lengthAttrName, d.poolIdx);
|
|
177
|
+
const clumpScale = this._attrVal(this._clumpAttrName, d.poolIdx);
|
|
178
|
+
const roughnessScale = this._attrVal(this._roughnessAttrName, d.poolIdx);
|
|
179
|
+
const kinkAmp = this.parameters.kinkAmplitude * roughnessScale;
|
|
180
|
+
const kinkFreq = this.parameters.kinkFrequency;
|
|
181
|
+
const pts = [];
|
|
182
|
+
for (let j = 0; j <= segs; j++) {
|
|
183
|
+
const t = (j / segs) * lengthScale;
|
|
184
|
+
const pt = this._strandCurve(d, t, d.poolIdx);
|
|
185
|
+
const kink = kinkAmp > 0 ? Math.sin(t * kinkFreq * Math.PI * 2) * kinkAmp * t : 0;
|
|
186
|
+
const clumpX = (d.position.x - pt.x) * (1 - clumpScale);
|
|
187
|
+
const clumpZ = (d.position.z - pt.z) * (1 - clumpScale);
|
|
188
|
+
pts.push(new Vector3(pt.x + kink + clumpX, pt.y, pt.z + kink * 0.5 + clumpZ));
|
|
189
|
+
}
|
|
190
|
+
// Build tube geometry along the curve
|
|
191
|
+
const curve = new CatmullRomCurve3(pts);
|
|
192
|
+
const radiusFn = (t) => thickness * (1 - t * (1 - taper));
|
|
193
|
+
const tubeRadius = thickness; // TubeGeometry doesn't support per-point radius
|
|
194
|
+
void radiusFn;
|
|
195
|
+
mesh.geometry.dispose();
|
|
196
|
+
const geo = new TubeGeometry(curve, segs, tubeRadius * taper, 4, false);
|
|
197
|
+
// Bake tangent attribute for anisotropic shading (PrincipledHair / HairInfo node)
|
|
198
|
+
if (this._tangentFn) {
|
|
199
|
+
const vtxCount = geo.attributes.position.count;
|
|
200
|
+
const tangents = new Float32Array(vtxCount * 3);
|
|
201
|
+
for (let vi = 0; vi < vtxCount; vi++) {
|
|
202
|
+
const t = (vi / vtxCount);
|
|
203
|
+
const tv = this._tangentFn(d, t);
|
|
204
|
+
tangents[vi * 3] = tv.x;
|
|
205
|
+
tangents[vi * 3 + 1] = tv.y;
|
|
206
|
+
tangents[vi * 3 + 2] = tv.z;
|
|
207
|
+
}
|
|
208
|
+
geo.setAttribute('strandTangent', new BufferAttribute(tangents, 3));
|
|
209
|
+
}
|
|
210
|
+
mesh.geometry = geo;
|
|
211
|
+
mesh.visible = true;
|
|
212
|
+
}
|
|
213
|
+
// Hide unused
|
|
214
|
+
for (let i = count; i < this._maxCount; i++) {
|
|
215
|
+
this._tubeMeshes[i].visible = false;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
// ── Vertex group attribute helpers ───────────────────────────────────────
|
|
219
|
+
/** Read a float attribute value at vertex index `vi`; returns 1 if unavailable. */
|
|
220
|
+
_attrVal(attrName, vi) {
|
|
221
|
+
if (!attrName || !this._sourceGeo)
|
|
222
|
+
return 1;
|
|
223
|
+
const attr = this._sourceGeo.getAttribute(attrName);
|
|
224
|
+
if (!attr)
|
|
225
|
+
return 1;
|
|
226
|
+
return attr.getX(vi);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
// ── Default strand curve ──────────────────────────────────────────────────
|
|
230
|
+
StrandRenderer._defaultCurve = (p, t) => ({
|
|
231
|
+
x: p.position.x,
|
|
232
|
+
y: p.position.y + t * p.size * 5, // strand grows upward from particle
|
|
233
|
+
z: p.position.z,
|
|
234
|
+
});
|
|
235
|
+
//# sourceMappingURL=StrandRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StrandRenderer.js","sourceRoot":"","sources":["../../src/renderers/StrandRenderer.ts"],"names":[],"mappings":"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"}
|