@flighthq/particles 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/applyParticleCollisions.d.ts +12 -0
- package/dist/applyParticleCollisions.d.ts.map +1 -0
- package/dist/applyParticleCollisions.js +175 -0
- package/dist/applyParticleCollisions.js.map +1 -0
- package/dist/applyParticleForces.d.ts +13 -0
- package/dist/applyParticleForces.d.ts.map +1 -0
- package/dist/applyParticleForces.js +129 -0
- package/dist/applyParticleForces.js.map +1 -0
- package/dist/curve.d.ts +35 -0
- package/dist/curve.d.ts.map +1 -0
- package/dist/curve.js +227 -0
- package/dist/curve.js.map +1 -0
- package/dist/emitParticleBurst.d.ts +15 -0
- package/dist/emitParticleBurst.d.ts.map +1 -0
- package/dist/emitParticleBurst.js +114 -0
- package/dist/emitParticleBurst.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/particleEmitterConfig.d.ts +4 -0
- package/dist/particleEmitterConfig.d.ts.map +1 -0
- package/dist/particleEmitterConfig.js +53 -0
- package/dist/particleEmitterConfig.js.map +1 -0
- package/dist/particleEmitterSignals.d.ts +20 -0
- package/dist/particleEmitterSignals.d.ts.map +1 -0
- package/dist/particleEmitterSignals.js +33 -0
- package/dist/particleEmitterSignals.js.map +1 -0
- package/dist/particleEmitterState.d.ts +7 -0
- package/dist/particleEmitterState.d.ts.map +1 -0
- package/dist/particleEmitterState.js +38 -0
- package/dist/particleEmitterState.js.map +1 -0
- package/dist/particleObjectsState.d.ts +4 -0
- package/dist/particleObjectsState.d.ts.map +1 -0
- package/dist/particleObjectsState.js +24 -0
- package/dist/particleObjectsState.js.map +1 -0
- package/dist/prewarmParticleEmitter.d.ts +5 -0
- package/dist/prewarmParticleEmitter.d.ts.map +1 -0
- package/dist/prewarmParticleEmitter.js +13 -0
- package/dist/prewarmParticleEmitter.js.map +1 -0
- package/dist/stepParticleEmitter.d.ts +38 -0
- package/dist/stepParticleEmitter.d.ts.map +1 -0
- package/dist/stepParticleEmitter.js +57 -0
- package/dist/stepParticleEmitter.js.map +1 -0
- package/dist/updateParticleEmitter.d.ts +8 -0
- package/dist/updateParticleEmitter.d.ts.map +1 -0
- package/dist/updateParticleEmitter.js +315 -0
- package/dist/updateParticleEmitter.js.map +1 -0
- package/dist/updateParticleObjects.d.ts +8 -0
- package/dist/updateParticleObjects.d.ts.map +1 -0
- package/dist/updateParticleObjects.js +151 -0
- package/dist/updateParticleObjects.js.map +1 -0
- package/dist/validateParticleEmitterConfig.d.ts +15 -0
- package/dist/validateParticleEmitterConfig.d.ts.map +1 -0
- package/dist/validateParticleEmitterConfig.js +206 -0
- package/dist/validateParticleEmitterConfig.js.map +1 -0
- package/package.json +42 -0
- package/src/applyParticleCollisions.test.ts +191 -0
- package/src/applyParticleForces.test.ts +174 -0
- package/src/curve.test.ts +327 -0
- package/src/deterministic.test.ts +54 -0
- package/src/emitParticleBurst.test.ts +103 -0
- package/src/particleEmitterConfig.test.ts +65 -0
- package/src/particleEmitterSignals.test.ts +125 -0
- package/src/particleEmitterState.test.ts +113 -0
- package/src/particleObjectsState.test.ts +34 -0
- package/src/prewarmParticleEmitter.test.ts +68 -0
- package/src/stepParticleEmitter.test.ts +113 -0
- package/src/updateParticleEmitter.test.ts +631 -0
- package/src/updateParticleObjects.test.ts +340 -0
- package/src/validateParticleEmitterConfig.test.ts +118 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CircleCollider, ParticleCollider, ParticleEmitter, ParticleEmitterState, ParticleObject, ParticleObjectsState, PlaneCollider, RectangleCollider } from '@flighthq/types';
|
|
2
|
+
export type { CircleCollider, ParticleCollider, PlaneCollider, RectangleCollider };
|
|
3
|
+
/** Resolve particle/collider collisions for a typed-array emitter, correcting
|
|
4
|
+
* position and velocity in place. Call this AFTER updateParticleEmitter so it
|
|
5
|
+
* fixes up penetration produced by the frame's integration.
|
|
6
|
+
*
|
|
7
|
+
* Fully opt-in: import it only for emitters that collide. The core update path
|
|
8
|
+
* is unaware of it. */
|
|
9
|
+
export declare function applyParticleCollisions(emitter: ParticleEmitter, state: ParticleEmitterState, colliders: ReadonlyArray<ParticleCollider>): void;
|
|
10
|
+
/** Collision pass for the object-pool path. Call AFTER updateParticleObjects. */
|
|
11
|
+
export declare function applyParticleObjectCollisions(objects: readonly ParticleObject[], state: ParticleObjectsState, colliders: ReadonlyArray<ParticleCollider>): void;
|
|
12
|
+
//# sourceMappingURL=applyParticleCollisions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyParticleCollisions.d.ts","sourceRoot":"","sources":["../src/applyParticleCollisions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,iBAAiB,EAClB,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,aAAa,EAAE,iBAAiB,EAAE,CAAC;AAKnF;;;;;wBAKwB;AACxB,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,oBAAoB,EAC3B,SAAS,EAAE,aAAa,CAAC,gBAAgB,CAAC,GACzC,IAAI,CAoBN;AAED,iFAAiF;AACjF,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,SAAS,cAAc,EAAE,EAClC,KAAK,EAAE,oBAAoB,EAC3B,SAAS,EAAE,aAAa,CAAC,gBAAgB,CAAC,GACzC,IAAI,CAkBN"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
// [px, py, vx, vy] scratch reused across particles to avoid per-iteration allocation.
|
|
2
|
+
const s = [0, 0, 0, 0];
|
|
3
|
+
/** Resolve particle/collider collisions for a typed-array emitter, correcting
|
|
4
|
+
* position and velocity in place. Call this AFTER updateParticleEmitter so it
|
|
5
|
+
* fixes up penetration produced by the frame's integration.
|
|
6
|
+
*
|
|
7
|
+
* Fully opt-in: import it only for emitters that collide. The core update path
|
|
8
|
+
* is unaware of it. */
|
|
9
|
+
export function applyParticleCollisions(emitter, state, colliders) {
|
|
10
|
+
if (colliders.length === 0)
|
|
11
|
+
return;
|
|
12
|
+
const data = emitter.data;
|
|
13
|
+
const count = data.particleCount;
|
|
14
|
+
const transforms = data.transforms;
|
|
15
|
+
const velocities = state.velocities;
|
|
16
|
+
for (let i = 0; i < count; i++) {
|
|
17
|
+
const tt = i * 4;
|
|
18
|
+
const vt = i * 2;
|
|
19
|
+
s[0] = transforms[tt];
|
|
20
|
+
s[1] = transforms[tt + 1];
|
|
21
|
+
s[2] = velocities[vt];
|
|
22
|
+
s[3] = velocities[vt + 1];
|
|
23
|
+
if (resolveColliders(colliders, s)) {
|
|
24
|
+
transforms[tt] = s[0];
|
|
25
|
+
transforms[tt + 1] = s[1];
|
|
26
|
+
velocities[vt] = s[2];
|
|
27
|
+
velocities[vt + 1] = s[3];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** Collision pass for the object-pool path. Call AFTER updateParticleObjects. */
|
|
32
|
+
export function applyParticleObjectCollisions(objects, state, colliders) {
|
|
33
|
+
if (colliders.length === 0)
|
|
34
|
+
return;
|
|
35
|
+
const velocities = state.velocities;
|
|
36
|
+
const lifetimes = state.lifetimes;
|
|
37
|
+
for (let i = 0; i < objects.length; i++) {
|
|
38
|
+
if (lifetimes[i * 2 + 1] <= 0)
|
|
39
|
+
continue; // dead slot
|
|
40
|
+
const vt = i * 2;
|
|
41
|
+
s[0] = objects[i].x;
|
|
42
|
+
s[1] = objects[i].y;
|
|
43
|
+
s[2] = velocities[vt];
|
|
44
|
+
s[3] = velocities[vt + 1];
|
|
45
|
+
if (resolveColliders(colliders, s)) {
|
|
46
|
+
objects[i].x = s[0];
|
|
47
|
+
objects[i].y = s[1];
|
|
48
|
+
velocities[vt] = s[2];
|
|
49
|
+
velocities[vt + 1] = s[3];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function resolveColliders(colliders, p) {
|
|
54
|
+
let hit = false;
|
|
55
|
+
for (let c = 0; c < colliders.length; c++) {
|
|
56
|
+
const collider = colliders[c];
|
|
57
|
+
switch (collider.kind) {
|
|
58
|
+
case 'PlaneCollider':
|
|
59
|
+
hit = resolvePlane(collider, p) || hit;
|
|
60
|
+
break;
|
|
61
|
+
case 'CircleCollider':
|
|
62
|
+
hit = resolveCircle(collider, p) || hit;
|
|
63
|
+
break;
|
|
64
|
+
case 'RectangleCollider':
|
|
65
|
+
hit = resolveRect(collider, p) || hit;
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return hit;
|
|
70
|
+
}
|
|
71
|
+
function resolvePlane(c, p) {
|
|
72
|
+
const depth = c.nx * p[0] + c.ny * p[1] - c.distance;
|
|
73
|
+
if (depth >= 0)
|
|
74
|
+
return false;
|
|
75
|
+
p[0] -= c.nx * depth; // push back onto the surface
|
|
76
|
+
p[1] -= c.ny * depth;
|
|
77
|
+
reflect(p, c.nx, c.ny, c.restitution ?? 0, c.friction ?? 0);
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
function resolveCircle(c, p) {
|
|
81
|
+
const dx = p[0] - c.x;
|
|
82
|
+
const dy = p[1] - c.y;
|
|
83
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
84
|
+
if (c.mode === 'exclude') {
|
|
85
|
+
if (dist >= c.radius || dist <= 1e-6)
|
|
86
|
+
return false;
|
|
87
|
+
const nx = dx / dist;
|
|
88
|
+
const ny = dy / dist;
|
|
89
|
+
p[0] = c.x + nx * c.radius;
|
|
90
|
+
p[1] = c.y + ny * c.radius;
|
|
91
|
+
reflect(p, nx, ny, c.restitution ?? 0, c.friction ?? 0);
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
// contain
|
|
95
|
+
if (dist <= c.radius)
|
|
96
|
+
return false;
|
|
97
|
+
const nx = dist <= 1e-6 ? 0 : -dx / dist; // inward normal
|
|
98
|
+
const ny = dist <= 1e-6 ? -1 : -dy / dist;
|
|
99
|
+
p[0] = c.x - nx * c.radius;
|
|
100
|
+
p[1] = c.y - ny * c.radius;
|
|
101
|
+
reflect(p, nx, ny, c.restitution ?? 0, c.friction ?? 0);
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
function resolveRect(c, p) {
|
|
105
|
+
const hw = c.width / 2;
|
|
106
|
+
const hh = c.height / 2;
|
|
107
|
+
const minX = c.x - hw;
|
|
108
|
+
const maxX = c.x + hw;
|
|
109
|
+
const minY = c.y - hh;
|
|
110
|
+
const maxY = c.y + hh;
|
|
111
|
+
const restitution = c.restitution ?? 0;
|
|
112
|
+
const friction = c.friction ?? 0;
|
|
113
|
+
if (c.mode === 'contain') {
|
|
114
|
+
let hit = false;
|
|
115
|
+
if (p[0] < minX) {
|
|
116
|
+
p[0] = minX;
|
|
117
|
+
reflect(p, 1, 0, restitution, friction);
|
|
118
|
+
hit = true;
|
|
119
|
+
}
|
|
120
|
+
else if (p[0] > maxX) {
|
|
121
|
+
p[0] = maxX;
|
|
122
|
+
reflect(p, -1, 0, restitution, friction);
|
|
123
|
+
hit = true;
|
|
124
|
+
}
|
|
125
|
+
if (p[1] < minY) {
|
|
126
|
+
p[1] = minY;
|
|
127
|
+
reflect(p, 0, 1, restitution, friction);
|
|
128
|
+
hit = true;
|
|
129
|
+
}
|
|
130
|
+
else if (p[1] > maxY) {
|
|
131
|
+
p[1] = maxY;
|
|
132
|
+
reflect(p, 0, -1, restitution, friction);
|
|
133
|
+
hit = true;
|
|
134
|
+
}
|
|
135
|
+
return hit;
|
|
136
|
+
}
|
|
137
|
+
// exclude: only if the point is inside the box, push out along the shallowest axis.
|
|
138
|
+
if (p[0] <= minX || p[0] >= maxX || p[1] <= minY || p[1] >= maxY)
|
|
139
|
+
return false;
|
|
140
|
+
const left = p[0] - minX;
|
|
141
|
+
const right = maxX - p[0];
|
|
142
|
+
const top = p[1] - minY;
|
|
143
|
+
const bottom = maxY - p[1];
|
|
144
|
+
const minPen = Math.min(left, right, top, bottom);
|
|
145
|
+
if (minPen === left) {
|
|
146
|
+
p[0] = minX;
|
|
147
|
+
reflect(p, -1, 0, restitution, friction);
|
|
148
|
+
}
|
|
149
|
+
else if (minPen === right) {
|
|
150
|
+
p[0] = maxX;
|
|
151
|
+
reflect(p, 1, 0, restitution, friction);
|
|
152
|
+
}
|
|
153
|
+
else if (minPen === top) {
|
|
154
|
+
p[1] = minY;
|
|
155
|
+
reflect(p, 0, -1, restitution, friction);
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
p[1] = maxY;
|
|
159
|
+
reflect(p, 0, 1, restitution, friction);
|
|
160
|
+
}
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
// Reflect the velocity in p[2],p[3] about a surface with unit normal (nx, ny):
|
|
164
|
+
// bounce the inward normal component by `restitution` and damp the tangential
|
|
165
|
+
// component by `friction`. Only acts when the particle is moving into the surface.
|
|
166
|
+
function reflect(p, nx, ny, restitution, friction) {
|
|
167
|
+
const vn = p[2] * nx + p[3] * ny;
|
|
168
|
+
if (vn >= 0)
|
|
169
|
+
return; // already separating
|
|
170
|
+
const tvx = p[2] - vn * nx;
|
|
171
|
+
const tvy = p[3] - vn * ny;
|
|
172
|
+
p[2] = tvx * (1 - friction) - restitution * vn * nx;
|
|
173
|
+
p[3] = tvy * (1 - friction) - restitution * vn * ny;
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=applyParticleCollisions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyParticleCollisions.js","sourceRoot":"","sources":["../src/applyParticleCollisions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AttractorForce, DragForce, ForceFalloff, ParticleEmitter, ParticleEmitterState, ParticleForce, ParticleObject, ParticleObjectsState, TurbulenceForce, VortexForce, WindForce } from '@flighthq/types';
|
|
2
|
+
export type { AttractorForce, DragForce, ForceFalloff, ParticleForce, TurbulenceForce, VortexForce, WindForce };
|
|
3
|
+
/** Apply force fields to a typed-array particle emitter, integrating the
|
|
4
|
+
* resulting acceleration into per-particle velocity. Call this BEFORE
|
|
5
|
+
* updateParticleEmitter each frame so the velocity change is integrated into
|
|
6
|
+
* position the same frame.
|
|
7
|
+
*
|
|
8
|
+
* This is a fully opt-in pass: import it only for emitters that need forces.
|
|
9
|
+
* The core update path is unaware of it. */
|
|
10
|
+
export declare function applyParticleForces(emitter: ParticleEmitter, state: ParticleEmitterState, forces: ReadonlyArray<ParticleForce>, deltaTime: number): void;
|
|
11
|
+
/** Force-field pass for the object-pool path. Call BEFORE updateParticleObjects. */
|
|
12
|
+
export declare function applyParticleObjectForces(objects: readonly ParticleObject[], state: ParticleObjectsState, forces: ReadonlyArray<ParticleForce>, deltaTime: number): void;
|
|
13
|
+
//# sourceMappingURL=applyParticleForces.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyParticleForces.d.ts","sourceRoot":"","sources":["../src/applyParticleForces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,SAAS,EACT,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,WAAW,EACX,SAAS,EACV,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;AAKhH;;;;;;6CAM6C;AAC7C,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,oBAAoB,EAC3B,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC,EACpC,SAAS,EAAE,MAAM,GAChB,IAAI,CAgBN;AAED,oFAAoF;AACpF,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,SAAS,cAAc,EAAE,EAClC,KAAK,EAAE,oBAAoB,EAC3B,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC,EACpC,SAAS,EAAE,MAAM,GAChB,IAAI,CAaN"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// Per-particle acceleration scratch, reused across the loop to avoid allocation.
|
|
2
|
+
const accel = [0, 0];
|
|
3
|
+
/** Apply force fields to a typed-array particle emitter, integrating the
|
|
4
|
+
* resulting acceleration into per-particle velocity. Call this BEFORE
|
|
5
|
+
* updateParticleEmitter each frame so the velocity change is integrated into
|
|
6
|
+
* position the same frame.
|
|
7
|
+
*
|
|
8
|
+
* This is a fully opt-in pass: import it only for emitters that need forces.
|
|
9
|
+
* The core update path is unaware of it. */
|
|
10
|
+
export function applyParticleForces(emitter, state, forces, deltaTime) {
|
|
11
|
+
if (deltaTime <= 0 || forces.length === 0)
|
|
12
|
+
return;
|
|
13
|
+
const data = emitter.data;
|
|
14
|
+
const count = data.particleCount;
|
|
15
|
+
const transforms = data.transforms;
|
|
16
|
+
const velocities = state.velocities;
|
|
17
|
+
for (let i = 0; i < count; i++) {
|
|
18
|
+
const tt = i * 4;
|
|
19
|
+
const vt = i * 2;
|
|
20
|
+
accel[0] = 0;
|
|
21
|
+
accel[1] = 0;
|
|
22
|
+
accumulateForces(forces, transforms[tt], transforms[tt + 1], velocities[vt], velocities[vt + 1], accel);
|
|
23
|
+
velocities[vt] += accel[0] * deltaTime;
|
|
24
|
+
velocities[vt + 1] += accel[1] * deltaTime;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** Force-field pass for the object-pool path. Call BEFORE updateParticleObjects. */
|
|
28
|
+
export function applyParticleObjectForces(objects, state, forces, deltaTime) {
|
|
29
|
+
if (deltaTime <= 0 || forces.length === 0)
|
|
30
|
+
return;
|
|
31
|
+
const velocities = state.velocities;
|
|
32
|
+
const lifetimes = state.lifetimes;
|
|
33
|
+
for (let i = 0; i < objects.length; i++) {
|
|
34
|
+
if (lifetimes[i * 2 + 1] <= 0)
|
|
35
|
+
continue; // dead slot
|
|
36
|
+
const vt = i * 2;
|
|
37
|
+
accel[0] = 0;
|
|
38
|
+
accel[1] = 0;
|
|
39
|
+
accumulateForces(forces, objects[i].x, objects[i].y, velocities[vt], velocities[vt + 1], accel);
|
|
40
|
+
velocities[vt] += accel[0] * deltaTime;
|
|
41
|
+
velocities[vt + 1] += accel[1] * deltaTime;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function accumulateForces(forces, px, py, vx, vy, out) {
|
|
45
|
+
for (let f = 0; f < forces.length; f++) {
|
|
46
|
+
const force = forces[f];
|
|
47
|
+
switch (force.kind) {
|
|
48
|
+
case 'WindForce':
|
|
49
|
+
out[0] += force.x;
|
|
50
|
+
out[1] += force.y;
|
|
51
|
+
break;
|
|
52
|
+
case 'DragForce':
|
|
53
|
+
out[0] -= force.strength * vx;
|
|
54
|
+
out[1] -= force.strength * vy;
|
|
55
|
+
break;
|
|
56
|
+
case 'AttractorForce': {
|
|
57
|
+
const dx = force.x - px;
|
|
58
|
+
const dy = force.y - py;
|
|
59
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
60
|
+
if (dist <= 1e-6)
|
|
61
|
+
break;
|
|
62
|
+
const mag = force.strength * falloffFactor(force.falloff, dist, force.radius);
|
|
63
|
+
if (mag === 0)
|
|
64
|
+
break;
|
|
65
|
+
out[0] += (dx / dist) * mag;
|
|
66
|
+
out[1] += (dy / dist) * mag;
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
case 'VortexForce': {
|
|
70
|
+
const dx = px - force.x;
|
|
71
|
+
const dy = py - force.y;
|
|
72
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
73
|
+
if (dist <= 1e-6)
|
|
74
|
+
break;
|
|
75
|
+
const mag = force.strength * falloffFactor(force.falloff, dist, force.radius);
|
|
76
|
+
if (mag === 0)
|
|
77
|
+
break;
|
|
78
|
+
// Tangent = perpendicular to the radial direction.
|
|
79
|
+
out[0] += (-dy / dist) * mag;
|
|
80
|
+
out[1] += (dx / dist) * mag;
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
case 'TurbulenceForce': {
|
|
84
|
+
const s = force.scale;
|
|
85
|
+
out[0] += (valueNoise(px * s, py * s, 0) * 2 - 1) * force.strength;
|
|
86
|
+
out[1] += (valueNoise(px * s, py * s, 1) * 2 - 1) * force.strength;
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function falloffFactor(falloff, dist, radius) {
|
|
93
|
+
if (radius != null && radius > 0 && dist > radius)
|
|
94
|
+
return 0; // hard cutoff
|
|
95
|
+
switch (falloff) {
|
|
96
|
+
case 'linear':
|
|
97
|
+
return radius != null && radius > 0 ? Math.max(0, 1 - dist / radius) : 1;
|
|
98
|
+
case 'inverseSquare': {
|
|
99
|
+
const d = dist < 1 ? 1 : dist; // clamp near the source to avoid a singularity
|
|
100
|
+
return 1 / (d * d);
|
|
101
|
+
}
|
|
102
|
+
default:
|
|
103
|
+
return 1;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Cheap deterministic 2-D value noise in [0, 1): hash the integer lattice and
|
|
107
|
+
// smoothstep-interpolate. Good enough for VFX turbulence, and fully reproducible.
|
|
108
|
+
function valueNoise(x, y, seed) {
|
|
109
|
+
const x0 = Math.floor(x);
|
|
110
|
+
const y0 = Math.floor(y);
|
|
111
|
+
const fx = x - x0;
|
|
112
|
+
const fy = y - y0;
|
|
113
|
+
const ux = fx * fx * (3 - 2 * fx);
|
|
114
|
+
const uy = fy * fy * (3 - 2 * fy);
|
|
115
|
+
const n00 = hash2(x0, y0, seed);
|
|
116
|
+
const n10 = hash2(x0 + 1, y0, seed);
|
|
117
|
+
const n01 = hash2(x0, y0 + 1, seed);
|
|
118
|
+
const n11 = hash2(x0 + 1, y0 + 1, seed);
|
|
119
|
+
const nx0 = n00 + (n10 - n00) * ux;
|
|
120
|
+
const nx1 = n01 + (n11 - n01) * ux;
|
|
121
|
+
return nx0 + (nx1 - nx0) * uy;
|
|
122
|
+
}
|
|
123
|
+
function hash2(x, y, seed) {
|
|
124
|
+
let h = (Math.imul(x, 0x27d4eb2d) ^ Math.imul(y, 0x165667b1) ^ Math.imul(seed + 1, 0x9e3779b1)) | 0;
|
|
125
|
+
h = Math.imul(h ^ (h >>> 15), 0x85ebca6b);
|
|
126
|
+
h = Math.imul(h ^ (h >>> 13), 0xc2b2ae35);
|
|
127
|
+
return ((h ^ (h >>> 16)) >>> 0) / 4294967296;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=applyParticleForces.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyParticleForces.js","sourceRoot":"","sources":["../src/applyParticleForces.ts"],"names":[],"mappings":"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"}
|
package/dist/curve.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ColorKeyframe, CurveKeyframe, ParticleCurve } from '@flighthq/types';
|
|
2
|
+
export type { ColorKeyframe, CurveKeyframe, ParticleCurve };
|
|
3
|
+
/** Bake an RGB function f:[0,1]→[r,g,b] into an interleaved curve LUT (length N×3). */
|
|
4
|
+
export declare function buildParticleColorCurve(f: (t: number) => readonly [number, number, number], samples?: number): number[];
|
|
5
|
+
/** Bake a scalar function f:[0,1]→value into an `samples`-entry curve LUT. */
|
|
6
|
+
export declare function buildParticleCurve(f: (t: number) => number, samples?: number): number[];
|
|
7
|
+
/** Linearly interpolate two sRGB colors through HSV space, writing into `out[offset..+3]`.
|
|
8
|
+
* Used by the `colorInterpolation: 'hsv'` path in updateParticleEmitter. */
|
|
9
|
+
export declare function lerpHsvDirect(out: Float32Array | number[], offset: number, r0: number, g0: number, b0: number, r1: number, g1: number, b1: number, t: number): void;
|
|
10
|
+
/** Interpolate through HSV space using per-particle birth/death color arrays. */
|
|
11
|
+
export declare function lerpHsvInPlace(colorsOut: Float32Array | number[], offset: number, birth: Float32Array, death: Float32Array, t: number): void;
|
|
12
|
+
/** Bake a piecewise-linear RGB timeline (e.g. an imported color gradient) into a
|
|
13
|
+
* uniform interleaved LUT (length N×3). */
|
|
14
|
+
export declare function particleColorCurveFromKeyframes(keys: ReadonlyArray<ColorKeyframe>, samples?: number): number[];
|
|
15
|
+
/** Convert a baked interleaved RGB curve LUT (length N×3) back into color
|
|
16
|
+
* keyframes (one per sample, at uniform times). */
|
|
17
|
+
export declare function particleColorCurveToKeyframes(lut: ParticleCurve): ColorKeyframe[];
|
|
18
|
+
/** Bake a piecewise-linear scalar timeline (e.g. an imported alpha-over-lifetime
|
|
19
|
+
* curve) into a uniform LUT. Keyframes need not be sorted; times are clamped to
|
|
20
|
+
* the [first, last] range. */
|
|
21
|
+
export declare function particleCurveFromKeyframes(keys: ReadonlyArray<CurveKeyframe>, samples?: number): number[];
|
|
22
|
+
/** Convert a baked scalar curve LUT back into keyframes (one per sample, at
|
|
23
|
+
* uniform times). The inverse of {@link particleCurveFromKeyframes} for the common case
|
|
24
|
+
* of a 33-sample LUT — used by format serializers to round-trip authored curves. */
|
|
25
|
+
export declare function particleCurveToKeyframes(lut: ParticleCurve): CurveKeyframe[];
|
|
26
|
+
/** Sample an interleaved RGB curve (length N×3) at t∈[0,1], writing the three
|
|
27
|
+
* channels into `out` starting at `offset`. */
|
|
28
|
+
export declare function sampleParticleColorCurve(out: {
|
|
29
|
+
[index: number]: number;
|
|
30
|
+
}, offset: number, lut: ParticleCurve, t: number): void;
|
|
31
|
+
/** Sample a uniformly-spaced scalar curve at t∈[0,1] with linear interpolation.
|
|
32
|
+
* Out-of-range t is clamped. An empty curve samples to 0; a single value is
|
|
33
|
+
* returned as-is. */
|
|
34
|
+
export declare function sampleParticleCurve(lut: ParticleCurve, t: number): number;
|
|
35
|
+
//# sourceMappingURL=curve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"curve.d.ts","sourceRoot":"","sources":["../src/curve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEnF,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC;AAE5D,uFAAuF;AACvF,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,SAAK,GAAG,MAAM,EAAE,CAUnH;AAED,8EAA8E;AAC9E,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAAE,OAAO,SAAK,GAAG,MAAM,EAAE,CAKnF;AAED;6EAC6E;AAC7E,wBAAgB,aAAa,CAC3B,GAAG,EAAE,YAAY,GAAG,MAAM,EAAE,EAC5B,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,CAAC,EAAE,MAAM,GACR,IAAI,CAWN;AAED,iFAAiF;AACjF,wBAAgB,cAAc,CAC5B,SAAS,EAAE,YAAY,GAAG,MAAM,EAAE,EAClC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,YAAY,EACnB,CAAC,EAAE,MAAM,GACR,IAAI,CAYN;AAED;4CAC4C;AAC5C,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,aAAa,CAAC,aAAa,CAAC,EAAE,OAAO,SAAK,GAAG,MAAM,EAAE,CAU1G;AAED;oDACoD;AACpD,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,aAAa,GAAG,aAAa,EAAE,CAOjF;AAED;;+BAE+B;AAC/B,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,aAAa,CAAC,aAAa,CAAC,EAAE,OAAO,SAAK,GAAG,MAAM,EAAE,CAIrG;AAED;;qFAEqF;AACrF,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,aAAa,GAAG,aAAa,EAAE,CAO5E;AAuFD;gDACgD;AAChD,wBAAgB,wBAAwB,CACtC,GAAG,EAAE;IAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,EAChC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,aAAa,EAClB,CAAC,EAAE,MAAM,GACR,IAAI,CA6BN;AAED;;sBAEsB;AACtB,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,aAAa,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAQzE"}
|
package/dist/curve.js
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/** Bake an RGB function f:[0,1]→[r,g,b] into an interleaved curve LUT (length N×3). */
|
|
2
|
+
export function buildParticleColorCurve(f, samples = 33) {
|
|
3
|
+
const n = Math.max(2, samples | 0);
|
|
4
|
+
const lut = new Array(n * 3);
|
|
5
|
+
for (let i = 0; i < n; i++) {
|
|
6
|
+
const [r, g, b] = f(i / (n - 1));
|
|
7
|
+
lut[i * 3] = r;
|
|
8
|
+
lut[i * 3 + 1] = g;
|
|
9
|
+
lut[i * 3 + 2] = b;
|
|
10
|
+
}
|
|
11
|
+
return lut;
|
|
12
|
+
}
|
|
13
|
+
/** Bake a scalar function f:[0,1]→value into an `samples`-entry curve LUT. */
|
|
14
|
+
export function buildParticleCurve(f, samples = 33) {
|
|
15
|
+
const n = Math.max(2, samples | 0);
|
|
16
|
+
const lut = new Array(n);
|
|
17
|
+
for (let i = 0; i < n; i++)
|
|
18
|
+
lut[i] = f(i / (n - 1));
|
|
19
|
+
return lut;
|
|
20
|
+
}
|
|
21
|
+
/** Linearly interpolate two sRGB colors through HSV space, writing into `out[offset..+3]`.
|
|
22
|
+
* Used by the `colorInterpolation: 'hsv'` path in updateParticleEmitter. */
|
|
23
|
+
export function lerpHsvDirect(out, offset, r0, g0, b0, r1, g1, b1, t) {
|
|
24
|
+
const [h0, s0, v0] = rgbToHsv(r0, g0, b0);
|
|
25
|
+
const [h1, s1, v1] = rgbToHsv(r1, g1, b1);
|
|
26
|
+
// Hue wraps around — take the shorter arc.
|
|
27
|
+
let dh = h1 - h0;
|
|
28
|
+
if (dh > 0.5)
|
|
29
|
+
dh -= 1;
|
|
30
|
+
else if (dh < -0.5)
|
|
31
|
+
dh += 1;
|
|
32
|
+
const [r, g, b] = hsvToRgb(h0 + dh * t, s0 + (s1 - s0) * t, v0 + (v1 - v0) * t);
|
|
33
|
+
out[offset] = r;
|
|
34
|
+
out[offset + 1] = g;
|
|
35
|
+
out[offset + 2] = b;
|
|
36
|
+
}
|
|
37
|
+
/** Interpolate through HSV space using per-particle birth/death color arrays. */
|
|
38
|
+
export function lerpHsvInPlace(colorsOut, offset, birth, death, t) {
|
|
39
|
+
lerpHsvDirect(colorsOut, offset, birth[offset], birth[offset + 1], birth[offset + 2], death[offset], death[offset + 1], death[offset + 2], t);
|
|
40
|
+
}
|
|
41
|
+
/** Bake a piecewise-linear RGB timeline (e.g. an imported color gradient) into a
|
|
42
|
+
* uniform interleaved LUT (length N×3). */
|
|
43
|
+
export function particleColorCurveFromKeyframes(keys, samples = 33) {
|
|
44
|
+
if (keys.length === 0)
|
|
45
|
+
return [0, 0, 0, 0, 0, 0];
|
|
46
|
+
const sorted = keys.slice().sort((a, b) => a.time - b.time);
|
|
47
|
+
return buildParticleColorCurve((t) => {
|
|
48
|
+
const seg = locateKeyframe(sorted, t);
|
|
49
|
+
if (seg.f === 0)
|
|
50
|
+
return [sorted[seg.i].r, sorted[seg.i].g, sorted[seg.i].b];
|
|
51
|
+
const a = sorted[seg.i];
|
|
52
|
+
const b = sorted[seg.i + 1];
|
|
53
|
+
return [a.r + (b.r - a.r) * seg.f, a.g + (b.g - a.g) * seg.f, a.b + (b.b - a.b) * seg.f];
|
|
54
|
+
}, samples);
|
|
55
|
+
}
|
|
56
|
+
/** Convert a baked interleaved RGB curve LUT (length N×3) back into color
|
|
57
|
+
* keyframes (one per sample, at uniform times). */
|
|
58
|
+
export function particleColorCurveToKeyframes(lut) {
|
|
59
|
+
const n = Math.floor(lut.length / 3);
|
|
60
|
+
if (n === 0)
|
|
61
|
+
return [];
|
|
62
|
+
if (n === 1)
|
|
63
|
+
return [{ time: 0, r: lut[0], g: lut[1], b: lut[2] }];
|
|
64
|
+
const keys = new Array(n);
|
|
65
|
+
for (let i = 0; i < n; i++)
|
|
66
|
+
keys[i] = { time: i / (n - 1), r: lut[i * 3], g: lut[i * 3 + 1], b: lut[i * 3 + 2] };
|
|
67
|
+
return keys;
|
|
68
|
+
}
|
|
69
|
+
/** Bake a piecewise-linear scalar timeline (e.g. an imported alpha-over-lifetime
|
|
70
|
+
* curve) into a uniform LUT. Keyframes need not be sorted; times are clamped to
|
|
71
|
+
* the [first, last] range. */
|
|
72
|
+
export function particleCurveFromKeyframes(keys, samples = 33) {
|
|
73
|
+
if (keys.length === 0)
|
|
74
|
+
return [0, 0];
|
|
75
|
+
const sorted = keys.slice().sort((a, b) => a.time - b.time);
|
|
76
|
+
return buildParticleCurve((t) => interpKeyframe(sorted, t), samples);
|
|
77
|
+
}
|
|
78
|
+
/** Convert a baked scalar curve LUT back into keyframes (one per sample, at
|
|
79
|
+
* uniform times). The inverse of {@link particleCurveFromKeyframes} for the common case
|
|
80
|
+
* of a 33-sample LUT — used by format serializers to round-trip authored curves. */
|
|
81
|
+
export function particleCurveToKeyframes(lut) {
|
|
82
|
+
const n = lut.length;
|
|
83
|
+
if (n === 0)
|
|
84
|
+
return [];
|
|
85
|
+
if (n === 1)
|
|
86
|
+
return [{ time: 0, value: lut[0] }];
|
|
87
|
+
const keys = new Array(n);
|
|
88
|
+
for (let i = 0; i < n; i++)
|
|
89
|
+
keys[i] = { time: i / (n - 1), value: lut[i] };
|
|
90
|
+
return keys;
|
|
91
|
+
}
|
|
92
|
+
/** Convert HSV to sRGB [0, 1]. Internal helper for HSV interpolation. */
|
|
93
|
+
function hsvToRgb(h, s, v) {
|
|
94
|
+
const c = v * s;
|
|
95
|
+
const x = c * (1 - Math.abs(((h * 6) % 2) - 1));
|
|
96
|
+
const m = v - c;
|
|
97
|
+
const hi = Math.floor(h * 6) % 6;
|
|
98
|
+
let r = 0;
|
|
99
|
+
let g = 0;
|
|
100
|
+
let b = 0;
|
|
101
|
+
switch (hi) {
|
|
102
|
+
case 0:
|
|
103
|
+
r = c;
|
|
104
|
+
g = x;
|
|
105
|
+
b = 0;
|
|
106
|
+
break;
|
|
107
|
+
case 1:
|
|
108
|
+
r = x;
|
|
109
|
+
g = c;
|
|
110
|
+
b = 0;
|
|
111
|
+
break;
|
|
112
|
+
case 2:
|
|
113
|
+
r = 0;
|
|
114
|
+
g = c;
|
|
115
|
+
b = x;
|
|
116
|
+
break;
|
|
117
|
+
case 3:
|
|
118
|
+
r = 0;
|
|
119
|
+
g = x;
|
|
120
|
+
b = c;
|
|
121
|
+
break;
|
|
122
|
+
case 4:
|
|
123
|
+
r = x;
|
|
124
|
+
g = 0;
|
|
125
|
+
b = c;
|
|
126
|
+
break;
|
|
127
|
+
default:
|
|
128
|
+
r = c;
|
|
129
|
+
g = 0;
|
|
130
|
+
b = x;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
return [r + m, g + m, b + m];
|
|
134
|
+
}
|
|
135
|
+
function interpKeyframe(sorted, t) {
|
|
136
|
+
const seg = locateKeyframe(sorted, t);
|
|
137
|
+
if (seg.f === 0)
|
|
138
|
+
return sorted[seg.i].value;
|
|
139
|
+
const a = sorted[seg.i].value;
|
|
140
|
+
const b = sorted[seg.i + 1].value;
|
|
141
|
+
return a + (b - a) * seg.f;
|
|
142
|
+
}
|
|
143
|
+
// Find the keyframe segment containing t: returns the lower index `i` and the
|
|
144
|
+
// fractional position `f` into segment [i, i+1] (f = 0 means "use sorted[i] exactly").
|
|
145
|
+
function locateKeyframe(sorted, t) {
|
|
146
|
+
const n = sorted.length;
|
|
147
|
+
if (t <= sorted[0].time)
|
|
148
|
+
return { f: 0, i: 0 };
|
|
149
|
+
if (t >= sorted[n - 1].time)
|
|
150
|
+
return { f: 0, i: n - 1 };
|
|
151
|
+
for (let i = 0; i < n - 1; i++) {
|
|
152
|
+
const t0 = sorted[i].time;
|
|
153
|
+
const t1 = sorted[i + 1].time;
|
|
154
|
+
if (t <= t1) {
|
|
155
|
+
const span = t1 - t0;
|
|
156
|
+
return { f: span <= 0 ? 0 : (t - t0) / span, i };
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return { f: 0, i: n - 1 };
|
|
160
|
+
}
|
|
161
|
+
/** Convert sRGB [0, 1] to HSV. Internal helper for HSV interpolation. */
|
|
162
|
+
function rgbToHsv(r, g, b) {
|
|
163
|
+
const max = Math.max(r, g, b);
|
|
164
|
+
const min = Math.min(r, g, b);
|
|
165
|
+
const delta = max - min;
|
|
166
|
+
let h = 0;
|
|
167
|
+
if (delta > 0) {
|
|
168
|
+
if (max === r)
|
|
169
|
+
h = ((g - b) / delta) % 6;
|
|
170
|
+
else if (max === g)
|
|
171
|
+
h = (b - r) / delta + 2;
|
|
172
|
+
else
|
|
173
|
+
h = (r - g) / delta + 4;
|
|
174
|
+
h /= 6;
|
|
175
|
+
if (h < 0)
|
|
176
|
+
h += 1;
|
|
177
|
+
}
|
|
178
|
+
return [h, max === 0 ? 0 : delta / max, max];
|
|
179
|
+
}
|
|
180
|
+
/** Sample an interleaved RGB curve (length N×3) at t∈[0,1], writing the three
|
|
181
|
+
* channels into `out` starting at `offset`. */
|
|
182
|
+
export function sampleParticleColorCurve(out, offset, lut, t) {
|
|
183
|
+
const n = lut.length / 3;
|
|
184
|
+
if (n <= 0) {
|
|
185
|
+
out[offset] = 0;
|
|
186
|
+
out[offset + 1] = 0;
|
|
187
|
+
out[offset + 2] = 0;
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (n === 1) {
|
|
191
|
+
out[offset] = lut[0];
|
|
192
|
+
out[offset + 1] = lut[1];
|
|
193
|
+
out[offset + 2] = lut[2];
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const x = (t <= 0 ? 0 : t >= 1 ? 1 : t) * (n - 1);
|
|
197
|
+
const i = x | 0;
|
|
198
|
+
if (i >= n - 1) {
|
|
199
|
+
const base = (n - 1) * 3;
|
|
200
|
+
out[offset] = lut[base];
|
|
201
|
+
out[offset + 1] = lut[base + 1];
|
|
202
|
+
out[offset + 2] = lut[base + 2];
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
const f = x - i;
|
|
206
|
+
const a = i * 3;
|
|
207
|
+
const b = a + 3;
|
|
208
|
+
out[offset] = lut[a] + (lut[b] - lut[a]) * f;
|
|
209
|
+
out[offset + 1] = lut[a + 1] + (lut[b + 1] - lut[a + 1]) * f;
|
|
210
|
+
out[offset + 2] = lut[a + 2] + (lut[b + 2] - lut[a + 2]) * f;
|
|
211
|
+
}
|
|
212
|
+
/** Sample a uniformly-spaced scalar curve at t∈[0,1] with linear interpolation.
|
|
213
|
+
* Out-of-range t is clamped. An empty curve samples to 0; a single value is
|
|
214
|
+
* returned as-is. */
|
|
215
|
+
export function sampleParticleCurve(lut, t) {
|
|
216
|
+
const n = lut.length;
|
|
217
|
+
if (n === 0)
|
|
218
|
+
return 0;
|
|
219
|
+
if (n === 1)
|
|
220
|
+
return lut[0];
|
|
221
|
+
const x = (t <= 0 ? 0 : t >= 1 ? 1 : t) * (n - 1);
|
|
222
|
+
const i = x | 0;
|
|
223
|
+
if (i >= n - 1)
|
|
224
|
+
return lut[n - 1];
|
|
225
|
+
return lut[i] + (lut[i + 1] - lut[i]) * (x - i);
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=curve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"curve.js","sourceRoot":"","sources":["../src/curve.ts"],"names":[],"mappings":"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"}
|