@newkrok/three-particles 2.6.3 → 2.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/index.d.ts +1782 -7
  2. package/dist/index.js +1578 -6
  3. package/dist/index.js.map +1 -0
  4. package/dist/three-particles.min.js +1 -2
  5. package/dist/three-particles.min.js.map +1 -0
  6. package/package.json +5 -7
  7. package/dist/bundle-report.json +0 -1
  8. package/dist/index.d.ts.map +0 -1
  9. package/dist/js/effects/three-particles/index.d.ts +0 -7
  10. package/dist/js/effects/three-particles/index.d.ts.map +0 -1
  11. package/dist/js/effects/three-particles/index.js +0 -6
  12. package/dist/js/effects/three-particles/shaders/particle-system-fragment-shader.glsl.d.ts +0 -3
  13. package/dist/js/effects/three-particles/shaders/particle-system-fragment-shader.glsl.d.ts.map +0 -1
  14. package/dist/js/effects/three-particles/shaders/particle-system-fragment-shader.glsl.js +0 -71
  15. package/dist/js/effects/three-particles/shaders/particle-system-vertex-shader.glsl.d.ts +0 -3
  16. package/dist/js/effects/three-particles/shaders/particle-system-vertex-shader.glsl.d.ts.map +0 -1
  17. package/dist/js/effects/three-particles/shaders/particle-system-vertex-shader.glsl.js +0 -37
  18. package/dist/js/effects/three-particles/three-particles-bezier.d.ts +0 -5
  19. package/dist/js/effects/three-particles/three-particles-bezier.d.ts.map +0 -1
  20. package/dist/js/effects/three-particles/three-particles-bezier.js +0 -62
  21. package/dist/js/effects/three-particles/three-particles-curves.d.ts +0 -108
  22. package/dist/js/effects/three-particles/three-particles-curves.d.ts.map +0 -1
  23. package/dist/js/effects/three-particles/three-particles-curves.js +0 -62
  24. package/dist/js/effects/three-particles/three-particles-enums.d.ts +0 -115
  25. package/dist/js/effects/three-particles/three-particles-enums.d.ts.map +0 -1
  26. package/dist/js/effects/three-particles/three-particles-enums.js +0 -1
  27. package/dist/js/effects/three-particles/three-particles-modifiers.d.ts +0 -73
  28. package/dist/js/effects/three-particles/three-particles-modifiers.d.ts.map +0 -1
  29. package/dist/js/effects/three-particles/three-particles-modifiers.js +0 -168
  30. package/dist/js/effects/three-particles/three-particles-utils.d.ts +0 -159
  31. package/dist/js/effects/three-particles/three-particles-utils.d.ts.map +0 -1
  32. package/dist/js/effects/three-particles/three-particles-utils.js +0 -302
  33. package/dist/js/effects/three-particles/three-particles.d.ts +0 -107
  34. package/dist/js/effects/three-particles/three-particles.d.ts.map +0 -1
  35. package/dist/js/effects/three-particles/three-particles.js +0 -972
  36. package/dist/js/effects/three-particles/types.d.ts +0 -1223
  37. package/dist/js/effects/three-particles/types.d.ts.map +0 -1
  38. package/dist/js/effects/three-particles/types.js +0 -1
  39. package/dist/three-particles.min.js.LICENSE.txt +0 -6
