@newkrok/three-particles 0.2.2 → 0.3.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/README.md +1 -1
- package/package.json +3 -2
- package/src/js/effects/shaders/particle-system-vertex-shader.glsl.js +2 -2
- package/src/js/effects/three-particles/three-particles-curves.js +74 -0
- package/src/js/effects/three-particles/three-particles-modifiers.js +44 -0
- package/src/js/effects/{three-particles-utils.js → three-particles/three-particles-utils.js} +4 -4
- package/src/js/effects/three-particles.js +128 -52
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@newkrok/three-particles",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Particle system for ThreeJS",
|
|
5
5
|
"main": "src/js/three-particles.js",
|
|
6
6
|
"bin": {
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
},
|
|
24
24
|
"homepage": "https://github.com/NewKrok/three-particles#readme",
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"three": "
|
|
26
|
+
"three": "0.135.0",
|
|
27
|
+
"easing-functions": "1.0.1"
|
|
27
28
|
},
|
|
28
29
|
"scripts": {
|
|
29
30
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const ParticleSystemVertexShader = `
|
|
2
|
-
attribute float
|
|
2
|
+
attribute float size;
|
|
3
3
|
attribute float colorR;
|
|
4
4
|
attribute float colorG;
|
|
5
5
|
attribute float colorB;
|
|
@@ -25,7 +25,7 @@ const ParticleSystemVertexShader = `
|
|
|
25
25
|
vStartFrame = startFrame;
|
|
26
26
|
|
|
27
27
|
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
|
|
28
|
-
gl_PointSize =
|
|
28
|
+
gl_PointSize = size * (100.0 / length(mvPosition.xyz));
|
|
29
29
|
gl_Position = projectionMatrix * mvPosition;
|
|
30
30
|
}
|
|
31
31
|
`;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import Easing from "easing-functions";
|
|
2
|
+
|
|
3
|
+
export const CurveFunction = {
|
|
4
|
+
LINEAR: "LINEAR",
|
|
5
|
+
QUADRATIC_IN: "QUADRATIC_IN",
|
|
6
|
+
QUADRATIC_OUT: "QUADRATIC_OUT",
|
|
7
|
+
QUADRATIC_IN_OUT: "QUADRATIC_IN_OUT",
|
|
8
|
+
CUBIC_IN: "CUBIC_IN",
|
|
9
|
+
CUBIC_OUT: "CUBIC_OUT",
|
|
10
|
+
CUBIC_IN_OUT: "CUBIC_IN_OUT",
|
|
11
|
+
QUARTIC_IN: "QUARTIC_IN",
|
|
12
|
+
QUARTIC_OUT: "QUARTIC_OUT",
|
|
13
|
+
QUARTIC_IN_OUT: "QUARTIC_IN_OUT",
|
|
14
|
+
QUINTIC_IN: "QUINTIC_IN",
|
|
15
|
+
QUINTIC_OUT: "QUINTIC_OUT",
|
|
16
|
+
QUINTIC_IN_OUT: "QUINTIC_IN_OUT",
|
|
17
|
+
SINUSOIDAL_IN: "SINUSOIDAL_IN",
|
|
18
|
+
SINUSOIDAL_OUT: "SINUSOIDAL_OUT",
|
|
19
|
+
SINUSOIDAL_IN_OUT: "SINUSOIDAL_IN_OUT",
|
|
20
|
+
EXPONENTIAL_IN: "EXPONENTIAL_IN",
|
|
21
|
+
EXPONENTIAL_OUT: "EXPONENTIAL_OUT",
|
|
22
|
+
EXPONENTIAL_IN_OUT: "EXPONENTIAL_IN_OUT",
|
|
23
|
+
CIRCULAR_IN: "CIRCULAR_IN",
|
|
24
|
+
CIRCULAR_OUT: "CIRCULAR_OUT",
|
|
25
|
+
CIRCULAR_IN_OUT: "CIRCULAR_IN_OUT",
|
|
26
|
+
ELASTIC_IN: "ELASTIC_IN",
|
|
27
|
+
ELASTIC_OUT: "ELASTIC_OUT",
|
|
28
|
+
ELASTIC_IN_OUT: "ELASTIC_IN_OUT",
|
|
29
|
+
BACK_IN: "BACK_IN",
|
|
30
|
+
BACK_OUT: "BACK_OUT",
|
|
31
|
+
BACK_IN_OUT: "BACK_IN_OUT",
|
|
32
|
+
BOUNCE_IN: "BOUNCE_IN",
|
|
33
|
+
BOUNCE_OUT: "BOUNCE_OUT",
|
|
34
|
+
BOUNCE_IN_OUT: "BOUNCE_IN_OUT",
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const CurveFunctionMap = {
|
|
38
|
+
[CurveFunction.LINEAR]: Easing.Linear.None,
|
|
39
|
+
[CurveFunction.QUADRATIC_IN]: Easing.Quadratic.In,
|
|
40
|
+
[CurveFunction.QUADRATIC_OUT]: Easing.Quadratic.Out,
|
|
41
|
+
[CurveFunction.QUADRATIC_IN_OUT]: Easing.Quadratic.InOut,
|
|
42
|
+
[CurveFunction.CUBIC_IN]: Easing.Cubic.In,
|
|
43
|
+
[CurveFunction.CUBIC_OUT]: Easing.Cubic.Out,
|
|
44
|
+
[CurveFunction.CUBIC_IN_OUT]: Easing.Cubic.InOut,
|
|
45
|
+
[CurveFunction.QUARTIC_IN]: Easing.Quartic.In,
|
|
46
|
+
[CurveFunction.QUARTIC_OUT]: Easing.Quartic.Out,
|
|
47
|
+
[CurveFunction.QUARTIC_IN_OUT]: Easing.Quartic.InOut,
|
|
48
|
+
[CurveFunction.QUINTIC_IN]: Easing.Quintic.In,
|
|
49
|
+
[CurveFunction.QUINTIC_OUT]: Easing.Quintic.Out,
|
|
50
|
+
[CurveFunction.QUINTIC_IN_OUT]: Easing.Quintic.InOut,
|
|
51
|
+
[CurveFunction.SINUSOIDAL_IN]: Easing.Sinusoidal.In,
|
|
52
|
+
[CurveFunction.SINUSOIDAL_OUT]: Easing.Sinusoidal.Out,
|
|
53
|
+
[CurveFunction.SINUSOIDAL_IN_OUT]: Easing.Sinusoidal.InOut,
|
|
54
|
+
[CurveFunction.EXPONENTIAL_IN]: Easing.Exponential.In,
|
|
55
|
+
[CurveFunction.EXPONENTIAL_OUT]: Easing.Exponential.Out,
|
|
56
|
+
[CurveFunction.EXPONENTIAL_IN_OUT]: Easing.Exponential.InOut,
|
|
57
|
+
[CurveFunction.CIRCULAR_IN]: Easing.Circular.In,
|
|
58
|
+
[CurveFunction.CIRCULAR_OUT]: Easing.Circular.Out,
|
|
59
|
+
[CurveFunction.CIRCULAR_IN_OUT]: Easing.Circular.InOut,
|
|
60
|
+
[CurveFunction.ELASTIC_IN]: Easing.Elastic.In,
|
|
61
|
+
[CurveFunction.ELASTIC_OUT]: Easing.Elastic.Out,
|
|
62
|
+
[CurveFunction.ELASTIC_IN_OUT]: Easing.Elastic.InOut,
|
|
63
|
+
[CurveFunction.BACK_IN]: Easing.Back.In,
|
|
64
|
+
[CurveFunction.BACK_OUT]: Easing.Back.Out,
|
|
65
|
+
[CurveFunction.BACK_IN_OUT]: Easing.Back.InOut,
|
|
66
|
+
[CurveFunction.BOUNCE_IN]: Easing.Bounce.In,
|
|
67
|
+
[CurveFunction.BOUNCE_OUT]: Easing.Bounce.Out,
|
|
68
|
+
[CurveFunction.BOUNCE_IN_OUT]: Easing.Bounce.InOut,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const getCurveFunction = (curveFunction) =>
|
|
72
|
+
typeof curveFunction === "function"
|
|
73
|
+
? curveFunction
|
|
74
|
+
: CurveFunctionMap[curveFunction];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { getCurveFunction } from "./three-particles-curves.js";
|
|
2
|
+
|
|
3
|
+
const modifiers = [
|
|
4
|
+
// {key:"colorOverLifetime", attributeKeys:["colorR", "colorG", "colorB"]},
|
|
5
|
+
{
|
|
6
|
+
key: "opacityOverLifetime",
|
|
7
|
+
attributeKeys: ["colorA"],
|
|
8
|
+
startValueKeys: ["startOpacity"],
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
key: "sizeOverLifetime",
|
|
12
|
+
attributeKeys: ["size"],
|
|
13
|
+
startValueKeys: ["startSize"],
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
export const applyModifiers = ({
|
|
18
|
+
startValues,
|
|
19
|
+
normalizedConfig,
|
|
20
|
+
attributes,
|
|
21
|
+
particleLifetimePercentage,
|
|
22
|
+
particleIndex,
|
|
23
|
+
forceUpdate = false,
|
|
24
|
+
}) => {
|
|
25
|
+
modifiers.forEach(({ key, attributeKeys, startValueKeys }) => {
|
|
26
|
+
const modifier = normalizedConfig[key];
|
|
27
|
+
if (modifier.isActive) {
|
|
28
|
+
const multiplier = getCurveFunction(modifier.curveFunction)(
|
|
29
|
+
particleLifetimePercentage
|
|
30
|
+
);
|
|
31
|
+
attributeKeys.forEach((attributeKey, index) => {
|
|
32
|
+
attributes[attributeKey].array[particleIndex] =
|
|
33
|
+
startValues[startValueKeys[index]][particleIndex] * multiplier;
|
|
34
|
+
attributes[attributeKey].needsUpdate = true;
|
|
35
|
+
});
|
|
36
|
+
} else if (forceUpdate) {
|
|
37
|
+
attributeKeys.forEach((attributeKey, index) => {
|
|
38
|
+
attributes[attributeKey].array[particleIndex] =
|
|
39
|
+
startValues[startValueKeys[index]][particleIndex];
|
|
40
|
+
attributes[attributeKey].needsUpdate = true;
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
};
|
package/src/js/effects/{three-particles-utils.js → three-particles/three-particles-utils.js}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as THREE from "three/build/three.module.js";
|
|
2
2
|
|
|
3
|
-
export const
|
|
3
|
+
export const patchObject = (
|
|
4
4
|
objectA,
|
|
5
5
|
objectB,
|
|
6
6
|
config = { skippedProperties: [], applyToFirstObject: false }
|
|
@@ -9,7 +9,7 @@ export const deepMerge = (
|
|
|
9
9
|
Object.keys(objectA).forEach((key) => {
|
|
10
10
|
if (!config.skippedProperties || !config.skippedProperties.includes(key)) {
|
|
11
11
|
if (typeof objectA[key] === "object" && objectA[key] && objectB[key]) {
|
|
12
|
-
result[key] =
|
|
12
|
+
result[key] = patchObject(objectA[key], objectB[key], config);
|
|
13
13
|
} else {
|
|
14
14
|
result[key] = objectB[key] === 0 ? 0 : objectB[key] || objectA[key];
|
|
15
15
|
if (config.applyToFirstObject) objectA[key] = result[key];
|
|
@@ -100,7 +100,7 @@ export const calculateRandomPositionAndVelocityOnCone = (
|
|
|
100
100
|
sinNormalizedAngle *
|
|
101
101
|
speedMultiplierByPosition *
|
|
102
102
|
randomizedSpeed,
|
|
103
|
-
|
|
103
|
+
Math.cos(normalizedAngle) * randomizedSpeed
|
|
104
104
|
);
|
|
105
105
|
};
|
|
106
106
|
|
|
@@ -157,5 +157,5 @@ export const calculateRandomPositionAndVelocityOnRectangle = (
|
|
|
157
157
|
startSpeed.min,
|
|
158
158
|
startSpeed.max
|
|
159
159
|
);
|
|
160
|
-
velocity.set(0, 0,
|
|
160
|
+
velocity.set(0, 0, randomizedSpeed);
|
|
161
161
|
};
|
|
@@ -5,11 +5,13 @@ import {
|
|
|
5
5
|
calculateRandomPositionAndVelocityOnCone,
|
|
6
6
|
calculateRandomPositionAndVelocityOnRectangle,
|
|
7
7
|
calculateRandomPositionAndVelocityOnSphere,
|
|
8
|
-
|
|
9
|
-
} from "./three-particles-utils.js";
|
|
8
|
+
patchObject,
|
|
9
|
+
} from "./three-particles/three-particles-utils.js";
|
|
10
10
|
|
|
11
|
-
import
|
|
12
|
-
import
|
|
11
|
+
import { CurveFunction } from "./three-particles/three-particles-curves.js";
|
|
12
|
+
import ParticleSystemFragmentShader from "./three-particles/shaders/particle-system-fragment-shader.glsl.js";
|
|
13
|
+
import ParticleSystemVertexShader from "./three-particles/shaders/particle-system-vertex-shader.glsl.js";
|
|
14
|
+
import { applyModifiers } from "./three-particles/three-particles-modifiers.js";
|
|
13
15
|
|
|
14
16
|
// Float32Array is not enough accurate when we are storing timestamp in it so we just remove unnecessary time
|
|
15
17
|
const float32Helper = 1638200000000;
|
|
@@ -38,6 +40,11 @@ export const getDefaultParticleSystemConfig = () =>
|
|
|
38
40
|
JSON.parse(JSON.stringify(DEFAULT_PARTICLE_SYSTEM_CONFIG));
|
|
39
41
|
|
|
40
42
|
const DEFAULT_PARTICLE_SYSTEM_CONFIG = {
|
|
43
|
+
transform: {
|
|
44
|
+
position: { x: 0, y: 0, z: 0 },
|
|
45
|
+
rotation: { x: 0, y: 0, z: 0 },
|
|
46
|
+
scale: { x: 1, y: 1, z: 1 },
|
|
47
|
+
},
|
|
41
48
|
duration: 5.0,
|
|
42
49
|
looping: true,
|
|
43
50
|
startDelay: { min: 0.0, max: 0.0 },
|
|
@@ -81,6 +88,18 @@ const DEFAULT_PARTICLE_SYSTEM_CONFIG = {
|
|
|
81
88
|
},
|
|
82
89
|
},
|
|
83
90
|
map: null,
|
|
91
|
+
sizeOverLifetime: {
|
|
92
|
+
isActive: false,
|
|
93
|
+
curveFunction: CurveFunction.LINEAR,
|
|
94
|
+
},
|
|
95
|
+
/* colorOverLifetime: {
|
|
96
|
+
isActive: false,
|
|
97
|
+
curveFunction: CurveFunction.LINEAR,
|
|
98
|
+
}, */
|
|
99
|
+
opacityOverLifetime: {
|
|
100
|
+
isActive: false,
|
|
101
|
+
curveFunction: CurveFunction.LINEAR,
|
|
102
|
+
},
|
|
84
103
|
textureSheetAnimation: {
|
|
85
104
|
tiles: new THREE.Vector2(1.0, 1.0),
|
|
86
105
|
timeMode: TimeMode.LIFETIME,
|
|
@@ -158,11 +177,21 @@ export const createParticleSystem = (
|
|
|
158
177
|
config = DEFAULT_PARTICLE_SYSTEM_CONFIG
|
|
159
178
|
) => {
|
|
160
179
|
const now = Date.now();
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
180
|
+
const generalData = {
|
|
181
|
+
distanceFromLastEmitByDistance: 0,
|
|
182
|
+
lastWorldPosition: new THREE.Vector3(-99999),
|
|
183
|
+
currentWorldPosition: new THREE.Vector3(-99999),
|
|
184
|
+
worldPositionChange: new THREE.Vector3(),
|
|
185
|
+
worldQuaternion: new THREE.Quaternion(),
|
|
186
|
+
lastWorldQuaternion: new THREE.Quaternion(-99999),
|
|
187
|
+
worldEuler: new THREE.Euler(),
|
|
188
|
+
gravityVelocity: new THREE.Vector3(0, 0, 0),
|
|
189
|
+
startValues: {},
|
|
190
|
+
};
|
|
164
191
|
|
|
192
|
+
const normalizedConfig = patchObject(DEFAULT_PARTICLE_SYSTEM_CONFIG, config);
|
|
165
193
|
const {
|
|
194
|
+
transform,
|
|
166
195
|
duration,
|
|
167
196
|
looping,
|
|
168
197
|
startDelay,
|
|
@@ -181,7 +210,7 @@ export const createParticleSystem = (
|
|
|
181
210
|
onUpdate,
|
|
182
211
|
onComplete,
|
|
183
212
|
textureSheetAnimation,
|
|
184
|
-
} =
|
|
213
|
+
} = normalizedConfig;
|
|
185
214
|
|
|
186
215
|
const startPositions = Array.from(
|
|
187
216
|
{ length: maxParticles },
|
|
@@ -192,6 +221,16 @@ export const createParticleSystem = (
|
|
|
192
221
|
() => new THREE.Vector3()
|
|
193
222
|
);
|
|
194
223
|
|
|
224
|
+
const startValueKeys = ["startSize", "startOpacity"];
|
|
225
|
+
startValueKeys.forEach((key) => {
|
|
226
|
+
generalData.startValues[key] = Array.from({ length: maxParticles }, () =>
|
|
227
|
+
THREE.MathUtils.randFloat(
|
|
228
|
+
normalizedConfig[key].min,
|
|
229
|
+
normalizedConfig[key].max
|
|
230
|
+
)
|
|
231
|
+
);
|
|
232
|
+
});
|
|
233
|
+
|
|
195
234
|
const material = new THREE.ShaderMaterial({
|
|
196
235
|
uniforms: {
|
|
197
236
|
elapsed: {
|
|
@@ -258,22 +297,16 @@ export const createParticleSystem = (
|
|
|
258
297
|
|
|
259
298
|
createFloat32AttributesRequest("opacity", 0);
|
|
260
299
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
THREE.Math.degToRad(
|
|
267
|
-
THREE.MathUtils.randFloat(startRotation.min, startRotation.max)
|
|
268
|
-
),
|
|
269
|
-
});
|
|
300
|
+
createFloat32AttributesRequest("rotation", () =>
|
|
301
|
+
THREE.Math.degToRad(
|
|
302
|
+
THREE.MathUtils.randFloat(startRotation.min, startRotation.max)
|
|
303
|
+
)
|
|
304
|
+
);
|
|
270
305
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
factory: () => THREE.MathUtils.randFloat(startSize.min, startSize.max),
|
|
276
|
-
});
|
|
306
|
+
createFloat32AttributesRequest(
|
|
307
|
+
"size",
|
|
308
|
+
(_, index) => generalData.startValues.startSize[index]
|
|
309
|
+
);
|
|
277
310
|
|
|
278
311
|
createFloat32AttributesRequest("rotation", 0);
|
|
279
312
|
|
|
@@ -300,8 +333,6 @@ export const createParticleSystem = (
|
|
|
300
333
|
|
|
301
334
|
const deactivateParticle = (particleIndex) => {
|
|
302
335
|
geometry.attributes.isActive.array[particleIndex] = false;
|
|
303
|
-
geometry.attributes.lifetime.array[particleIndex] = 0;
|
|
304
|
-
geometry.attributes.lifetime.needsUpdate = true;
|
|
305
336
|
geometry.attributes.colorA.array[particleIndex] = 0;
|
|
306
337
|
geometry.attributes.colorA.needsUpdate = true;
|
|
307
338
|
};
|
|
@@ -328,12 +359,6 @@ export const createParticleSystem = (
|
|
|
328
359
|
colorRandomRatio * (startColor.max.b - startColor.min.b);
|
|
329
360
|
geometry.attributes.colorB.needsUpdate = true;
|
|
330
361
|
|
|
331
|
-
geometry.attributes.colorA.array[particleIndex] = THREE.MathUtils.randFloat(
|
|
332
|
-
startOpacity.min,
|
|
333
|
-
startOpacity.max
|
|
334
|
-
);
|
|
335
|
-
geometry.attributes.colorA.needsUpdate = true;
|
|
336
|
-
|
|
337
362
|
geometry.attributes.startFrame.array[particleIndex] =
|
|
338
363
|
THREE.MathUtils.randInt(
|
|
339
364
|
textureSheetAnimation.startFrame.min,
|
|
@@ -345,14 +370,17 @@ export const createParticleSystem = (
|
|
|
345
370
|
THREE.MathUtils.randFloat(startLifetime.min, startLifetime.max) * 1000;
|
|
346
371
|
geometry.attributes.startLifetime.needsUpdate = true;
|
|
347
372
|
|
|
348
|
-
|
|
373
|
+
generalData.startValues.startSize[particleIndex] =
|
|
349
374
|
THREE.MathUtils.randFloat(startSize.min, startSize.max);
|
|
350
|
-
|
|
375
|
+
generalData.startValues.startOpacity[particleIndex] =
|
|
376
|
+
THREE.MathUtils.randFloat(startOpacity.min, startOpacity.max);
|
|
351
377
|
|
|
352
378
|
geometry.attributes.rotation.array[particleIndex] = THREE.Math.degToRad(
|
|
353
379
|
THREE.MathUtils.randFloat(startRotation.min, startRotation.max)
|
|
354
380
|
);
|
|
381
|
+
|
|
355
382
|
geometry.attributes.rotation.needsUpdate = true;
|
|
383
|
+
geometry.attributes.colorB.needsUpdate = true;
|
|
356
384
|
|
|
357
385
|
calculatePositionAndVelocity(
|
|
358
386
|
shape,
|
|
@@ -371,19 +399,32 @@ export const createParticleSystem = (
|
|
|
371
399
|
|
|
372
400
|
geometry.attributes.lifetime.array[particleIndex] = 0;
|
|
373
401
|
geometry.attributes.lifetime.needsUpdate = true;
|
|
402
|
+
|
|
403
|
+
applyModifiers({
|
|
404
|
+
startValues: generalData.startValues,
|
|
405
|
+
normalizedConfig,
|
|
406
|
+
attributes: particleSystem.geometry.attributes,
|
|
407
|
+
particleLifetimePercentage: 0,
|
|
408
|
+
particleIndex,
|
|
409
|
+
forceUpdate: true,
|
|
410
|
+
});
|
|
374
411
|
};
|
|
375
412
|
|
|
376
413
|
const particleSystem = new THREE.Points(geometry, material);
|
|
377
414
|
particleSystem.sortParticles = true;
|
|
378
415
|
|
|
416
|
+
particleSystem.position.copy(transform.position);
|
|
417
|
+
particleSystem.rotation.x = THREE.Math.degToRad(transform.rotation.x);
|
|
418
|
+
particleSystem.rotation.y = THREE.Math.degToRad(transform.rotation.y);
|
|
419
|
+
particleSystem.rotation.z = THREE.Math.degToRad(transform.rotation.z);
|
|
420
|
+
particleSystem.scale.copy(transform.scale);
|
|
421
|
+
|
|
379
422
|
const calculatedCreationTime =
|
|
380
423
|
now + THREE.MathUtils.randFloat(startDelay.min, startDelay.max) * 1000;
|
|
381
424
|
|
|
382
425
|
createdParticleSystems.push({
|
|
383
426
|
particleSystem,
|
|
384
427
|
generalData,
|
|
385
|
-
lastWorldPosition,
|
|
386
|
-
worldPositionChange,
|
|
387
428
|
onUpdate,
|
|
388
429
|
onComplete,
|
|
389
430
|
creationTime: calculatedCreationTime,
|
|
@@ -393,6 +434,7 @@ export const createParticleSystem = (
|
|
|
393
434
|
simulationSpace,
|
|
394
435
|
gravity,
|
|
395
436
|
emission,
|
|
437
|
+
normalizedConfig,
|
|
396
438
|
iterationCount: 0,
|
|
397
439
|
velocities,
|
|
398
440
|
deactivateParticle,
|
|
@@ -417,8 +459,6 @@ export const updateParticleSystems = ({ now, delta, elapsed }) => {
|
|
|
417
459
|
const {
|
|
418
460
|
onUpdate,
|
|
419
461
|
generalData,
|
|
420
|
-
lastWorldPosition,
|
|
421
|
-
worldPositionChange,
|
|
422
462
|
onComplete,
|
|
423
463
|
particleSystem,
|
|
424
464
|
creationTime,
|
|
@@ -426,6 +466,7 @@ export const updateParticleSystems = ({ now, delta, elapsed }) => {
|
|
|
426
466
|
duration,
|
|
427
467
|
looping,
|
|
428
468
|
emission,
|
|
469
|
+
normalizedConfig,
|
|
429
470
|
iterationCount,
|
|
430
471
|
velocities,
|
|
431
472
|
deactivateParticle,
|
|
@@ -433,21 +474,50 @@ export const updateParticleSystems = ({ now, delta, elapsed }) => {
|
|
|
433
474
|
simulationSpace,
|
|
434
475
|
gravity,
|
|
435
476
|
} = props;
|
|
477
|
+
|
|
478
|
+
const {
|
|
479
|
+
lastWorldPosition,
|
|
480
|
+
currentWorldPosition,
|
|
481
|
+
worldPositionChange,
|
|
482
|
+
lastWorldQuaternion,
|
|
483
|
+
worldQuaternion,
|
|
484
|
+
worldEuler,
|
|
485
|
+
gravityVelocity,
|
|
486
|
+
} = generalData;
|
|
487
|
+
|
|
436
488
|
const lifetime = now - creationTime;
|
|
437
489
|
particleSystem.material.uniforms.elapsed.value = elapsed;
|
|
438
490
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
lastWorldPosition.y !== -99999 &&
|
|
442
|
-
lastWorldPosition.z !== -99999
|
|
443
|
-
)
|
|
491
|
+
particleSystem.getWorldPosition(currentWorldPosition);
|
|
492
|
+
if (lastWorldPosition.x !== -99999)
|
|
444
493
|
worldPositionChange.set(
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
494
|
+
currentWorldPosition.x - lastWorldPosition.x,
|
|
495
|
+
currentWorldPosition.y - lastWorldPosition.y,
|
|
496
|
+
currentWorldPosition.z - lastWorldPosition.z
|
|
448
497
|
);
|
|
449
498
|
generalData.distanceFromLastEmitByDistance += worldPositionChange.length();
|
|
450
|
-
|
|
499
|
+
particleSystem.getWorldPosition(lastWorldPosition);
|
|
500
|
+
|
|
501
|
+
particleSystem.getWorldQuaternion(worldQuaternion);
|
|
502
|
+
if (
|
|
503
|
+
lastWorldQuaternion.x === -99999 ||
|
|
504
|
+
lastWorldQuaternion.x != worldQuaternion.x ||
|
|
505
|
+
lastWorldQuaternion.y != worldQuaternion.y ||
|
|
506
|
+
lastWorldQuaternion.z != worldQuaternion.z
|
|
507
|
+
) {
|
|
508
|
+
worldEuler.setFromQuaternion(worldQuaternion);
|
|
509
|
+
lastWorldQuaternion.copy(worldQuaternion);
|
|
510
|
+
|
|
511
|
+
const tempPosX = particleSystem.position.x;
|
|
512
|
+
const tempPosY = particleSystem.position.y;
|
|
513
|
+
const tempPosZ = particleSystem.position.z;
|
|
514
|
+
gravityVelocity.set(0, gravity, 0);
|
|
515
|
+
particleSystem.position.set(0, 0, 0);
|
|
516
|
+
particleSystem.updateMatrixWorld();
|
|
517
|
+
particleSystem.worldToLocal(gravityVelocity);
|
|
518
|
+
particleSystem.position.set(tempPosX, tempPosY, tempPosZ);
|
|
519
|
+
particleSystem.updateMatrixWorld();
|
|
520
|
+
}
|
|
451
521
|
|
|
452
522
|
particleSystem.geometry.attributes.creationTime.array.forEach(
|
|
453
523
|
(entry, index) => {
|
|
@@ -460,7 +530,9 @@ export const updateParticleSystems = ({ now, delta, elapsed }) => {
|
|
|
460
530
|
deactivateParticle(index);
|
|
461
531
|
else {
|
|
462
532
|
const velocity = velocities[index];
|
|
463
|
-
velocity.
|
|
533
|
+
velocity.x -= gravityVelocity.x;
|
|
534
|
+
velocity.y -= gravityVelocity.y;
|
|
535
|
+
velocity.z -= gravityVelocity.z;
|
|
464
536
|
|
|
465
537
|
if (
|
|
466
538
|
gravity !== 0 ||
|
|
@@ -486,12 +558,16 @@ export const updateParticleSystems = ({ now, delta, elapsed }) => {
|
|
|
486
558
|
particleLifetime;
|
|
487
559
|
particleSystem.geometry.attributes.lifetime.needsUpdate = true;
|
|
488
560
|
|
|
489
|
-
|
|
490
|
-
particleSystem.geometry.attributes.colorA.array[index] =
|
|
491
|
-
1 -
|
|
561
|
+
const particleLifetimePercentage =
|
|
492
562
|
particleLifetime /
|
|
493
|
-
|
|
494
|
-
|
|
563
|
+
particleSystem.geometry.attributes.startLifetime.array[index];
|
|
564
|
+
applyModifiers({
|
|
565
|
+
startValues: generalData.startValues,
|
|
566
|
+
normalizedConfig,
|
|
567
|
+
attributes: particleSystem.geometry.attributes,
|
|
568
|
+
particleLifetimePercentage,
|
|
569
|
+
particleIndex: index,
|
|
570
|
+
});
|
|
495
571
|
}
|
|
496
572
|
}
|
|
497
573
|
}
|