@newkrok/three-particles 0.1.0 → 0.2.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 +5 -7
- package/package.json +4 -1
- package/src/js/effects/three-particles-utils.js +36 -2
- package/src/js/effects/three-particles.js +111 -134
package/README.md
CHANGED
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
# THREE Particles
|
|
2
|
+
|
|
2
3
|
Particle sytem for ThreeJS
|
|
3
4
|
|
|
4
5
|
# THREE Particles Editor
|
|
6
|
+
|
|
5
7
|
You can create your own particle effects with it's editor https://github.com/NewKrok/three-particles-editor
|
|
6
8
|
|
|
7
9
|
# Live demo
|
|
10
|
+
|
|
8
11
|
https://newkrok.com/three-particles-editor/index.html
|
|
9
12
|
|
|
10
13
|
# Install
|
|
14
|
+
|
|
11
15
|
npm package https://www.npmjs.com/package/@newkrok/three-particles
|
|
12
16
|
|
|
13
17
|
Install with npm
|
|
14
18
|
`npm i @newkrok/three-particles`
|
|
15
19
|
|
|
16
20
|
Add as a package.json dependency
|
|
17
|
-
`
|
|
18
|
-
"dependencies": {
|
|
19
|
-
...
|
|
20
|
-
"@newkrok/three-particles": "0.0.1"
|
|
21
|
-
...
|
|
22
|
-
},
|
|
23
|
-
`
|
|
21
|
+
`"dependencies": { ... "@newkrok/three-particles": "0.2.0" ... }, `
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@newkrok/three-particles",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Particle system for ThreeJS",
|
|
5
5
|
"main": "src/js/three-particles.js",
|
|
6
6
|
"bin": {
|
|
@@ -22,6 +22,9 @@
|
|
|
22
22
|
"url": "https://github.com/NewKrok/three-particles/issues"
|
|
23
23
|
},
|
|
24
24
|
"homepage": "https://github.com/NewKrok/three-particles#readme",
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"three": "^0.135.0"
|
|
27
|
+
},
|
|
25
28
|
"scripts": {
|
|
26
29
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
27
30
|
}
|
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import * as THREE from "three/build/three.module.js";
|
|
2
2
|
|
|
3
|
+
export const deepMerge = (objectA, objectB) => {
|
|
4
|
+
const result = {};
|
|
5
|
+
Object.keys(objectA).forEach((key) => {
|
|
6
|
+
result[key] =
|
|
7
|
+
typeof objectA[key] === "object" && objectA[key] && objectB[key]
|
|
8
|
+
? deepMerge(objectA[key], objectB[key])
|
|
9
|
+
: objectB[key] === 0
|
|
10
|
+
? 0
|
|
11
|
+
: objectB[key] || objectA[key];
|
|
12
|
+
});
|
|
13
|
+
return result;
|
|
14
|
+
};
|
|
15
|
+
|
|
3
16
|
export const calculateRandomPositionAndVelocityOnSphere = (
|
|
4
17
|
position,
|
|
5
18
|
velocity,
|
|
@@ -106,12 +119,12 @@ export const calculateRandomPositionAndVelocityOnCircle = (
|
|
|
106
119
|
radius * radiusThickness * randomizedDistanceRatio * yDirection;
|
|
107
120
|
position.z = 0;
|
|
108
121
|
|
|
109
|
-
const positionLength = position.length();
|
|
110
|
-
|
|
111
122
|
const randomizedSpeed = THREE.MathUtils.randFloat(
|
|
112
123
|
startSpeed.min,
|
|
113
124
|
startSpeed.max
|
|
114
125
|
);
|
|
126
|
+
|
|
127
|
+
const positionLength = position.length();
|
|
115
128
|
const speedMultiplierByPosition = 1 / positionLength;
|
|
116
129
|
velocity.set(
|
|
117
130
|
position.x * speedMultiplierByPosition * randomizedSpeed,
|
|
@@ -119,3 +132,24 @@ export const calculateRandomPositionAndVelocityOnCircle = (
|
|
|
119
132
|
0
|
|
120
133
|
);
|
|
121
134
|
};
|
|
135
|
+
|
|
136
|
+
export const calculateRandomPositionAndVelocityOnRectangle = (
|
|
137
|
+
position,
|
|
138
|
+
velocity,
|
|
139
|
+
startSpeed,
|
|
140
|
+
{ rotation, scale }
|
|
141
|
+
) => {
|
|
142
|
+
const xOffset = Math.random() * scale.x - scale.x / 2;
|
|
143
|
+
const yOffset = Math.random() * scale.y - scale.y / 2;
|
|
144
|
+
const rotationX = THREE.Math.degToRad(rotation.x);
|
|
145
|
+
const rotationY = THREE.Math.degToRad(rotation.y);
|
|
146
|
+
position.x = xOffset * Math.cos(rotationY);
|
|
147
|
+
position.y = yOffset * Math.cos(rotationX);
|
|
148
|
+
position.z = xOffset * Math.sin(rotationY) - yOffset * Math.sin(rotationX);
|
|
149
|
+
|
|
150
|
+
const randomizedSpeed = THREE.MathUtils.randFloat(
|
|
151
|
+
startSpeed.min,
|
|
152
|
+
startSpeed.max
|
|
153
|
+
);
|
|
154
|
+
velocity.set(0, 0, -randomizedSpeed);
|
|
155
|
+
};
|
|
@@ -3,7 +3,9 @@ import * as THREE from "three/build/three.module.js";
|
|
|
3
3
|
import {
|
|
4
4
|
calculateRandomPositionAndVelocityOnCircle,
|
|
5
5
|
calculateRandomPositionAndVelocityOnCone,
|
|
6
|
+
calculateRandomPositionAndVelocityOnRectangle,
|
|
6
7
|
calculateRandomPositionAndVelocityOnSphere,
|
|
8
|
+
deepMerge,
|
|
7
9
|
} from "./three-particles-utils.js";
|
|
8
10
|
|
|
9
11
|
import ParticleSystemFragmentShader from "./shaders/particle-system-fragment-shader.glsl.js";
|
|
@@ -27,9 +29,54 @@ export const Shape = {
|
|
|
27
29
|
RECTANGLE: "RECTANGLE",
|
|
28
30
|
};
|
|
29
31
|
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
export const getDefaultParticleSystemConfig = () =>
|
|
33
|
+
JSON.parse(JSON.stringify(DEFAULT_PARTICLE_SYSTEM_CONFIG));
|
|
34
|
+
|
|
35
|
+
const DEFAULT_PARTICLE_SYSTEM_CONFIG = {
|
|
36
|
+
duration: 5.0,
|
|
37
|
+
looping: true,
|
|
38
|
+
startDelay: { min: 0.0, max: 0.0 },
|
|
39
|
+
startLifeTime: { min: 2.0, max: 2.0 },
|
|
40
|
+
startSpeed: { min: 1.0, max: 1.0 },
|
|
41
|
+
startSize: { min: 1.0, max: 1.0 },
|
|
42
|
+
startRotation: { min: 0.0, max: 0.0 },
|
|
43
|
+
startColor: {
|
|
44
|
+
min: { r: 1.0, g: 1.0, b: 1.0 },
|
|
45
|
+
max: { r: 1.0, g: 1.0, b: 1.0 },
|
|
46
|
+
},
|
|
47
|
+
startOpacity: { min: 1.0, max: 1.0 },
|
|
48
|
+
gravity: 0,
|
|
49
|
+
simulationSpace: SimulationSpace.LOCAL,
|
|
50
|
+
maxParticles: 100.0,
|
|
51
|
+
emission: {
|
|
52
|
+
rateOverTime: 10.0,
|
|
53
|
+
rateOverDistance: 0.0,
|
|
54
|
+
},
|
|
55
|
+
shape: {
|
|
56
|
+
shape: Shape.SPHERE,
|
|
57
|
+
sphere: {
|
|
58
|
+
radius: 1.0,
|
|
59
|
+
radiusThickness: 1.0,
|
|
60
|
+
arc: 360.0,
|
|
61
|
+
},
|
|
62
|
+
cone: {
|
|
63
|
+
angle: 25.0,
|
|
64
|
+
radius: 1.0,
|
|
65
|
+
radiusThickness: 1.0,
|
|
66
|
+
arc: 360.0,
|
|
67
|
+
},
|
|
68
|
+
circle: {
|
|
69
|
+
radius: 1.0,
|
|
70
|
+
radiusThickness: 1.0,
|
|
71
|
+
arc: 360.0,
|
|
72
|
+
},
|
|
73
|
+
rectangle: {
|
|
74
|
+
rotation: { x: 0.0, y: 0.0 }, // TODO: add z rotation
|
|
75
|
+
scale: { x: 1.0, y: 1.0 },
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
map: null,
|
|
79
|
+
textureSheetAnimation: { tiles: new THREE.Vector2(1.0, 1.0), fps: 30.0 },
|
|
33
80
|
};
|
|
34
81
|
|
|
35
82
|
const createFloat32Attributes = ({
|
|
@@ -53,7 +100,7 @@ const createFloat32Attributes = ({
|
|
|
53
100
|
};
|
|
54
101
|
|
|
55
102
|
const calculatePositionAndVelocity = (
|
|
56
|
-
{ shape, sphere, cone, circle },
|
|
103
|
+
{ shape, sphere, cone, circle, rectangle },
|
|
57
104
|
startSpeed,
|
|
58
105
|
position,
|
|
59
106
|
velocity
|
|
@@ -85,78 +132,46 @@ const calculatePositionAndVelocity = (
|
|
|
85
132
|
circle
|
|
86
133
|
);
|
|
87
134
|
break;
|
|
135
|
+
|
|
136
|
+
case Shape.RECTANGLE:
|
|
137
|
+
calculateRandomPositionAndVelocityOnRectangle(
|
|
138
|
+
position,
|
|
139
|
+
velocity,
|
|
140
|
+
startSpeed,
|
|
141
|
+
rectangle
|
|
142
|
+
);
|
|
143
|
+
break;
|
|
88
144
|
}
|
|
89
145
|
};
|
|
90
146
|
|
|
91
|
-
export const createParticleSystem = (
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
startDelay = { min: 0.0, max: 0.0 },
|
|
95
|
-
startLifeTime = { min: 5.0, max: 5.0 },
|
|
96
|
-
startSpeed = { min: 5.0, max: 5.0 },
|
|
97
|
-
startSize = { min: 1.0, max: 1.0 },
|
|
98
|
-
startRotation = { min: 0.0, max: 0.0 },
|
|
99
|
-
startColor = {
|
|
100
|
-
min: { r: 1.0, g: 1.0, b: 1.0 },
|
|
101
|
-
max: { r: 1.0, g: 1.0, b: 1.0 },
|
|
102
|
-
},
|
|
103
|
-
startOpacity = { min: 1.0, max: 1.0 },
|
|
104
|
-
gravity = 0.0,
|
|
105
|
-
simulationSpace = SimulationSpace.LOCAL,
|
|
106
|
-
maxParticles = 100,
|
|
107
|
-
emission = {
|
|
108
|
-
rateOverTime: 10.0,
|
|
109
|
-
rateOverDistance: 0.0,
|
|
110
|
-
},
|
|
111
|
-
shape,
|
|
112
|
-
map,
|
|
113
|
-
onUpdate = null,
|
|
114
|
-
onComplete = null,
|
|
115
|
-
textureSheetAnimation = defaultTextureSheetAnimation,
|
|
116
|
-
}) => {
|
|
147
|
+
export const createParticleSystem = (
|
|
148
|
+
config = DEFAULT_PARTICLE_SYSTEM_CONFIG
|
|
149
|
+
) => {
|
|
117
150
|
const now = Date.now();
|
|
118
151
|
const lastWorldPosition = new THREE.Vector3(-99999, -99999, -99999);
|
|
119
152
|
const worldPositionChange = new THREE.Vector3();
|
|
120
153
|
const generalData = { distanceFromLastEmitByDistance: 0 };
|
|
121
154
|
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
arc: 360.0,
|
|
143
|
-
...shape.sphere,
|
|
144
|
-
},
|
|
145
|
-
cone: {
|
|
146
|
-
angle: 25,
|
|
147
|
-
radius: 1.0,
|
|
148
|
-
radiusThickness: 1.0,
|
|
149
|
-
arc: 360.0,
|
|
150
|
-
...shape.cone,
|
|
151
|
-
},
|
|
152
|
-
circle: {
|
|
153
|
-
radius: 1.0,
|
|
154
|
-
radiusThickness: 1.0,
|
|
155
|
-
arc: 360.0,
|
|
156
|
-
...shape.circle,
|
|
157
|
-
},
|
|
158
|
-
...shape,
|
|
159
|
-
};
|
|
155
|
+
const {
|
|
156
|
+
duration,
|
|
157
|
+
looping,
|
|
158
|
+
startDelay,
|
|
159
|
+
startLifeTime,
|
|
160
|
+
startSpeed,
|
|
161
|
+
startSize,
|
|
162
|
+
startRotation,
|
|
163
|
+
startColor,
|
|
164
|
+
startOpacity,
|
|
165
|
+
gravity,
|
|
166
|
+
simulationSpace,
|
|
167
|
+
maxParticles,
|
|
168
|
+
emission,
|
|
169
|
+
shape,
|
|
170
|
+
map,
|
|
171
|
+
onUpdate,
|
|
172
|
+
onComplete,
|
|
173
|
+
textureSheetAnimation,
|
|
174
|
+
} = deepMerge(DEFAULT_PARTICLE_SYSTEM_CONFIG, config);
|
|
160
175
|
|
|
161
176
|
const startPositions = Array.from(
|
|
162
177
|
{ length: maxParticles },
|
|
@@ -167,18 +182,10 @@ export const createParticleSystem = ({
|
|
|
167
182
|
() => new THREE.Vector3()
|
|
168
183
|
);
|
|
169
184
|
|
|
170
|
-
const
|
|
171
|
-
...defaultTextureSheetAnimation,
|
|
172
|
-
...textureSheetAnimation,
|
|
173
|
-
};
|
|
174
|
-
rawUniforms.tiles = rawUniforms.tiles
|
|
175
|
-
? rawUniforms.tiles
|
|
176
|
-
: defaultTextureSheetAnimation.tiles;
|
|
177
|
-
|
|
178
|
-
const uniforms = Object.keys(rawUniforms).reduce(
|
|
185
|
+
const uniforms = Object.keys(textureSheetAnimation).reduce(
|
|
179
186
|
(prev, key) => ({
|
|
180
187
|
...prev,
|
|
181
|
-
[key]: { value:
|
|
188
|
+
[key]: { value: textureSheetAnimation[key] },
|
|
182
189
|
}),
|
|
183
190
|
{}
|
|
184
191
|
);
|
|
@@ -205,8 +212,8 @@ export const createParticleSystem = ({
|
|
|
205
212
|
|
|
206
213
|
for (let i = 0; i < maxParticles; i++)
|
|
207
214
|
calculatePositionAndVelocity(
|
|
208
|
-
|
|
209
|
-
|
|
215
|
+
shape,
|
|
216
|
+
startSpeed,
|
|
210
217
|
startPositions[i],
|
|
211
218
|
velocities[i]
|
|
212
219
|
);
|
|
@@ -230,10 +237,7 @@ export const createParticleSystem = ({
|
|
|
230
237
|
createFloat32AttributesRequest("creationTime", 0);
|
|
231
238
|
createFloat32AttributesRequest("lifeTime", 0);
|
|
232
239
|
createFloat32AttributesRequest("startLifeTime", () =>
|
|
233
|
-
THREE.MathUtils.randFloat(
|
|
234
|
-
normalizedStartLifeTime.min,
|
|
235
|
-
normalizedStartLifeTime.max
|
|
236
|
-
)
|
|
240
|
+
THREE.MathUtils.randFloat(startLifeTime.min, startLifeTime.max)
|
|
237
241
|
);
|
|
238
242
|
|
|
239
243
|
createFloat32AttributesRequest("opacity", 0);
|
|
@@ -244,10 +248,7 @@ export const createParticleSystem = ({
|
|
|
244
248
|
maxParticles,
|
|
245
249
|
factory: () =>
|
|
246
250
|
THREE.Math.degToRad(
|
|
247
|
-
THREE.MathUtils.randFloat(
|
|
248
|
-
normalizedStartRotation.min,
|
|
249
|
-
normalizedStartRotation.max
|
|
250
|
-
)
|
|
251
|
+
THREE.MathUtils.randFloat(startRotation.min, startRotation.max)
|
|
251
252
|
),
|
|
252
253
|
});
|
|
253
254
|
|
|
@@ -255,11 +256,7 @@ export const createParticleSystem = ({
|
|
|
255
256
|
geometry,
|
|
256
257
|
propertyName: "startSize",
|
|
257
258
|
maxParticles,
|
|
258
|
-
factory: () =>
|
|
259
|
-
THREE.MathUtils.randFloat(
|
|
260
|
-
normalizedStartSize.min,
|
|
261
|
-
normalizedStartSize.max
|
|
262
|
-
),
|
|
259
|
+
factory: () => THREE.MathUtils.randFloat(startSize.min, startSize.max),
|
|
263
260
|
});
|
|
264
261
|
|
|
265
262
|
createFloat32AttributesRequest("rotation", 0);
|
|
@@ -268,23 +265,20 @@ export const createParticleSystem = ({
|
|
|
268
265
|
createFloat32AttributesRequest(
|
|
269
266
|
"colorR",
|
|
270
267
|
() =>
|
|
271
|
-
|
|
272
|
-
colorRandomRatio *
|
|
273
|
-
(normalizedStartColor.max.r - normalizedStartColor.min.r)
|
|
268
|
+
startColor.min.r +
|
|
269
|
+
colorRandomRatio * (startColor.max.r - startColor.min.r)
|
|
274
270
|
);
|
|
275
271
|
createFloat32AttributesRequest(
|
|
276
272
|
"colorG",
|
|
277
273
|
() =>
|
|
278
|
-
|
|
279
|
-
colorRandomRatio *
|
|
280
|
-
(normalizedStartColor.max.g - normalizedStartColor.min.g)
|
|
274
|
+
startColor.min.g +
|
|
275
|
+
colorRandomRatio * (startColor.max.g - startColor.min.g)
|
|
281
276
|
);
|
|
282
277
|
createFloat32AttributesRequest(
|
|
283
278
|
"colorB",
|
|
284
279
|
() =>
|
|
285
|
-
|
|
286
|
-
colorRandomRatio *
|
|
287
|
-
(normalizedStartColor.max.b - normalizedStartColor.min.b)
|
|
280
|
+
startColor.min.b +
|
|
281
|
+
colorRandomRatio * (startColor.max.b - startColor.min.b)
|
|
288
282
|
);
|
|
289
283
|
createFloat32AttributesRequest("colorA", 0);
|
|
290
284
|
|
|
@@ -304,54 +298,42 @@ export const createParticleSystem = ({
|
|
|
304
298
|
const colorRandomRatio = Math.random();
|
|
305
299
|
|
|
306
300
|
geometry.attributes.colorR.array[particleIndex] =
|
|
307
|
-
|
|
308
|
-
colorRandomRatio *
|
|
309
|
-
(normalizedStartColor.max.r - normalizedStartColor.min.r);
|
|
301
|
+
startColor.min.r +
|
|
302
|
+
colorRandomRatio * (startColor.max.r - startColor.min.r);
|
|
310
303
|
geometry.attributes.colorR.needsUpdate = true;
|
|
311
304
|
|
|
312
305
|
geometry.attributes.colorG.array[particleIndex] =
|
|
313
|
-
|
|
314
|
-
colorRandomRatio *
|
|
315
|
-
(normalizedStartColor.max.g - normalizedStartColor.min.g);
|
|
306
|
+
startColor.min.g +
|
|
307
|
+
colorRandomRatio * (startColor.max.g - startColor.min.g);
|
|
316
308
|
geometry.attributes.colorG.needsUpdate = true;
|
|
317
309
|
|
|
318
310
|
geometry.attributes.colorB.array[particleIndex] =
|
|
319
|
-
|
|
320
|
-
colorRandomRatio *
|
|
321
|
-
(normalizedStartColor.max.b - normalizedStartColor.min.b);
|
|
311
|
+
startColor.min.b +
|
|
312
|
+
colorRandomRatio * (startColor.max.b - startColor.min.b);
|
|
322
313
|
geometry.attributes.colorB.needsUpdate = true;
|
|
323
314
|
|
|
324
315
|
geometry.attributes.colorA.array[particleIndex] = THREE.MathUtils.randFloat(
|
|
325
|
-
|
|
326
|
-
|
|
316
|
+
startOpacity.min,
|
|
317
|
+
startOpacity.max
|
|
327
318
|
);
|
|
328
319
|
geometry.attributes.colorA.needsUpdate = true;
|
|
329
320
|
|
|
330
321
|
geometry.attributes.startLifeTime.array[particleIndex] =
|
|
331
|
-
THREE.MathUtils.randFloat(
|
|
332
|
-
normalizedStartLifeTime.min,
|
|
333
|
-
normalizedStartLifeTime.max
|
|
334
|
-
) * 1000;
|
|
322
|
+
THREE.MathUtils.randFloat(startLifeTime.min, startLifeTime.max) * 1000;
|
|
335
323
|
geometry.attributes.startLifeTime.needsUpdate = true;
|
|
336
324
|
|
|
337
325
|
geometry.attributes.startSize.array[particleIndex] =
|
|
338
|
-
THREE.MathUtils.randFloat(
|
|
339
|
-
normalizedStartSize.min,
|
|
340
|
-
normalizedStartSize.max
|
|
341
|
-
);
|
|
326
|
+
THREE.MathUtils.randFloat(startSize.min, startSize.max);
|
|
342
327
|
geometry.attributes.startSize.needsUpdate = true;
|
|
343
328
|
|
|
344
329
|
geometry.attributes.rotation.array[particleIndex] = THREE.Math.degToRad(
|
|
345
|
-
THREE.MathUtils.randFloat(
|
|
346
|
-
normalizedStartRotation.min,
|
|
347
|
-
normalizedStartRotation.max
|
|
348
|
-
)
|
|
330
|
+
THREE.MathUtils.randFloat(startRotation.min, startRotation.max)
|
|
349
331
|
);
|
|
350
332
|
geometry.attributes.rotation.needsUpdate = true;
|
|
351
333
|
|
|
352
334
|
calculatePositionAndVelocity(
|
|
353
|
-
|
|
354
|
-
|
|
335
|
+
shape,
|
|
336
|
+
startSpeed,
|
|
355
337
|
startPositions[particleIndex],
|
|
356
338
|
velocities[particleIndex]
|
|
357
339
|
);
|
|
@@ -372,12 +354,7 @@ export const createParticleSystem = ({
|
|
|
372
354
|
particleSystem.sortParticles = true;
|
|
373
355
|
|
|
374
356
|
const calculatedCreationTime =
|
|
375
|
-
now +
|
|
376
|
-
THREE.MathUtils.randFloat(
|
|
377
|
-
normalizedStartDelay.min,
|
|
378
|
-
normalizedStartDelay.max
|
|
379
|
-
) *
|
|
380
|
-
1000;
|
|
357
|
+
now + THREE.MathUtils.randFloat(startDelay.min, startDelay.max) * 1000;
|
|
381
358
|
|
|
382
359
|
createdParticleSystems.push({
|
|
383
360
|
particleSystem,
|
|
@@ -392,7 +369,7 @@ export const createParticleSystem = ({
|
|
|
392
369
|
looping,
|
|
393
370
|
simulationSpace,
|
|
394
371
|
gravity,
|
|
395
|
-
emission
|
|
372
|
+
emission,
|
|
396
373
|
iterationCount: 0,
|
|
397
374
|
velocities,
|
|
398
375
|
deactivateParticle,
|