package/dist/index.js CHANGED
@@ -1,6 +1,1578 @@
1
- export * from './js/effects/three-particles/three-particles-bezier.js';
2
- export * from './js/effects/three-particles/three-particles-curves.js';
3
- export * from './js/effects/three-particles/three-particles-enums.js';
4
- export * from './js/effects/three-particles/three-particles-modifiers.js';
5
- export * from './js/effects/three-particles/three-particles-utils.js';
6
- export * from './js/effects/three-particles/three-particles.js';
1
+ import Easing from 'easing-functions';
2
+ import * as THREE3 from 'three';
3
+ import { ObjectUtils } from '@newkrok/three-utils';
4
+ import { Gyroscope } from 'three/examples/jsm/misc/Gyroscope.js';
5
+ import { FBM } from 'three-noise/build/three-noise.module.js';
6
+
7
+ // src/js/effects/three-particles/three-particles-bezier.ts
8
+ var cache = [];
9
+ var nCr = (n, k) => {
10
+ let z = 1;
11
+ for (let i = 1; i <= k; i++) z *= (n + 1 - i) / i;
12
+ return z;
13
+ };
14
+ var createBezierCurveFunction = (particleSystemId, bezierPoints) => {
15
+ const cacheEntry = cache.find((item) => item.bezierPoints === bezierPoints);
16
+ if (cacheEntry) {
17
+ if (!cacheEntry.referencedBy.includes(particleSystemId))
18
+ cacheEntry.referencedBy.push(particleSystemId);
19
+ return cacheEntry.curveFunction;
20
+ }
21
+ const entry = {
22
+ referencedBy: [particleSystemId],
23
+ bezierPoints,
24
+ curveFunction: (percentage) => {
25
+ if (percentage < 0) return bezierPoints[0].y;
26
+ if (percentage > 1) return bezierPoints[bezierPoints.length - 1].y;
27
+ let start = 0;
28
+ let stop = bezierPoints.length - 1;
29
+ bezierPoints.find((point, index) => {
30
+ const result = percentage < (point.percentage ?? 0);
31
+ if (result) stop = index;
32
+ else if (point.percentage !== void 0) start = index;
33
+ return result;
34
+ });
35
+ const n = stop - start;
36
+ const calculatedPercentage = (percentage - (bezierPoints[start].percentage ?? 0)) / ((bezierPoints[stop].percentage ?? 1) - (bezierPoints[start].percentage ?? 0));
37
+ let value = 0;
38
+ for (let i = 0; i <= n; i++) {
39
+ const p = bezierPoints[start + i];
40
+ const c = nCr(n, i) * Math.pow(1 - calculatedPercentage, n - i) * Math.pow(calculatedPercentage, i);
41
+ value += c * p.y;
42
+ }
43
+ return value;
44
+ }
45
+ };
46
+ cache.push(entry);
47
+ return entry.curveFunction;
48
+ };
49
+ var removeBezierCurveFunction = (particleSystemId) => {
50
+ while (true) {
51
+ const index = cache.findIndex(
52
+ (item) => item.referencedBy.includes(particleSystemId)
53
+ );
54
+ if (index === -1) break;
55
+ const entry = cache[index];
56
+ entry.referencedBy = entry.referencedBy.filter(
57
+ (id) => id !== particleSystemId
58
+ );
59
+ if (entry.referencedBy.length === 0) cache.splice(index, 1);
60
+ }
61
+ };
62
+ var getBezierCacheSize = () => cache.length;
63
+ var CurveFunctionId = /* @__PURE__ */ ((CurveFunctionId2) => {
64
+ CurveFunctionId2["BEZIER"] = "BEZIER";
65
+ CurveFunctionId2["LINEAR"] = "LINEAR";
66
+ CurveFunctionId2["QUADRATIC_IN"] = "QUADRATIC_IN";
67
+ CurveFunctionId2["QUADRATIC_OUT"] = "QUADRATIC_OUT";
68
+ CurveFunctionId2["QUADRATIC_IN_OUT"] = "QUADRATIC_IN_OUT";
69
+ CurveFunctionId2["CUBIC_IN"] = "CUBIC_IN";
70
+ CurveFunctionId2["CUBIC_OUT"] = "CUBIC_OUT";
71
+ CurveFunctionId2["CUBIC_IN_OUT"] = "CUBIC_IN_OUT";
72
+ CurveFunctionId2["QUARTIC_IN"] = "QUARTIC_IN";
73
+ CurveFunctionId2["QUARTIC_OUT"] = "QUARTIC_OUT";
74
+ CurveFunctionId2["QUARTIC_IN_OUT"] = "QUARTIC_IN_OUT";
75
+ CurveFunctionId2["QUINTIC_IN"] = "QUINTIC_IN";
76
+ CurveFunctionId2["QUINTIC_OUT"] = "QUINTIC_OUT";
77
+ CurveFunctionId2["QUINTIC_IN_OUT"] = "QUINTIC_IN_OUT";
78
+ CurveFunctionId2["SINUSOIDAL_IN"] = "SINUSOIDAL_IN";
79
+ CurveFunctionId2["SINUSOIDAL_OUT"] = "SINUSOIDAL_OUT";
80
+ CurveFunctionId2["SINUSOIDAL_IN_OUT"] = "SINUSOIDAL_IN_OUT";
81
+ CurveFunctionId2["EXPONENTIAL_IN"] = "EXPONENTIAL_IN";
82
+ CurveFunctionId2["EXPONENTIAL_OUT"] = "EXPONENTIAL_OUT";
83
+ CurveFunctionId2["EXPONENTIAL_IN_OUT"] = "EXPONENTIAL_IN_OUT";
84
+ CurveFunctionId2["CIRCULAR_IN"] = "CIRCULAR_IN";
85
+ CurveFunctionId2["CIRCULAR_OUT"] = "CIRCULAR_OUT";
86
+ CurveFunctionId2["CIRCULAR_IN_OUT"] = "CIRCULAR_IN_OUT";
87
+ CurveFunctionId2["ELASTIC_IN"] = "ELASTIC_IN";
88
+ CurveFunctionId2["ELASTIC_OUT"] = "ELASTIC_OUT";
89
+ CurveFunctionId2["ELASTIC_IN_OUT"] = "ELASTIC_IN_OUT";
90
+ CurveFunctionId2["BACK_IN"] = "BACK_IN";
91
+ CurveFunctionId2["BACK_OUT"] = "BACK_OUT";
92
+ CurveFunctionId2["BACK_IN_OUT"] = "BACK_IN_OUT";
93
+ CurveFunctionId2["BOUNCE_IN"] = "BOUNCE_IN";
94
+ CurveFunctionId2["BOUNCE_OUT"] = "BOUNCE_OUT";
95
+ CurveFunctionId2["BOUNCE_IN_OUT"] = "BOUNCE_IN_OUT";
96
+ return CurveFunctionId2;
97
+ })(CurveFunctionId || {});
98
+ var CurveFunctionIdMap = {
99
+ ["LINEAR" /* LINEAR */]: Easing.Linear.None,
100
+ ["QUADRATIC_IN" /* QUADRATIC_IN */]: Easing.Quadratic.In,
101
+ ["QUADRATIC_OUT" /* QUADRATIC_OUT */]: Easing.Quadratic.Out,
102
+ ["QUADRATIC_IN_OUT" /* QUADRATIC_IN_OUT */]: Easing.Quadratic.InOut,
103
+ ["CUBIC_IN" /* CUBIC_IN */]: Easing.Cubic.In,
104
+ ["CUBIC_OUT" /* CUBIC_OUT */]: Easing.Cubic.Out,
105
+ ["CUBIC_IN_OUT" /* CUBIC_IN_OUT */]: Easing.Cubic.InOut,
106
+ ["QUARTIC_IN" /* QUARTIC_IN */]: Easing.Quartic.In,
107
+ ["QUARTIC_OUT" /* QUARTIC_OUT */]: Easing.Quartic.Out,
108
+ ["QUARTIC_IN_OUT" /* QUARTIC_IN_OUT */]: Easing.Quartic.InOut,
109
+ ["QUINTIC_IN" /* QUINTIC_IN */]: Easing.Quintic.In,
110
+ ["QUINTIC_OUT" /* QUINTIC_OUT */]: Easing.Quintic.Out,
111
+ ["QUINTIC_IN_OUT" /* QUINTIC_IN_OUT */]: Easing.Quintic.InOut,
112
+ ["SINUSOIDAL_IN" /* SINUSOIDAL_IN */]: Easing.Sinusoidal.In,
113
+ ["SINUSOIDAL_OUT" /* SINUSOIDAL_OUT */]: Easing.Sinusoidal.Out,
114
+ ["SINUSOIDAL_IN_OUT" /* SINUSOIDAL_IN_OUT */]: Easing.Sinusoidal.InOut,
115
+ ["EXPONENTIAL_IN" /* EXPONENTIAL_IN */]: Easing.Exponential.In,
116
+ ["EXPONENTIAL_OUT" /* EXPONENTIAL_OUT */]: Easing.Exponential.Out,
117
+ ["EXPONENTIAL_IN_OUT" /* EXPONENTIAL_IN_OUT */]: Easing.Exponential.InOut,
118
+ ["CIRCULAR_IN" /* CIRCULAR_IN */]: Easing.Circular.In,
119
+ ["CIRCULAR_OUT" /* CIRCULAR_OUT */]: Easing.Circular.Out,
120
+ ["CIRCULAR_IN_OUT" /* CIRCULAR_IN_OUT */]: Easing.Circular.InOut,
121
+ ["ELASTIC_IN" /* ELASTIC_IN */]: Easing.Elastic.In,
122
+ ["ELASTIC_OUT" /* ELASTIC_OUT */]: Easing.Elastic.Out,
123
+ ["ELASTIC_IN_OUT" /* ELASTIC_IN_OUT */]: Easing.Elastic.InOut,
124
+ ["BACK_IN" /* BACK_IN */]: Easing.Back.In,
125
+ ["BACK_OUT" /* BACK_OUT */]: Easing.Back.Out,
126
+ ["BACK_IN_OUT" /* BACK_IN_OUT */]: Easing.Back.InOut,
127
+ ["BOUNCE_IN" /* BOUNCE_IN */]: Easing.Bounce.In,
128
+ ["BOUNCE_OUT" /* BOUNCE_OUT */]: Easing.Bounce.Out,
129
+ ["BOUNCE_IN_OUT" /* BOUNCE_IN_OUT */]: Easing.Bounce.InOut
130
+ };
131
+ var getCurveFunction = (curveFunctionId) => typeof curveFunctionId === "function" ? curveFunctionId : CurveFunctionIdMap[curveFunctionId];
132
+
133
+ // src/js/effects/three-particles/three-particles-enums.ts
134
+ var SimulationSpace = /* @__PURE__ */ ((SimulationSpace2) => {
135
+ SimulationSpace2["LOCAL"] = "LOCAL";
136
+ SimulationSpace2["WORLD"] = "WORLD";
137
+ return SimulationSpace2;
138
+ })(SimulationSpace || {});
139
+ var Shape = /* @__PURE__ */ ((Shape2) => {
140
+ Shape2["SPHERE"] = "SPHERE";
141
+ Shape2["CONE"] = "CONE";
142
+ Shape2["BOX"] = "BOX";
143
+ Shape2["CIRCLE"] = "CIRCLE";
144
+ Shape2["RECTANGLE"] = "RECTANGLE";
145
+ return Shape2;
146
+ })(Shape || {});
147
+ var EmitFrom = /* @__PURE__ */ ((EmitFrom2) => {
148
+ EmitFrom2["VOLUME"] = "VOLUME";
149
+ EmitFrom2["SHELL"] = "SHELL";
150
+ EmitFrom2["EDGE"] = "EDGE";
151
+ return EmitFrom2;
152
+ })(EmitFrom || {});
153
+ var TimeMode = /* @__PURE__ */ ((TimeMode2) => {
154
+ TimeMode2["LIFETIME"] = "LIFETIME";
155
+ TimeMode2["FPS"] = "FPS";
156
+ return TimeMode2;
157
+ })(TimeMode || {});
158
+ var LifeTimeCurve = /* @__PURE__ */ ((LifeTimeCurve2) => {
159
+ LifeTimeCurve2["BEZIER"] = "BEZIER";
160
+ LifeTimeCurve2["EASING"] = "EASING";
161
+ return LifeTimeCurve2;
162
+ })(LifeTimeCurve || {});
163
+ var calculateRandomPositionAndVelocityOnSphere = (position, quaternion, velocity, speed, {
164
+ radius,
165
+ radiusThickness,
166
+ arc
167
+ }) => {
168
+ const u = Math.random() * (arc / 360);
169
+ const v = Math.random();
170
+ const randomizedDistanceRatio = Math.random();
171
+ const theta = 2 * Math.PI * u;
172
+ const phi = Math.acos(2 * v - 1);
173
+ const sinPhi = Math.sin(phi);
174
+ const xDirection = sinPhi * Math.cos(theta);
175
+ const yDirection = sinPhi * Math.sin(theta);
176
+ const zDirection = Math.cos(phi);
177
+ const normalizedThickness = 1 - radiusThickness;
178
+ position.x = radius * normalizedThickness * xDirection + radius * radiusThickness * randomizedDistanceRatio * xDirection;
179
+ position.y = radius * normalizedThickness * yDirection + radius * radiusThickness * randomizedDistanceRatio * yDirection;
180
+ position.z = radius * normalizedThickness * zDirection + radius * radiusThickness * randomizedDistanceRatio * zDirection;
181
+ position.applyQuaternion(quaternion);
182
+ const speedMultiplierByPosition = 1 / position.length();
183
+ velocity.set(
184
+ position.x * speedMultiplierByPosition * speed,
185
+ position.y * speedMultiplierByPosition * speed,
186
+ position.z * speedMultiplierByPosition * speed
187
+ );
188
+ velocity.applyQuaternion(quaternion);
189
+ };
190
+ var calculateRandomPositionAndVelocityOnCone = (position, quaternion, velocity, speed, {
191
+ radius,
192
+ radiusThickness,
193
+ arc,
194
+ angle = 90
195
+ }) => {
196
+ const theta = 2 * Math.PI * Math.random() * (arc / 360);
197
+ const randomizedDistanceRatio = Math.random();
198
+ const xDirection = Math.cos(theta);
199
+ const yDirection = Math.sin(theta);
200
+ const normalizedThickness = 1 - radiusThickness;
201
+ position.x = radius * normalizedThickness * xDirection + radius * radiusThickness * randomizedDistanceRatio * xDirection;
202
+ position.y = radius * normalizedThickness * yDirection + radius * radiusThickness * randomizedDistanceRatio * yDirection;
203
+ position.z = 0;
204
+ position.applyQuaternion(quaternion);
205
+ const positionLength = position.length();
206
+ const normalizedAngle = Math.abs(
207
+ positionLength / radius * THREE3.MathUtils.degToRad(angle)
208
+ );
209
+ const sinNormalizedAngle = Math.sin(normalizedAngle);
210
+ const speedMultiplierByPosition = 1 / positionLength;
211
+ velocity.set(
212
+ position.x * sinNormalizedAngle * speedMultiplierByPosition * speed,
213
+ position.y * sinNormalizedAngle * speedMultiplierByPosition * speed,
214
+ Math.cos(normalizedAngle) * speed
215
+ );
216
+ velocity.applyQuaternion(quaternion);
217
+ };
218
+ var calculateRandomPositionAndVelocityOnBox = (position, quaternion, velocity, speed, { scale, emitFrom }) => {
219
+ const _scale = scale;
220
+ switch (emitFrom) {
221
+ case "VOLUME" /* VOLUME */:
222
+ position.x = Math.random() * _scale.x - _scale.x / 2;
223
+ position.y = Math.random() * _scale.y - _scale.y / 2;
224
+ position.z = Math.random() * _scale.z - _scale.z / 2;
225
+ break;
226
+ case "SHELL" /* SHELL */:
227
+ const side = Math.floor(Math.random() * 6);
228
+ const perpendicularAxis = side % 3;
229
+ const shellResult = [];
230
+ shellResult[perpendicularAxis] = side > 2 ? 1 : 0;
231
+ shellResult[(perpendicularAxis + 1) % 3] = Math.random();
232
+ shellResult[(perpendicularAxis + 2) % 3] = Math.random();
233
+ position.x = shellResult[0] * _scale.x - _scale.x / 2;
234
+ position.y = shellResult[1] * _scale.y - _scale.y / 2;
235
+ position.z = shellResult[2] * _scale.z - _scale.z / 2;
236
+ break;
237
+ case "EDGE" /* EDGE */:
238
+ const side2 = Math.floor(Math.random() * 6);
239
+ const perpendicularAxis2 = side2 % 3;
240
+ const edge = Math.floor(Math.random() * 4);
241
+ const edgeResult = [];
242
+ edgeResult[perpendicularAxis2] = side2 > 2 ? 1 : 0;
243
+ edgeResult[(perpendicularAxis2 + 1) % 3] = edge < 2 ? Math.random() : edge - 2;
244
+ edgeResult[(perpendicularAxis2 + 2) % 3] = edge < 2 ? edge : Math.random();
245
+ position.x = edgeResult[0] * _scale.x - _scale.x / 2;
246
+ position.y = edgeResult[1] * _scale.y - _scale.y / 2;
247
+ position.z = edgeResult[2] * _scale.z - _scale.z / 2;
248
+ break;
249
+ }
250
+ position.applyQuaternion(quaternion);
251
+ velocity.set(0, 0, speed);
252
+ velocity.applyQuaternion(quaternion);
253
+ };
254
+ var calculateRandomPositionAndVelocityOnCircle = (position, quaternion, velocity, speed, {
255
+ radius,
256
+ radiusThickness,
257
+ arc
258
+ }) => {
259
+ const theta = 2 * Math.PI * Math.random() * (arc / 360);
260
+ const randomizedDistanceRatio = Math.random();
261
+ const xDirection = Math.cos(theta);
262
+ const yDirection = Math.sin(theta);
263
+ const normalizedThickness = 1 - radiusThickness;
264
+ position.x = radius * normalizedThickness * xDirection + radius * radiusThickness * randomizedDistanceRatio * xDirection;
265
+ position.y = radius * normalizedThickness * yDirection + radius * radiusThickness * randomizedDistanceRatio * yDirection;
266
+ position.z = 0;
267
+ position.applyQuaternion(quaternion);
268
+ const positionLength = position.length();
269
+ const speedMultiplierByPosition = 1 / positionLength;
270
+ velocity.set(
271
+ position.x * speedMultiplierByPosition * speed,
272
+ position.y * speedMultiplierByPosition * speed,
273
+ 0
274
+ );
275
+ velocity.applyQuaternion(quaternion);
276
+ };
277
+ var calculateRandomPositionAndVelocityOnRectangle = (position, quaternion, velocity, speed, { rotation, scale }) => {
278
+ const _scale = scale;
279
+ const _rotation = rotation;
280
+ const xOffset = Math.random() * _scale.x - _scale.x / 2;
281
+ const yOffset = Math.random() * _scale.y - _scale.y / 2;
282
+ const rotationX = THREE3.MathUtils.degToRad(_rotation.x);
283
+ const rotationY = THREE3.MathUtils.degToRad(_rotation.y);
284
+ position.x = xOffset * Math.cos(rotationY);
285
+ position.y = yOffset * Math.cos(rotationX);
286
+ position.z = xOffset * Math.sin(rotationY) - yOffset * Math.sin(rotationX);
287
+ position.applyQuaternion(quaternion);
288
+ velocity.set(0, 0, speed);
289
+ velocity.applyQuaternion(quaternion);
290
+ };
291
+ var createDefaultParticleTexture = () => {
292
+ try {
293
+ const canvas = document.createElement("canvas");
294
+ const size = 64;
295
+ canvas.width = size;
296
+ canvas.height = size;
297
+ const context = canvas.getContext("2d");
298
+ if (context) {
299
+ const centerX = size / 2;
300
+ const centerY = size / 2;
301
+ const radius = size / 2 - 2;
302
+ context.beginPath();
303
+ context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
304
+ context.fillStyle = "white";
305
+ context.fill();
306
+ const texture = new THREE3.CanvasTexture(canvas);
307
+ texture.needsUpdate = true;
308
+ return texture;
309
+ } else {
310
+ console.warn(
311
+ "Could not get 2D context to generate default particle texture."
312
+ );
313
+ return null;
314
+ }
315
+ } catch (error) {
316
+ console.warn("Error creating default particle texture:", error);
317
+ return null;
318
+ }
319
+ };
320
+ var isLifeTimeCurve = (value) => {
321
+ return typeof value !== "number" && "type" in value;
322
+ };
323
+ var getCurveFunctionFromConfig = (particleSystemId, lifetimeCurve) => {
324
+ if (lifetimeCurve.type === "BEZIER" /* BEZIER */) {
325
+ return createBezierCurveFunction(
326
+ particleSystemId,
327
+ lifetimeCurve.bezierPoints
328
+ );
329
+ }
330
+ if (lifetimeCurve.type === "EASING" /* EASING */) {
331
+ return lifetimeCurve.curveFunction;
332
+ }
333
+ throw new Error(`Unsupported value type: ${lifetimeCurve}`);
334
+ };
335
+ var calculateValue = (particleSystemId, value, time = 0) => {
336
+ if (typeof value === "number") {
337
+ return value;
338
+ }
339
+ if ("min" in value && "max" in value) {
340
+ if (value.min === value.max) {
341
+ return value.min ?? 0;
342
+ }
343
+ return THREE3.MathUtils.randFloat(value.min ?? 0, value.max ?? 1);
344
+ }
345
+ const lifetimeCurve = value;
346
+ return getCurveFunctionFromConfig(particleSystemId, lifetimeCurve)(time) * (lifetimeCurve.scale ?? 1);
347
+ };
348
+
349
+ // src/js/effects/three-particles/three-particles-modifiers.ts
350
+ var noiseInput = new THREE3.Vector3(0, 0, 0);
351
+ var orbitalEuler = new THREE3.Euler();
352
+ var applyModifiers = ({
353
+ delta,
354
+ generalData,
355
+ normalizedConfig,
356
+ attributes,
357
+ particleLifetimePercentage,
358
+ particleIndex
359
+ }) => {
360
+ const {
361
+ particleSystemId,
362
+ startValues,
363
+ lifetimeValues,
364
+ linearVelocityData,
365
+ orbitalVelocityData,
366
+ noise
367
+ } = generalData;
368
+ const positionIndex = particleIndex * 3;
369
+ const positionArr = attributes.position.array;
370
+ if (linearVelocityData) {
371
+ const { speed, valueModifiers } = linearVelocityData[particleIndex];
372
+ const normalizedXSpeed = valueModifiers.x ? valueModifiers.x(particleLifetimePercentage) : speed.x;
373
+ const normalizedYSpeed = valueModifiers.y ? valueModifiers.y(particleLifetimePercentage) : speed.y;
374
+ const normalizedZSpeed = valueModifiers.z ? valueModifiers.z(particleLifetimePercentage) : speed.z;
375
+ positionArr[positionIndex] += normalizedXSpeed * delta;
376
+ positionArr[positionIndex + 1] += normalizedYSpeed * delta;
377
+ positionArr[positionIndex + 2] += normalizedZSpeed * delta;
378
+ attributes.position.needsUpdate = true;
379
+ }
380
+ if (orbitalVelocityData) {
381
+ const { speed, positionOffset, valueModifiers } = orbitalVelocityData[particleIndex];
382
+ positionArr[positionIndex] -= positionOffset.x;
383
+ positionArr[positionIndex + 1] -= positionOffset.y;
384
+ positionArr[positionIndex + 2] -= positionOffset.z;
385
+ const normalizedXSpeed = valueModifiers.x ? valueModifiers.x(particleLifetimePercentage) : speed.x;
386
+ const normalizedYSpeed = valueModifiers.y ? valueModifiers.y(particleLifetimePercentage) : speed.y;
387
+ const normalizedZSpeed = valueModifiers.z ? valueModifiers.z(particleLifetimePercentage) : speed.z;
388
+ orbitalEuler.set(
389
+ normalizedXSpeed * delta,
390
+ normalizedZSpeed * delta,
391
+ normalizedYSpeed * delta
392
+ );
393
+ positionOffset.applyEuler(orbitalEuler);
394
+ positionArr[positionIndex] += positionOffset.x;
395
+ positionArr[positionIndex + 1] += positionOffset.y;
396
+ positionArr[positionIndex + 2] += positionOffset.z;
397
+ attributes.position.needsUpdate = true;
398
+ }
399
+ if (normalizedConfig.sizeOverLifetime.isActive) {
400
+ const multiplier = calculateValue(
401
+ particleSystemId,
402
+ normalizedConfig.sizeOverLifetime.lifetimeCurve,
403
+ particleLifetimePercentage
404
+ );
405
+ attributes.size.array[particleIndex] = startValues.startSize[particleIndex] * multiplier;
406
+ attributes.size.needsUpdate = true;
407
+ }
408
+ if (normalizedConfig.opacityOverLifetime.isActive) {
409
+ const multiplier = calculateValue(
410
+ particleSystemId,
411
+ normalizedConfig.opacityOverLifetime.lifetimeCurve,
412
+ particleLifetimePercentage
413
+ );
414
+ attributes.colorA.array[particleIndex] = startValues.startOpacity[particleIndex] * multiplier;
415
+ attributes.colorA.needsUpdate = true;
416
+ }
417
+ if (normalizedConfig.colorOverLifetime.isActive) {
418
+ const rMultiplier = calculateValue(
419
+ particleSystemId,
420
+ normalizedConfig.colorOverLifetime.r,
421
+ particleLifetimePercentage
422
+ );
423
+ const gMultiplier = calculateValue(
424
+ particleSystemId,
425
+ normalizedConfig.colorOverLifetime.g,
426
+ particleLifetimePercentage
427
+ );
428
+ const bMultiplier = calculateValue(
429
+ particleSystemId,
430
+ normalizedConfig.colorOverLifetime.b,
431
+ particleLifetimePercentage
432
+ );
433
+ attributes.colorR.array[particleIndex] = startValues.startColorR[particleIndex] * rMultiplier;
434
+ attributes.colorG.array[particleIndex] = startValues.startColorG[particleIndex] * gMultiplier;
435
+ attributes.colorB.array[particleIndex] = startValues.startColorB[particleIndex] * bMultiplier;
436
+ attributes.colorR.needsUpdate = true;
437
+ attributes.colorG.needsUpdate = true;
438
+ attributes.colorB.needsUpdate = true;
439
+ }
440
+ if (lifetimeValues.rotationOverLifetime) {
441
+ attributes.rotation.array[particleIndex] += lifetimeValues.rotationOverLifetime[particleIndex] * delta * 0.02;
442
+ attributes.rotation.needsUpdate = true;
443
+ }
444
+ if (noise.isActive) {
445
+ const {
446
+ sampler,
447
+ strength,
448
+ noisePower,
449
+ offsets,
450
+ positionAmount,
451
+ rotationAmount,
452
+ sizeAmount
453
+ } = noise;
454
+ let noiseOnPosition;
455
+ const noisePosition = (particleLifetimePercentage + (offsets ? offsets[particleIndex] : 0)) * 10 * strength;
456
+ noiseInput.set(noisePosition, 0, 0);
457
+ noiseOnPosition = sampler.get3(noiseInput);
458
+ positionArr[positionIndex] += noiseOnPosition * noisePower * positionAmount;
459
+ if (rotationAmount !== 0) {
460
+ attributes.rotation.array[particleIndex] += noiseOnPosition * noisePower * rotationAmount;
461
+ attributes.rotation.needsUpdate = true;
462
+ }
463
+ if (sizeAmount !== 0) {
464
+ attributes.size.array[particleIndex] += noiseOnPosition * noisePower * sizeAmount;
465
+ attributes.size.needsUpdate = true;
466
+ }
467
+ noiseInput.set(noisePosition, noisePosition, 0);
468
+ noiseOnPosition = sampler.get3(noiseInput);
469
+ positionArr[positionIndex + 1] += noiseOnPosition * noisePower * positionAmount;
470
+ noiseInput.set(noisePosition, noisePosition, noisePosition);
471
+ noiseOnPosition = sampler.get3(noiseInput);
472
+ positionArr[positionIndex + 2] += noiseOnPosition * noisePower * positionAmount;
473
+ attributes.position.needsUpdate = true;
474
+ }
475
+ };
476
+
477
+ // src/js/effects/three-particles/shaders/particle-system-fragment-shader.glsl.ts
478
+ var ParticleSystemFragmentShader = `
479
+ uniform sampler2D map;
480
+ uniform float elapsed;
481
+ uniform float fps;
482
+ uniform bool useFPSForFrameIndex;
483
+ uniform vec2 tiles;
484
+ uniform bool discardBackgroundColor;
485
+ uniform vec3 backgroundColor;
486
+ uniform float backgroundColorTolerance;
487
+
488
+ varying vec4 vColor;
489
+ varying float vLifetime;
490
+ varying float vStartLifetime;
491
+ varying float vRotation;
492
+ varying float vStartFrame;
493
+
494
+ #include <common>
495
+ #include <logdepthbuf_pars_fragment>
496
+
497
+ void main()
498
+ {
499
+ gl_FragColor = vColor;
500
+ float mid = 0.5;
501
+
502
+ float frameIndex = round(vStartFrame) + (
503
+ useFPSForFrameIndex == true
504
+ ? fps == 0.0
505
+ ? 0.0
506
+ : max((vLifetime / 1000.0) * fps, 0.0)
507
+ : max(min(floor(min(vLifetime / vStartLifetime, 1.0) * (tiles.x * tiles.y)), tiles.x * tiles.y - 1.0), 0.0)
508
+ );
509
+
510
+ float spriteXIndex = floor(mod(frameIndex, tiles.x));
511
+ float spriteYIndex = floor(mod(frameIndex / tiles.x, tiles.y));
512
+
513
+ vec2 frameUV = vec2(
514
+ gl_PointCoord.x / tiles.x + spriteXIndex / tiles.x,
515
+ gl_PointCoord.y / tiles.y + spriteYIndex / tiles.y);
516
+
517
+ vec2 center = vec2(0.5, 0.5);
518
+ vec2 centeredPoint = gl_PointCoord - center;
519
+
520
+ mat2 rotation = mat2(
521
+ cos(vRotation), sin(vRotation),
522
+ -sin(vRotation), cos(vRotation)
523
+ );
524
+
525
+ centeredPoint = rotation * centeredPoint;
526
+ vec2 centeredMiddlePoint = vec2(
527
+ centeredPoint.x + center.x,
528
+ centeredPoint.y + center.y
529
+ );
530
+
531
+ float dist = distance(centeredMiddlePoint, center);
532
+ if (dist > 0.5) discard;
533
+
534
+ vec2 uvPoint = vec2(
535
+ centeredMiddlePoint.x / tiles.x + spriteXIndex / tiles.x,
536
+ centeredMiddlePoint.y / tiles.y + spriteYIndex / tiles.y
537
+ );
538
+
539
+ vec4 rotatedTexture = texture2D(map, uvPoint);
540
+
541
+ gl_FragColor = gl_FragColor * rotatedTexture;
542
+
543
+ if (discardBackgroundColor && abs(length(rotatedTexture.rgb - backgroundColor.rgb)) < backgroundColorTolerance) discard;
544
+
545
+ #include <logdepthbuf_fragment>
546
+ }
547
+ `;
548
+ var particle_system_fragment_shader_glsl_default = ParticleSystemFragmentShader;
549
+
550
+ // src/js/effects/three-particles/shaders/particle-system-vertex-shader.glsl.ts
551
+ var ParticleSystemVertexShader = `
552
+ attribute float size;
553
+ attribute float colorR;
554
+ attribute float colorG;
555
+ attribute float colorB;
556
+ attribute float colorA;
557
+ attribute float lifetime;
558
+ attribute float startLifetime;
559
+ attribute float rotation;
560
+ attribute float startFrame;
561
+
562
+ varying mat4 vPosition;
563
+ varying vec4 vColor;
564
+ varying float vLifetime;
565
+ varying float vStartLifetime;
566
+ varying float vRotation;
567
+ varying float vStartFrame;
568
+
569
+ #include <common>
570
+ #include <logdepthbuf_pars_vertex>
571
+
572
+ void main()
573
+ {
574
+ vColor = vec4(colorR, colorG, colorB, colorA);
575
+ vLifetime = lifetime;
576
+ vStartLifetime = startLifetime;
577
+ vRotation = rotation;
578
+ vStartFrame = startFrame;
579
+
580
+ vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
581
+ gl_PointSize = size * (100.0 / length(mvPosition.xyz));
582
+ gl_Position = projectionMatrix * mvPosition;
583
+
584
+ #include <logdepthbuf_vertex>
585
+ }
586
+ `;
587
+ var particle_system_vertex_shader_glsl_default = ParticleSystemVertexShader;
588
+
589
+ // src/js/effects/three-particles/three-particles.ts
590
+ var _particleSystemId = 0;
591
+ var createdParticleSystems = [];
592
+ var _lastWorldPositionSnapshot = new THREE3.Vector3();
593
+ var _distanceStep = { x: 0, y: 0, z: 0 };
594
+ var _tempPosition = { x: 0, y: 0, z: 0 };
595
+ var _modifierParams = {
596
+ delta: 0,
597
+ generalData: null,
598
+ normalizedConfig: null,
599
+ attributes: null,
600
+ particleLifetimePercentage: 0,
601
+ particleIndex: 0
602
+ };
603
+ var blendingMap = {
604
+ "THREE.NoBlending": THREE3.NoBlending,
605
+ "THREE.NormalBlending": THREE3.NormalBlending,
606
+ "THREE.AdditiveBlending": THREE3.AdditiveBlending,
607
+ "THREE.SubtractiveBlending": THREE3.SubtractiveBlending,
608
+ "THREE.MultiplyBlending": THREE3.MultiplyBlending
609
+ };
610
+ var getDefaultParticleSystemConfig = () => JSON.parse(JSON.stringify(DEFAULT_PARTICLE_SYSTEM_CONFIG));
611
+ var DEFAULT_PARTICLE_SYSTEM_CONFIG = {
612
+ transform: {
613
+ position: new THREE3.Vector3(),
614
+ rotation: new THREE3.Vector3(),
615
+ scale: new THREE3.Vector3(1, 1, 1)
616
+ },
617
+ duration: 5,
618
+ looping: true,
619
+ startDelay: 0,
620
+ startLifetime: 5,
621
+ startSpeed: 1,
622
+ startSize: 1,
623
+ startOpacity: 1,
624
+ startRotation: 0,
625
+ startColor: {
626
+ min: { r: 1, g: 1, b: 1 },
627
+ max: { r: 1, g: 1, b: 1 }
628
+ },
629
+ gravity: 0,
630
+ simulationSpace: "LOCAL" /* LOCAL */,
631
+ maxParticles: 100,
632
+ emission: {
633
+ rateOverTime: 10,
634
+ rateOverDistance: 0,
635
+ bursts: []
636
+ },
637
+ shape: {
638
+ shape: "SPHERE" /* SPHERE */,
639
+ sphere: {
640
+ radius: 1,
641
+ radiusThickness: 1,
642
+ arc: 360
643
+ },
644
+ cone: {
645
+ angle: 25,
646
+ radius: 1,
647
+ radiusThickness: 1,
648
+ arc: 360
649
+ },
650
+ circle: {
651
+ radius: 1,
652
+ radiusThickness: 1,
653
+ arc: 360
654
+ },
655
+ rectangle: {
656
+ rotation: { x: 0, y: 0 },
657
+ // TODO: add z rotation
658
+ scale: { x: 1, y: 1 }
659
+ },
660
+ box: {
661
+ scale: { x: 1, y: 1, z: 1 },
662
+ emitFrom: "VOLUME" /* VOLUME */
663
+ }
664
+ },
665
+ map: void 0,
666
+ renderer: {
667
+ blending: THREE3.NormalBlending,
668
+ discardBackgroundColor: false,
669
+ backgroundColorTolerance: 1,
670
+ backgroundColor: { r: 1, g: 1, b: 1 },
671
+ transparent: true,
672
+ depthTest: true,
673
+ depthWrite: false
674
+ },
675
+ velocityOverLifetime: {
676
+ isActive: false,
677
+ linear: {
678
+ x: 0,
679
+ y: 0,
680
+ z: 0
681
+ },
682
+ orbital: {
683
+ x: 0,
684
+ y: 0,
685
+ z: 0
686
+ }
687
+ },
688
+ sizeOverLifetime: {
689
+ isActive: false,
690
+ lifetimeCurve: {
691
+ type: "BEZIER" /* BEZIER */,
692
+ scale: 1,
693
+ bezierPoints: [
694
+ { x: 0, y: 0, percentage: 0 },
695
+ { x: 1, y: 1, percentage: 1 }
696
+ ]
697
+ }
698
+ },
699
+ colorOverLifetime: {
700
+ isActive: false,
701
+ r: {
702
+ type: "BEZIER" /* BEZIER */,
703
+ scale: 1,
704
+ bezierPoints: [
705
+ { x: 0, y: 1, percentage: 0 },
706
+ { x: 1, y: 1, percentage: 1 }
707
+ ]
708
+ },
709
+ g: {
710
+ type: "BEZIER" /* BEZIER */,
711
+ scale: 1,
712
+ bezierPoints: [
713
+ { x: 0, y: 1, percentage: 0 },
714
+ { x: 1, y: 1, percentage: 1 }
715
+ ]
716
+ },
717
+ b: {
718
+ type: "BEZIER" /* BEZIER */,
719
+ scale: 1,
720
+ bezierPoints: [
721
+ { x: 0, y: 1, percentage: 0 },
722
+ { x: 1, y: 1, percentage: 1 }
723
+ ]
724
+ }
725
+ },
726
+ opacityOverLifetime: {
727
+ isActive: false,
728
+ lifetimeCurve: {
729
+ type: "BEZIER" /* BEZIER */,
730
+ scale: 1,
731
+ bezierPoints: [
732
+ { x: 0, y: 0, percentage: 0 },
733
+ { x: 1, y: 1, percentage: 1 }
734
+ ]
735
+ }
736
+ },
737
+ rotationOverLifetime: {
738
+ isActive: false,
739
+ min: 0,
740
+ max: 0
741
+ },
742
+ noise: {
743
+ isActive: false,
744
+ useRandomOffset: false,
745
+ strength: 1,
746
+ frequency: 0.5,
747
+ octaves: 1,
748
+ positionAmount: 1,
749
+ rotationAmount: 0,
750
+ sizeAmount: 0
751
+ },
752
+ textureSheetAnimation: {
753
+ tiles: new THREE3.Vector2(1, 1),
754
+ timeMode: "LIFETIME" /* LIFETIME */,
755
+ fps: 30,
756
+ startFrame: 0
757
+ }
758
+ };
759
+ var createFloat32Attributes = ({
760
+ geometry,
761
+ propertyName,
762
+ maxParticles,
763
+ factory
764
+ }) => {
765
+ const array = new Float32Array(maxParticles);
766
+ if (typeof factory === "function") {
767
+ for (let i = 0; i < maxParticles; i++) {
768
+ array[i] = factory(void 0, i);
769
+ }
770
+ } else {
771
+ array.fill(factory);
772
+ }
773
+ geometry.setAttribute(propertyName, new THREE3.BufferAttribute(array, 1));
774
+ };
775
+ var calculatePositionAndVelocity = (generalData, { shape, sphere, cone, circle, rectangle, box }, startSpeed, position, velocity) => {
776
+ const calculatedStartSpeed = calculateValue(
777
+ generalData.particleSystemId,
778
+ startSpeed,
779
+ generalData.normalizedLifetimePercentage
780
+ );
781
+ switch (shape) {
782
+ case "SPHERE" /* SPHERE */:
783
+ calculateRandomPositionAndVelocityOnSphere(
784
+ position,
785
+ generalData.wrapperQuaternion,
786
+ velocity,
787
+ calculatedStartSpeed,
788
+ sphere
789
+ );
790
+ break;
791
+ case "CONE" /* CONE */:
792
+ calculateRandomPositionAndVelocityOnCone(
793
+ position,
794
+ generalData.wrapperQuaternion,
795
+ velocity,
796
+ calculatedStartSpeed,
797
+ cone
798
+ );
799
+ break;
800
+ case "CIRCLE" /* CIRCLE */:
801
+ calculateRandomPositionAndVelocityOnCircle(
802
+ position,
803
+ generalData.wrapperQuaternion,
804
+ velocity,
805
+ calculatedStartSpeed,
806
+ circle
807
+ );
808
+ break;
809
+ case "RECTANGLE" /* RECTANGLE */:
810
+ calculateRandomPositionAndVelocityOnRectangle(
811
+ position,
812
+ generalData.wrapperQuaternion,
813
+ velocity,
814
+ calculatedStartSpeed,
815
+ rectangle
816
+ );
817
+ break;
818
+ case "BOX" /* BOX */:
819
+ calculateRandomPositionAndVelocityOnBox(
820
+ position,
821
+ generalData.wrapperQuaternion,
822
+ velocity,
823
+ calculatedStartSpeed,
824
+ box
825
+ );
826
+ break;
827
+ }
828
+ };
829
+ var destroyParticleSystem = (particleSystem) => {
830
+ createdParticleSystems = createdParticleSystems.filter(
831
+ ({
832
+ particleSystem: savedParticleSystem,
833
+ wrapper,
834
+ generalData: { particleSystemId }
835
+ }) => {
836
+ if (savedParticleSystem !== particleSystem && wrapper !== particleSystem) {
837
+ return true;
838
+ }
839
+ removeBezierCurveFunction(particleSystemId);
840
+ savedParticleSystem.geometry.dispose();
841
+ if (Array.isArray(savedParticleSystem.material))
842
+ savedParticleSystem.material.forEach((material) => material.dispose());
843
+ else savedParticleSystem.material.dispose();
844
+ if (savedParticleSystem.parent)
845
+ savedParticleSystem.parent.remove(savedParticleSystem);
846
+ return false;
847
+ }
848
+ );
849
+ };
850
+ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow) => {
851
+ const now = externalNow || Date.now();
852
+ const generalData = {
853
+ particleSystemId: _particleSystemId++,
854
+ normalizedLifetimePercentage: 0,
855
+ distanceFromLastEmitByDistance: 0,
856
+ lastWorldPosition: new THREE3.Vector3(-99999),
857
+ currentWorldPosition: new THREE3.Vector3(-99999),
858
+ worldPositionChange: new THREE3.Vector3(),
859
+ worldQuaternion: new THREE3.Quaternion(),
860
+ wrapperQuaternion: new THREE3.Quaternion(),
861
+ lastWorldQuaternion: new THREE3.Quaternion(-99999),
862
+ worldEuler: new THREE3.Euler(),
863
+ gravityVelocity: new THREE3.Vector3(0, 0, 0),
864
+ startValues: {},
865
+ linearVelocityData: void 0,
866
+ orbitalVelocityData: void 0,
867
+ lifetimeValues: {},
868
+ creationTimes: [],
869
+ noise: {
870
+ isActive: false,
871
+ strength: 0,
872
+ noisePower: 0,
873
+ positionAmount: 0,
874
+ rotationAmount: 0,
875
+ sizeAmount: 0
876
+ },
877
+ isEnabled: true
878
+ };
879
+ const normalizedConfig = ObjectUtils.deepMerge(
880
+ DEFAULT_PARTICLE_SYSTEM_CONFIG,
881
+ config,
882
+ { applyToFirstObject: false, skippedProperties: [] }
883
+ );
884
+ let particleMap = normalizedConfig.map || createDefaultParticleTexture();
885
+ const {
886
+ transform,
887
+ duration,
888
+ looping,
889
+ startDelay,
890
+ startLifetime,
891
+ startSpeed,
892
+ startSize,
893
+ startRotation,
894
+ startColor,
895
+ startOpacity,
896
+ gravity,
897
+ simulationSpace,
898
+ maxParticles,
899
+ emission,
900
+ shape,
901
+ renderer,
902
+ noise,
903
+ velocityOverLifetime,
904
+ onUpdate,
905
+ onComplete,
906
+ textureSheetAnimation
907
+ } = normalizedConfig;
908
+ if (typeof renderer?.blending === "string")
909
+ renderer.blending = blendingMap[renderer.blending];
910
+ const startPositions = Array.from(
911
+ { length: maxParticles },
912
+ () => new THREE3.Vector3()
913
+ );
914
+ const velocities = Array.from(
915
+ { length: maxParticles },
916
+ () => new THREE3.Vector3()
917
+ );
918
+ generalData.creationTimes = Array.from({ length: maxParticles }, () => 0);
919
+ const freeList = Array.from(
920
+ { length: maxParticles },
921
+ (_, i) => maxParticles - 1 - i
922
+ );
923
+ if (velocityOverLifetime.isActive) {
924
+ generalData.linearVelocityData = Array.from(
925
+ { length: maxParticles },
926
+ () => ({
927
+ speed: new THREE3.Vector3(
928
+ velocityOverLifetime.linear.x ? calculateValue(
929
+ generalData.particleSystemId,
930
+ velocityOverLifetime.linear.x,
931
+ 0
932
+ ) : 0,
933
+ velocityOverLifetime.linear.y ? calculateValue(
934
+ generalData.particleSystemId,
935
+ velocityOverLifetime.linear.y,
936
+ 0
937
+ ) : 0,
938
+ velocityOverLifetime.linear.z ? calculateValue(
939
+ generalData.particleSystemId,
940
+ velocityOverLifetime.linear.z,
941
+ 0
942
+ ) : 0
943
+ ),
944
+ valueModifiers: {
945
+ x: isLifeTimeCurve(velocityOverLifetime.linear.x || 0) ? getCurveFunctionFromConfig(
946
+ generalData.particleSystemId,
947
+ velocityOverLifetime.linear.x
948
+ ) : void 0,
949
+ y: isLifeTimeCurve(velocityOverLifetime.linear.y || 0) ? getCurveFunctionFromConfig(
950
+ generalData.particleSystemId,
951
+ velocityOverLifetime.linear.y
952
+ ) : void 0,
953
+ z: isLifeTimeCurve(velocityOverLifetime.linear.z || 0) ? getCurveFunctionFromConfig(
954
+ generalData.particleSystemId,
955
+ velocityOverLifetime.linear.z
956
+ ) : void 0
957
+ }
958
+ })
959
+ );
960
+ generalData.orbitalVelocityData = Array.from(
961
+ { length: maxParticles },
962
+ () => ({
963
+ speed: new THREE3.Vector3(
964
+ velocityOverLifetime.orbital.x ? calculateValue(
965
+ generalData.particleSystemId,
966
+ velocityOverLifetime.orbital.x,
967
+ 0
968
+ ) : 0,
969
+ velocityOverLifetime.orbital.y ? calculateValue(
970
+ generalData.particleSystemId,
971
+ velocityOverLifetime.orbital.y,
972
+ 0
973
+ ) : 0,
974
+ velocityOverLifetime.orbital.z ? calculateValue(
975
+ generalData.particleSystemId,
976
+ velocityOverLifetime.orbital.z,
977
+ 0
978
+ ) : 0
979
+ ),
980
+ valueModifiers: {
981
+ x: isLifeTimeCurve(velocityOverLifetime.orbital.x || 0) ? getCurveFunctionFromConfig(
982
+ generalData.particleSystemId,
983
+ velocityOverLifetime.orbital.x
984
+ ) : void 0,
985
+ y: isLifeTimeCurve(velocityOverLifetime.orbital.y || 0) ? getCurveFunctionFromConfig(
986
+ generalData.particleSystemId,
987
+ velocityOverLifetime.orbital.y
988
+ ) : void 0,
989
+ z: isLifeTimeCurve(velocityOverLifetime.orbital.z || 0) ? getCurveFunctionFromConfig(
990
+ generalData.particleSystemId,
991
+ velocityOverLifetime.orbital.z
992
+ ) : void 0
993
+ },
994
+ positionOffset: new THREE3.Vector3()
995
+ })
996
+ );
997
+ }
998
+ const startValueKeys = [
999
+ "startSize",
1000
+ "startOpacity"
1001
+ ];
1002
+ startValueKeys.forEach((key) => {
1003
+ generalData.startValues[key] = Array.from(
1004
+ { length: maxParticles },
1005
+ () => calculateValue(
1006
+ generalData.particleSystemId,
1007
+ normalizedConfig[key],
1008
+ 0
1009
+ )
1010
+ );
1011
+ });
1012
+ generalData.startValues.startColorR = Array.from(
1013
+ { length: maxParticles },
1014
+ () => 0
1015
+ );
1016
+ generalData.startValues.startColorG = Array.from(
1017
+ { length: maxParticles },
1018
+ () => 0
1019
+ );
1020
+ generalData.startValues.startColorB = Array.from(
1021
+ { length: maxParticles },
1022
+ () => 0
1023
+ );
1024
+ const lifetimeValueKeys = [
1025
+ "rotationOverLifetime"
1026
+ ];
1027
+ lifetimeValueKeys.forEach((key) => {
1028
+ const value = normalizedConfig[key];
1029
+ if (value.isActive)
1030
+ generalData.lifetimeValues[key] = Array.from(
1031
+ { length: maxParticles },
1032
+ () => THREE3.MathUtils.randFloat(value.min, value.max)
1033
+ );
1034
+ });
1035
+ generalData.noise = {
1036
+ isActive: noise.isActive,
1037
+ strength: noise.strength,
1038
+ noisePower: 0.15 * noise.strength,
1039
+ positionAmount: noise.positionAmount,
1040
+ rotationAmount: noise.rotationAmount,
1041
+ sizeAmount: noise.sizeAmount,
1042
+ sampler: noise.isActive ? new FBM({
1043
+ seed: Math.random(),
1044
+ scale: noise.frequency,
1045
+ octaves: noise.octaves
1046
+ }) : void 0,
1047
+ offsets: noise.useRandomOffset ? Array.from({ length: maxParticles }, () => Math.random() * 100) : void 0
1048
+ };
1049
+ if (emission.bursts && emission.bursts.length > 0) {
1050
+ generalData.burstStates = emission.bursts.map(() => ({
1051
+ cyclesExecuted: 0,
1052
+ lastCycleTime: 0,
1053
+ probabilityPassed: false
1054
+ }));
1055
+ }
1056
+ const material = new THREE3.ShaderMaterial({
1057
+ uniforms: {
1058
+ elapsed: {
1059
+ value: 0
1060
+ },
1061
+ map: {
1062
+ value: particleMap
1063
+ },
1064
+ tiles: {
1065
+ value: textureSheetAnimation.tiles
1066
+ },
1067
+ fps: {
1068
+ value: textureSheetAnimation.fps
1069
+ },
1070
+ useFPSForFrameIndex: {
1071
+ value: textureSheetAnimation.timeMode === "FPS" /* FPS */
1072
+ },
1073
+ backgroundColor: {
1074
+ value: renderer.backgroundColor
1075
+ },
1076
+ discardBackgroundColor: {
1077
+ value: renderer.discardBackgroundColor
1078
+ },
1079
+ backgroundColorTolerance: {
1080
+ value: renderer.backgroundColorTolerance
1081
+ }
1082
+ },
1083
+ vertexShader: particle_system_vertex_shader_glsl_default,
1084
+ fragmentShader: particle_system_fragment_shader_glsl_default,
1085
+ transparent: renderer.transparent,
1086
+ blending: renderer.blending,
1087
+ depthTest: renderer.depthTest,
1088
+ depthWrite: renderer.depthWrite
1089
+ });
1090
+ const geometry = new THREE3.BufferGeometry();
1091
+ for (let i = 0; i < maxParticles; i++)
1092
+ calculatePositionAndVelocity(
1093
+ generalData,
1094
+ shape,
1095
+ startSpeed,
1096
+ startPositions[i],
1097
+ velocities[i]
1098
+ );
1099
+ const positionArray = new Float32Array(maxParticles * 3);
1100
+ for (let i = 0; i < maxParticles; i++) {
1101
+ positionArray[i * 3] = startPositions[i].x;
1102
+ positionArray[i * 3 + 1] = startPositions[i].y;
1103
+ positionArray[i * 3 + 2] = startPositions[i].z;
1104
+ }
1105
+ geometry.setAttribute(
1106
+ "position",
1107
+ new THREE3.BufferAttribute(positionArray, 3)
1108
+ );
1109
+ createFloat32Attributes({
1110
+ geometry,
1111
+ propertyName: "isActive",
1112
+ maxParticles,
1113
+ factory: 0
1114
+ });
1115
+ createFloat32Attributes({
1116
+ geometry,
1117
+ propertyName: "lifetime",
1118
+ maxParticles,
1119
+ factory: 0
1120
+ });
1121
+ createFloat32Attributes({
1122
+ geometry,
1123
+ propertyName: "startLifetime",
1124
+ maxParticles,
1125
+ factory: () => calculateValue(generalData.particleSystemId, startLifetime, 0) * 1e3
1126
+ });
1127
+ createFloat32Attributes({
1128
+ geometry,
1129
+ propertyName: "startFrame",
1130
+ maxParticles,
1131
+ factory: () => textureSheetAnimation.startFrame ? calculateValue(
1132
+ generalData.particleSystemId,
1133
+ textureSheetAnimation.startFrame,
1134
+ 0
1135
+ ) : 0
1136
+ });
1137
+ createFloat32Attributes({
1138
+ geometry,
1139
+ propertyName: "opacity",
1140
+ maxParticles,
1141
+ factory: () => calculateValue(generalData.particleSystemId, startOpacity, 0)
1142
+ });
1143
+ createFloat32Attributes({
1144
+ geometry,
1145
+ propertyName: "rotation",
1146
+ maxParticles,
1147
+ factory: () => calculateValue(generalData.particleSystemId, startRotation, 0)
1148
+ });
1149
+ createFloat32Attributes({
1150
+ geometry,
1151
+ propertyName: "size",
1152
+ maxParticles,
1153
+ factory: (_, index) => generalData.startValues.startSize[index]
1154
+ });
1155
+ createFloat32Attributes({
1156
+ geometry,
1157
+ propertyName: "rotation",
1158
+ maxParticles,
1159
+ factory: 0
1160
+ });
1161
+ const colorRandomRatio = Math.random();
1162
+ createFloat32Attributes({
1163
+ geometry,
1164
+ propertyName: "colorR",
1165
+ maxParticles,
1166
+ factory: () => startColor.min.r + colorRandomRatio * (startColor.max.r - startColor.min.r)
1167
+ });
1168
+ createFloat32Attributes({
1169
+ geometry,
1170
+ propertyName: "colorG",
1171
+ maxParticles,
1172
+ factory: () => startColor.min.g + colorRandomRatio * (startColor.max.g - startColor.min.g)
1173
+ });
1174
+ createFloat32Attributes({
1175
+ geometry,
1176
+ propertyName: "colorB",
1177
+ maxParticles,
1178
+ factory: () => startColor.min.b + colorRandomRatio * (startColor.max.b - startColor.min.b)
1179
+ });
1180
+ createFloat32Attributes({
1181
+ geometry,
1182
+ propertyName: "colorA",
1183
+ maxParticles,
1184
+ factory: 0
1185
+ });
1186
+ const deactivateParticle = (particleIndex) => {
1187
+ geometry.attributes.isActive.array[particleIndex] = 0;
1188
+ geometry.attributes.colorA.array[particleIndex] = 0;
1189
+ geometry.attributes.colorA.needsUpdate = true;
1190
+ freeList.push(particleIndex);
1191
+ };
1192
+ const activateParticle = ({
1193
+ particleIndex,
1194
+ activationTime,
1195
+ position
1196
+ }) => {
1197
+ geometry.attributes.isActive.array[particleIndex] = 1;
1198
+ generalData.creationTimes[particleIndex] = activationTime;
1199
+ if (generalData.noise.offsets)
1200
+ generalData.noise.offsets[particleIndex] = Math.random() * 100;
1201
+ const colorRandomRatio2 = Math.random();
1202
+ geometry.attributes.colorR.array[particleIndex] = startColor.min.r + colorRandomRatio2 * (startColor.max.r - startColor.min.r);
1203
+ geometry.attributes.colorR.needsUpdate = true;
1204
+ geometry.attributes.colorG.array[particleIndex] = startColor.min.g + colorRandomRatio2 * (startColor.max.g - startColor.min.g);
1205
+ geometry.attributes.colorG.needsUpdate = true;
1206
+ geometry.attributes.colorB.array[particleIndex] = startColor.min.b + colorRandomRatio2 * (startColor.max.b - startColor.min.b);
1207
+ geometry.attributes.colorB.needsUpdate = true;
1208
+ generalData.startValues.startColorR[particleIndex] = geometry.attributes.colorR.array[particleIndex];
1209
+ generalData.startValues.startColorG[particleIndex] = geometry.attributes.colorG.array[particleIndex];
1210
+ generalData.startValues.startColorB[particleIndex] = geometry.attributes.colorB.array[particleIndex];
1211
+ geometry.attributes.startFrame.array[particleIndex] = textureSheetAnimation.startFrame ? calculateValue(
1212
+ generalData.particleSystemId,
1213
+ textureSheetAnimation.startFrame,
1214
+ 0
1215
+ ) : 0;
1216
+ geometry.attributes.startFrame.needsUpdate = true;
1217
+ geometry.attributes.startLifetime.array[particleIndex] = calculateValue(
1218
+ generalData.particleSystemId,
1219
+ startLifetime,
1220
+ generalData.normalizedLifetimePercentage
1221
+ ) * 1e3;
1222
+ geometry.attributes.startLifetime.needsUpdate = true;
1223
+ generalData.startValues.startSize[particleIndex] = calculateValue(
1224
+ generalData.particleSystemId,
1225
+ startSize,
1226
+ generalData.normalizedLifetimePercentage
1227
+ );
1228
+ geometry.attributes.size.array[particleIndex] = generalData.startValues.startSize[particleIndex];
1229
+ geometry.attributes.size.needsUpdate = true;
1230
+ generalData.startValues.startOpacity[particleIndex] = calculateValue(
1231
+ generalData.particleSystemId,
1232
+ startOpacity,
1233
+ generalData.normalizedLifetimePercentage
1234
+ );
1235
+ geometry.attributes.colorA.array[particleIndex] = generalData.startValues.startOpacity[particleIndex];
1236
+ geometry.attributes.colorA.needsUpdate = true;
1237
+ geometry.attributes.rotation.array[particleIndex] = calculateValue(
1238
+ generalData.particleSystemId,
1239
+ startRotation,
1240
+ generalData.normalizedLifetimePercentage
1241
+ );
1242
+ geometry.attributes.rotation.needsUpdate = true;
1243
+ if (normalizedConfig.rotationOverLifetime.isActive)
1244
+ generalData.lifetimeValues.rotationOverLifetime[particleIndex] = THREE3.MathUtils.randFloat(
1245
+ normalizedConfig.rotationOverLifetime.min,
1246
+ normalizedConfig.rotationOverLifetime.max
1247
+ );
1248
+ calculatePositionAndVelocity(
1249
+ generalData,
1250
+ shape,
1251
+ startSpeed,
1252
+ startPositions[particleIndex],
1253
+ velocities[particleIndex]
1254
+ );
1255
+ const positionIndex = Math.floor(particleIndex * 3);
1256
+ geometry.attributes.position.array[positionIndex] = position.x + startPositions[particleIndex].x;
1257
+ geometry.attributes.position.array[positionIndex + 1] = position.y + startPositions[particleIndex].y;
1258
+ geometry.attributes.position.array[positionIndex + 2] = position.z + startPositions[particleIndex].z;
1259
+ geometry.attributes.position.needsUpdate = true;
1260
+ if (generalData.linearVelocityData) {
1261
+ generalData.linearVelocityData[particleIndex].speed.set(
1262
+ normalizedConfig.velocityOverLifetime.linear.x ? calculateValue(
1263
+ generalData.particleSystemId,
1264
+ normalizedConfig.velocityOverLifetime.linear.x,
1265
+ 0
1266
+ ) : 0,
1267
+ normalizedConfig.velocityOverLifetime.linear.y ? calculateValue(
1268
+ generalData.particleSystemId,
1269
+ normalizedConfig.velocityOverLifetime.linear.y,
1270
+ 0
1271
+ ) : 0,
1272
+ normalizedConfig.velocityOverLifetime.linear.z ? calculateValue(
1273
+ generalData.particleSystemId,
1274
+ normalizedConfig.velocityOverLifetime.linear.z,
1275
+ 0
1276
+ ) : 0
1277
+ );
1278
+ }
1279
+ if (generalData.orbitalVelocityData) {
1280
+ generalData.orbitalVelocityData[particleIndex].speed.set(
1281
+ normalizedConfig.velocityOverLifetime.orbital.x ? calculateValue(
1282
+ generalData.particleSystemId,
1283
+ normalizedConfig.velocityOverLifetime.orbital.x,
1284
+ 0
1285
+ ) : 0,
1286
+ normalizedConfig.velocityOverLifetime.orbital.y ? calculateValue(
1287
+ generalData.particleSystemId,
1288
+ normalizedConfig.velocityOverLifetime.orbital.y,
1289
+ 0
1290
+ ) : 0,
1291
+ normalizedConfig.velocityOverLifetime.orbital.z ? calculateValue(
1292
+ generalData.particleSystemId,
1293
+ normalizedConfig.velocityOverLifetime.orbital.z,
1294
+ 0
1295
+ ) : 0
1296
+ );
1297
+ generalData.orbitalVelocityData[particleIndex].positionOffset.set(
1298
+ startPositions[particleIndex].x,
1299
+ startPositions[particleIndex].y,
1300
+ startPositions[particleIndex].z
1301
+ );
1302
+ }
1303
+ geometry.attributes.lifetime.array[particleIndex] = 0;
1304
+ geometry.attributes.lifetime.needsUpdate = true;
1305
+ applyModifiers({
1306
+ delta: 0,
1307
+ generalData,
1308
+ normalizedConfig,
1309
+ attributes: particleSystem.geometry.attributes,
1310
+ particleLifetimePercentage: 0,
1311
+ particleIndex
1312
+ });
1313
+ };
1314
+ let particleSystem = new THREE3.Points(geometry, material);
1315
+ particleSystem.position.copy(transform.position);
1316
+ particleSystem.rotation.x = THREE3.MathUtils.degToRad(transform.rotation.x);
1317
+ particleSystem.rotation.y = THREE3.MathUtils.degToRad(transform.rotation.y);
1318
+ particleSystem.rotation.z = THREE3.MathUtils.degToRad(transform.rotation.z);
1319
+ particleSystem.scale.copy(transform.scale);
1320
+ const calculatedCreationTime = now + calculateValue(generalData.particleSystemId, startDelay) * 1e3;
1321
+ let wrapper;
1322
+ if (normalizedConfig.simulationSpace === "WORLD" /* WORLD */) {
1323
+ wrapper = new Gyroscope();
1324
+ wrapper.add(particleSystem);
1325
+ }
1326
+ const instanceData = {
1327
+ particleSystem,
1328
+ wrapper,
1329
+ elapsedUniform: material.uniforms.elapsed,
1330
+ generalData,
1331
+ onUpdate,
1332
+ onComplete,
1333
+ creationTime: calculatedCreationTime,
1334
+ lastEmissionTime: calculatedCreationTime,
1335
+ duration,
1336
+ looping,
1337
+ simulationSpace,
1338
+ gravity,
1339
+ emission,
1340
+ normalizedConfig,
1341
+ iterationCount: 0,
1342
+ velocities,
1343
+ freeList,
1344
+ deactivateParticle,
1345
+ activateParticle
1346
+ };
1347
+ createdParticleSystems.push(instanceData);
1348
+ const resumeEmitter = () => generalData.isEnabled = true;
1349
+ const pauseEmitter = () => generalData.isEnabled = false;
1350
+ const dispose = () => destroyParticleSystem(particleSystem);
1351
+ const update = (cycleData) => updateParticleSystemInstance(instanceData, cycleData);
1352
+ return {
1353
+ instance: wrapper || particleSystem,
1354
+ resumeEmitter,
1355
+ pauseEmitter,
1356
+ dispose,
1357
+ update
1358
+ };
1359
+ };
1360
+ var updateParticleSystemInstance = (props, { now, delta, elapsed }) => {
1361
+ const {
1362
+ onUpdate,
1363
+ generalData,
1364
+ onComplete,
1365
+ particleSystem,
1366
+ wrapper,
1367
+ elapsedUniform,
1368
+ creationTime,
1369
+ lastEmissionTime,
1370
+ duration,
1371
+ looping,
1372
+ emission,
1373
+ normalizedConfig,
1374
+ iterationCount,
1375
+ velocities,
1376
+ freeList,
1377
+ deactivateParticle,
1378
+ activateParticle,
1379
+ simulationSpace,
1380
+ gravity
1381
+ } = props;
1382
+ const lifetime = now - creationTime;
1383
+ const normalizedLifetime = lifetime % (duration * 1e3);
1384
+ generalData.normalizedLifetimePercentage = Math.max(
1385
+ Math.min(normalizedLifetime / (duration * 1e3), 1),
1386
+ 0
1387
+ );
1388
+ const {
1389
+ lastWorldPosition,
1390
+ currentWorldPosition,
1391
+ worldPositionChange,
1392
+ lastWorldQuaternion,
1393
+ worldQuaternion,
1394
+ worldEuler,
1395
+ gravityVelocity,
1396
+ isEnabled
1397
+ } = generalData;
1398
+ if (wrapper?.parent)
1399
+ generalData.wrapperQuaternion.copy(wrapper.parent.quaternion);
1400
+ _lastWorldPositionSnapshot.copy(lastWorldPosition);
1401
+ elapsedUniform.value = elapsed;
1402
+ particleSystem.getWorldPosition(currentWorldPosition);
1403
+ if (lastWorldPosition.x !== -99999) {
1404
+ worldPositionChange.set(
1405
+ currentWorldPosition.x - lastWorldPosition.x,
1406
+ currentWorldPosition.y - lastWorldPosition.y,
1407
+ currentWorldPosition.z - lastWorldPosition.z
1408
+ );
1409
+ }
1410
+ if (isEnabled) {
1411
+ generalData.distanceFromLastEmitByDistance += worldPositionChange.length();
1412
+ }
1413
+ particleSystem.getWorldPosition(lastWorldPosition);
1414
+ particleSystem.getWorldQuaternion(worldQuaternion);
1415
+ if (lastWorldQuaternion.x === -99999 || lastWorldQuaternion.x !== worldQuaternion.x || lastWorldQuaternion.y !== worldQuaternion.y || lastWorldQuaternion.z !== worldQuaternion.z) {
1416
+ worldEuler.setFromQuaternion(worldQuaternion);
1417
+ lastWorldQuaternion.copy(worldQuaternion);
1418
+ gravityVelocity.set(
1419
+ lastWorldPosition.x,
1420
+ lastWorldPosition.y + gravity,
1421
+ lastWorldPosition.z
1422
+ );
1423
+ particleSystem.worldToLocal(gravityVelocity);
1424
+ }
1425
+ const creationTimes = generalData.creationTimes;
1426
+ const attributes = particleSystem.geometry.attributes;
1427
+ const isActiveArr = attributes.isActive.array;
1428
+ const startLifetimeArr = attributes.startLifetime.array;
1429
+ const positionArr = attributes.position.array;
1430
+ const lifetimeArr = attributes.lifetime.array;
1431
+ const creationTimesLength = creationTimes.length;
1432
+ let positionNeedsUpdate = false;
1433
+ let lifetimeNeedsUpdate = false;
1434
+ _modifierParams.delta = delta;
1435
+ _modifierParams.generalData = generalData;
1436
+ _modifierParams.normalizedConfig = normalizedConfig;
1437
+ _modifierParams.attributes = attributes;
1438
+ for (let index = 0; index < creationTimesLength; index++) {
1439
+ if (isActiveArr[index]) {
1440
+ const particleLifetime = now - creationTimes[index];
1441
+ if (particleLifetime > startLifetimeArr[index]) {
1442
+ deactivateParticle(index);
1443
+ } else {
1444
+ const velocity = velocities[index];
1445
+ velocity.x -= gravityVelocity.x * delta;
1446
+ velocity.y -= gravityVelocity.y * delta;
1447
+ velocity.z -= gravityVelocity.z * delta;
1448
+ if (gravity !== 0 || velocity.x !== 0 || velocity.y !== 0 || velocity.z !== 0 || worldPositionChange.x !== 0 || worldPositionChange.y !== 0 || worldPositionChange.z !== 0) {
1449
+ const positionIndex = index * 3;
1450
+ if (simulationSpace === "WORLD" /* WORLD */) {
1451
+ positionArr[positionIndex] -= worldPositionChange.x;
1452
+ positionArr[positionIndex + 1] -= worldPositionChange.y;
1453
+ positionArr[positionIndex + 2] -= worldPositionChange.z;
1454
+ }
1455
+ positionArr[positionIndex] += velocity.x * delta;
1456
+ positionArr[positionIndex + 1] += velocity.y * delta;
1457
+ positionArr[positionIndex + 2] += velocity.z * delta;
1458
+ positionNeedsUpdate = true;
1459
+ }
1460
+ lifetimeArr[index] = particleLifetime;
1461
+ lifetimeNeedsUpdate = true;
1462
+ _modifierParams.particleLifetimePercentage = particleLifetime / startLifetimeArr[index];
1463
+ _modifierParams.particleIndex = index;
1464
+ applyModifiers(_modifierParams);
1465
+ }
1466
+ }
1467
+ }
1468
+ if (positionNeedsUpdate) attributes.position.needsUpdate = true;
1469
+ if (lifetimeNeedsUpdate) attributes.lifetime.needsUpdate = true;
1470
+ if (isEnabled && (looping || lifetime < duration * 1e3)) {
1471
+ const emissionDelta = now - lastEmissionTime;
1472
+ const neededParticlesByTime = emission.rateOverTime ? Math.floor(
1473
+ calculateValue(
1474
+ generalData.particleSystemId,
1475
+ emission.rateOverTime,
1476
+ generalData.normalizedLifetimePercentage
1477
+ ) * (emissionDelta / 1e3)
1478
+ ) : 0;
1479
+ const rateOverDistance = emission.rateOverDistance ? calculateValue(
1480
+ generalData.particleSystemId,
1481
+ emission.rateOverDistance,
1482
+ generalData.normalizedLifetimePercentage
1483
+ ) : 0;
1484
+ const neededParticlesByDistance = rateOverDistance > 0 && generalData.distanceFromLastEmitByDistance > 0 ? Math.floor(
1485
+ generalData.distanceFromLastEmitByDistance / (1 / rateOverDistance)
1486
+ ) : 0;
1487
+ const useDistanceStep = neededParticlesByDistance > 0;
1488
+ if (useDistanceStep) {
1489
+ _distanceStep.x = (currentWorldPosition.x - _lastWorldPositionSnapshot.x) / neededParticlesByDistance;
1490
+ _distanceStep.y = (currentWorldPosition.y - _lastWorldPositionSnapshot.y) / neededParticlesByDistance;
1491
+ _distanceStep.z = (currentWorldPosition.z - _lastWorldPositionSnapshot.z) / neededParticlesByDistance;
1492
+ }
1493
+ let neededParticles = neededParticlesByTime + neededParticlesByDistance;
1494
+ if (rateOverDistance > 0 && neededParticlesByDistance >= 1) {
1495
+ generalData.distanceFromLastEmitByDistance = 0;
1496
+ }
1497
+ if (emission.bursts && generalData.burstStates) {
1498
+ const bursts = emission.bursts;
1499
+ const burstStates = generalData.burstStates;
1500
+ const currentIterationTime = normalizedLifetime;
1501
+ for (let i = 0; i < bursts.length; i++) {
1502
+ const burst = bursts[i];
1503
+ const state = burstStates[i];
1504
+ const burstTimeMs = burst.time * 1e3;
1505
+ const cycles = burst.cycles ?? 1;
1506
+ const intervalMs = (burst.interval ?? 0) * 1e3;
1507
+ const probability = burst.probability ?? 1;
1508
+ if (looping && currentIterationTime < burstTimeMs && state.cyclesExecuted > 0) {
1509
+ state.cyclesExecuted = 0;
1510
+ state.lastCycleTime = 0;
1511
+ state.probabilityPassed = false;
1512
+ }
1513
+ if (state.cyclesExecuted >= cycles) continue;
1514
+ const nextCycleTime = burstTimeMs + state.cyclesExecuted * intervalMs;
1515
+ if (currentIterationTime >= nextCycleTime) {
1516
+ if (state.cyclesExecuted === 0) {
1517
+ state.probabilityPassed = Math.random() < probability;
1518
+ }
1519
+ if (state.probabilityPassed) {
1520
+ const burstCount = Math.floor(
1521
+ calculateValue(
1522
+ generalData.particleSystemId,
1523
+ burst.count,
1524
+ generalData.normalizedLifetimePercentage
1525
+ )
1526
+ );
1527
+ neededParticles += burstCount;
1528
+ }
1529
+ state.cyclesExecuted++;
1530
+ state.lastCycleTime = currentIterationTime;
1531
+ }
1532
+ }
1533
+ }
1534
+ if (neededParticles > 0) {
1535
+ let generatedParticlesByDistanceNeeds = 0;
1536
+ for (let i = 0; i < neededParticles; i++) {
1537
+ if (freeList.length === 0) break;
1538
+ const particleIndex = freeList.pop();
1539
+ _tempPosition.x = 0;
1540
+ _tempPosition.y = 0;
1541
+ _tempPosition.z = 0;
1542
+ if (useDistanceStep && generatedParticlesByDistanceNeeds < neededParticlesByDistance) {
1543
+ _tempPosition.x = _distanceStep.x * generatedParticlesByDistanceNeeds;
1544
+ _tempPosition.y = _distanceStep.y * generatedParticlesByDistanceNeeds;
1545
+ _tempPosition.z = _distanceStep.z * generatedParticlesByDistanceNeeds;
1546
+ generatedParticlesByDistanceNeeds++;
1547
+ }
1548
+ activateParticle({
1549
+ particleIndex,
1550
+ activationTime: now,
1551
+ position: _tempPosition
1552
+ });
1553
+ props.lastEmissionTime = now;
1554
+ }
1555
+ }
1556
+ if (onUpdate)
1557
+ onUpdate({
1558
+ particleSystem,
1559
+ delta,
1560
+ elapsed,
1561
+ lifetime,
1562
+ normalizedLifetime,
1563
+ iterationCount: iterationCount + 1
1564
+ });
1565
+ } else if (onComplete)
1566
+ onComplete({
1567
+ particleSystem
1568
+ });
1569
+ };
1570
+ var updateParticleSystems = (cycleData) => {
1571
+ createdParticleSystems.forEach(
1572
+ (props) => updateParticleSystemInstance(props, cycleData)
1573
+ );
1574
+ };
1575
+
1576
+ export { CurveFunctionId, EmitFrom, LifeTimeCurve, Shape, SimulationSpace, TimeMode, applyModifiers, blendingMap, calculateRandomPositionAndVelocityOnBox, calculateRandomPositionAndVelocityOnCircle, calculateRandomPositionAndVelocityOnCone, calculateRandomPositionAndVelocityOnRectangle, calculateRandomPositionAndVelocityOnSphere, calculateValue, createBezierCurveFunction, createDefaultParticleTexture, createParticleSystem, getBezierCacheSize, getCurveFunction, getCurveFunctionFromConfig, getDefaultParticleSystemConfig, isLifeTimeCurve, removeBezierCurveFunction, updateParticleSystems };
1577
+ //# sourceMappingURL=index.js.map
1578
+ //# sourceMappingURL=index.js.map