@newkrok/three-particles 2.15.2 → 2.16.1
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 +80 -0
- package/dist/index.d.ts +362 -7
- package/dist/index.js +1041 -395
- package/dist/index.js.map +1 -1
- package/dist/three-particles.min.js +1 -1
- package/dist/three-particles.min.js.map +1 -1
- package/dist/webgpu.js +1664 -0
- package/dist/webgpu.js.map +1 -0
- package/llms-full.txt +189 -0
- package/llms.txt +89 -0
- package/package.json +15 -10
- package/webgpu.d.ts +88 -0
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Easing from 'easing-functions';
|
|
2
|
-
import * as
|
|
2
|
+
import * as THREE5 from 'three';
|
|
3
3
|
import { ObjectUtils } from '@newkrok/three-utils';
|
|
4
4
|
import { Gyroscope } from 'three/examples/jsm/misc/Gyroscope.js';
|
|
5
5
|
import { FBM } from 'three-noise/build/three-noise.module.js';
|
|
@@ -60,40 +60,40 @@ var removeBezierCurveFunction = (particleSystemId) => {
|
|
|
60
60
|
}
|
|
61
61
|
};
|
|
62
62
|
var getBezierCacheSize = () => cache.length;
|
|
63
|
-
var CurveFunctionId = /* @__PURE__ */ ((
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
return
|
|
63
|
+
var CurveFunctionId = /* @__PURE__ */ ((CurveFunctionId3) => {
|
|
64
|
+
CurveFunctionId3["BEZIER"] = "BEZIER";
|
|
65
|
+
CurveFunctionId3["LINEAR"] = "LINEAR";
|
|
66
|
+
CurveFunctionId3["QUADRATIC_IN"] = "QUADRATIC_IN";
|
|
67
|
+
CurveFunctionId3["QUADRATIC_OUT"] = "QUADRATIC_OUT";
|
|
68
|
+
CurveFunctionId3["QUADRATIC_IN_OUT"] = "QUADRATIC_IN_OUT";
|
|
69
|
+
CurveFunctionId3["CUBIC_IN"] = "CUBIC_IN";
|
|
70
|
+
CurveFunctionId3["CUBIC_OUT"] = "CUBIC_OUT";
|
|
71
|
+
CurveFunctionId3["CUBIC_IN_OUT"] = "CUBIC_IN_OUT";
|
|
72
|
+
CurveFunctionId3["QUARTIC_IN"] = "QUARTIC_IN";
|
|
73
|
+
CurveFunctionId3["QUARTIC_OUT"] = "QUARTIC_OUT";
|
|
74
|
+
CurveFunctionId3["QUARTIC_IN_OUT"] = "QUARTIC_IN_OUT";
|
|
75
|
+
CurveFunctionId3["QUINTIC_IN"] = "QUINTIC_IN";
|
|
76
|
+
CurveFunctionId3["QUINTIC_OUT"] = "QUINTIC_OUT";
|
|
77
|
+
CurveFunctionId3["QUINTIC_IN_OUT"] = "QUINTIC_IN_OUT";
|
|
78
|
+
CurveFunctionId3["SINUSOIDAL_IN"] = "SINUSOIDAL_IN";
|
|
79
|
+
CurveFunctionId3["SINUSOIDAL_OUT"] = "SINUSOIDAL_OUT";
|
|
80
|
+
CurveFunctionId3["SINUSOIDAL_IN_OUT"] = "SINUSOIDAL_IN_OUT";
|
|
81
|
+
CurveFunctionId3["EXPONENTIAL_IN"] = "EXPONENTIAL_IN";
|
|
82
|
+
CurveFunctionId3["EXPONENTIAL_OUT"] = "EXPONENTIAL_OUT";
|
|
83
|
+
CurveFunctionId3["EXPONENTIAL_IN_OUT"] = "EXPONENTIAL_IN_OUT";
|
|
84
|
+
CurveFunctionId3["CIRCULAR_IN"] = "CIRCULAR_IN";
|
|
85
|
+
CurveFunctionId3["CIRCULAR_OUT"] = "CIRCULAR_OUT";
|
|
86
|
+
CurveFunctionId3["CIRCULAR_IN_OUT"] = "CIRCULAR_IN_OUT";
|
|
87
|
+
CurveFunctionId3["ELASTIC_IN"] = "ELASTIC_IN";
|
|
88
|
+
CurveFunctionId3["ELASTIC_OUT"] = "ELASTIC_OUT";
|
|
89
|
+
CurveFunctionId3["ELASTIC_IN_OUT"] = "ELASTIC_IN_OUT";
|
|
90
|
+
CurveFunctionId3["BACK_IN"] = "BACK_IN";
|
|
91
|
+
CurveFunctionId3["BACK_OUT"] = "BACK_OUT";
|
|
92
|
+
CurveFunctionId3["BACK_IN_OUT"] = "BACK_IN_OUT";
|
|
93
|
+
CurveFunctionId3["BOUNCE_IN"] = "BOUNCE_IN";
|
|
94
|
+
CurveFunctionId3["BOUNCE_OUT"] = "BOUNCE_OUT";
|
|
95
|
+
CurveFunctionId3["BOUNCE_IN_OUT"] = "BOUNCE_IN_OUT";
|
|
96
|
+
return CurveFunctionId3;
|
|
97
97
|
})(CurveFunctionId || {});
|
|
98
98
|
var curveFunctionIdMap = {
|
|
99
99
|
["LINEAR" /* LINEAR */]: Easing.Linear.None,
|
|
@@ -165,10 +165,10 @@ var SubEmitterTrigger = /* @__PURE__ */ ((SubEmitterTrigger2) => {
|
|
|
165
165
|
SubEmitterTrigger2["DEATH"] = "DEATH";
|
|
166
166
|
return SubEmitterTrigger2;
|
|
167
167
|
})(SubEmitterTrigger || {});
|
|
168
|
-
var ForceFieldType = /* @__PURE__ */ ((
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
return
|
|
168
|
+
var ForceFieldType = /* @__PURE__ */ ((ForceFieldType3) => {
|
|
169
|
+
ForceFieldType3["POINT"] = "POINT";
|
|
170
|
+
ForceFieldType3["DIRECTIONAL"] = "DIRECTIONAL";
|
|
171
|
+
return ForceFieldType3;
|
|
172
172
|
})(ForceFieldType || {});
|
|
173
173
|
var RendererType = /* @__PURE__ */ ((RendererType2) => {
|
|
174
174
|
RendererType2["POINTS"] = "POINTS";
|
|
@@ -177,12 +177,37 @@ var RendererType = /* @__PURE__ */ ((RendererType2) => {
|
|
|
177
177
|
RendererType2["MESH"] = "MESH";
|
|
178
178
|
return RendererType2;
|
|
179
179
|
})(RendererType || {});
|
|
180
|
-
var ForceFieldFalloff = /* @__PURE__ */ ((
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
return
|
|
180
|
+
var ForceFieldFalloff = /* @__PURE__ */ ((ForceFieldFalloff3) => {
|
|
181
|
+
ForceFieldFalloff3["NONE"] = "NONE";
|
|
182
|
+
ForceFieldFalloff3["LINEAR"] = "LINEAR";
|
|
183
|
+
ForceFieldFalloff3["QUADRATIC"] = "QUADRATIC";
|
|
184
|
+
return ForceFieldFalloff3;
|
|
185
185
|
})(ForceFieldFalloff || {});
|
|
186
|
+
var CollisionPlaneMode = /* @__PURE__ */ ((CollisionPlaneMode3) => {
|
|
187
|
+
CollisionPlaneMode3["KILL"] = "KILL";
|
|
188
|
+
CollisionPlaneMode3["CLAMP"] = "CLAMP";
|
|
189
|
+
CollisionPlaneMode3["BOUNCE"] = "BOUNCE";
|
|
190
|
+
return CollisionPlaneMode3;
|
|
191
|
+
})(CollisionPlaneMode || {});
|
|
192
|
+
var SimulationBackend = /* @__PURE__ */ ((SimulationBackend2) => {
|
|
193
|
+
SimulationBackend2["AUTO"] = "AUTO";
|
|
194
|
+
SimulationBackend2["CPU"] = "CPU";
|
|
195
|
+
SimulationBackend2["GPU"] = "GPU";
|
|
196
|
+
return SimulationBackend2;
|
|
197
|
+
})(SimulationBackend || {});
|
|
198
|
+
|
|
199
|
+
// src/js/effects/three-particles/three-particles-constants.ts
|
|
200
|
+
var SCALAR_STRIDE = 10;
|
|
201
|
+
var S_IS_ACTIVE = 0;
|
|
202
|
+
var S_LIFETIME = 1;
|
|
203
|
+
var S_START_LIFETIME = 2;
|
|
204
|
+
var S_START_FRAME = 3;
|
|
205
|
+
var S_SIZE = 4;
|
|
206
|
+
var S_ROTATION = 5;
|
|
207
|
+
var S_COLOR_R = 6;
|
|
208
|
+
var S_COLOR_G = 7;
|
|
209
|
+
var S_COLOR_B = 8;
|
|
210
|
+
var S_COLOR_A = 9;
|
|
186
211
|
var calculateRandomPositionAndVelocityOnSphere = (position, quaternion, velocity, speed, {
|
|
187
212
|
radius,
|
|
188
213
|
radiusThickness,
|
|
@@ -227,7 +252,7 @@ var calculateRandomPositionAndVelocityOnCone = (position, quaternion, velocity,
|
|
|
227
252
|
position.applyQuaternion(quaternion);
|
|
228
253
|
const positionLength = position.length();
|
|
229
254
|
const normalizedAngle = Math.abs(
|
|
230
|
-
positionLength / radius *
|
|
255
|
+
positionLength / radius * THREE5.MathUtils.degToRad(angle)
|
|
231
256
|
);
|
|
232
257
|
const sinNormalizedAngle = Math.sin(normalizedAngle);
|
|
233
258
|
const speedMultiplierByPosition = 1 / positionLength;
|
|
@@ -302,8 +327,8 @@ var calculateRandomPositionAndVelocityOnRectangle = (position, quaternion, veloc
|
|
|
302
327
|
const _rotation = rotation;
|
|
303
328
|
const xOffset = Math.random() * _scale.x - _scale.x / 2;
|
|
304
329
|
const yOffset = Math.random() * _scale.y - _scale.y / 2;
|
|
305
|
-
const rotationX =
|
|
306
|
-
const rotationY =
|
|
330
|
+
const rotationX = THREE5.MathUtils.degToRad(_rotation.x);
|
|
331
|
+
const rotationY = THREE5.MathUtils.degToRad(_rotation.y);
|
|
307
332
|
position.x = xOffset * Math.cos(rotationY);
|
|
308
333
|
position.y = yOffset * Math.cos(rotationX);
|
|
309
334
|
position.z = xOffset * Math.sin(rotationY) - yOffset * Math.sin(rotationX);
|
|
@@ -320,7 +345,7 @@ var createDefaultMeshTexture = () => {
|
|
|
320
345
|
if (context) {
|
|
321
346
|
context.fillStyle = "white";
|
|
322
347
|
context.fillRect(0, 0, 1, 1);
|
|
323
|
-
const texture = new
|
|
348
|
+
const texture = new THREE5.CanvasTexture(canvas);
|
|
324
349
|
texture.needsUpdate = true;
|
|
325
350
|
return texture;
|
|
326
351
|
}
|
|
@@ -344,7 +369,7 @@ var createDefaultParticleTexture = () => {
|
|
|
344
369
|
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
|
|
345
370
|
context.fillStyle = "white";
|
|
346
371
|
context.fill();
|
|
347
|
-
const texture = new
|
|
372
|
+
const texture = new THREE5.CanvasTexture(canvas);
|
|
348
373
|
texture.needsUpdate = true;
|
|
349
374
|
return texture;
|
|
350
375
|
} else {
|
|
@@ -381,20 +406,21 @@ var calculateValue = (particleSystemId, value, time = 0) => {
|
|
|
381
406
|
if (value.min === value.max) {
|
|
382
407
|
return value.min ?? 0;
|
|
383
408
|
}
|
|
384
|
-
return
|
|
409
|
+
return THREE5.MathUtils.randFloat(value.min ?? 0, value.max ?? 1);
|
|
385
410
|
}
|
|
386
411
|
const lifetimeCurve = value;
|
|
387
412
|
return getCurveFunctionFromConfig(particleSystemId, lifetimeCurve)(time) * (lifetimeCurve.scale ?? 1);
|
|
388
413
|
};
|
|
389
414
|
|
|
390
415
|
// src/js/effects/three-particles/three-particles-modifiers.ts
|
|
391
|
-
var noiseInput = new
|
|
392
|
-
var orbitalEuler = new
|
|
416
|
+
var noiseInput = new THREE5.Vector3(0, 0, 0);
|
|
417
|
+
var orbitalEuler = new THREE5.Euler();
|
|
393
418
|
var applyModifiers = ({
|
|
394
419
|
delta,
|
|
395
420
|
generalData,
|
|
396
421
|
normalizedConfig,
|
|
397
422
|
attributes,
|
|
423
|
+
scalarArray,
|
|
398
424
|
particleLifetimePercentage,
|
|
399
425
|
particleIndex
|
|
400
426
|
}) => {
|
|
@@ -408,6 +434,7 @@ var applyModifiers = ({
|
|
|
408
434
|
} = generalData;
|
|
409
435
|
const positionIndex = particleIndex * 3;
|
|
410
436
|
const positionArr = attributes.position.array;
|
|
437
|
+
const base = particleIndex * SCALAR_STRIDE;
|
|
411
438
|
if (linearVelocityData) {
|
|
412
439
|
const { speed, valueModifiers } = linearVelocityData[particleIndex];
|
|
413
440
|
const normalizedXSpeed = valueModifiers.x ? valueModifiers.x(particleLifetimePercentage) : speed.x;
|
|
@@ -443,8 +470,7 @@ var applyModifiers = ({
|
|
|
443
470
|
normalizedConfig.sizeOverLifetime.lifetimeCurve,
|
|
444
471
|
particleLifetimePercentage
|
|
445
472
|
);
|
|
446
|
-
|
|
447
|
-
attributes.size.needsUpdate = true;
|
|
473
|
+
scalarArray[base + S_SIZE] = startValues.startSize[particleIndex] * multiplier;
|
|
448
474
|
}
|
|
449
475
|
if (normalizedConfig.opacityOverLifetime.isActive) {
|
|
450
476
|
const multiplier = calculateValue(
|
|
@@ -452,8 +478,7 @@ var applyModifiers = ({
|
|
|
452
478
|
normalizedConfig.opacityOverLifetime.lifetimeCurve,
|
|
453
479
|
particleLifetimePercentage
|
|
454
480
|
);
|
|
455
|
-
|
|
456
|
-
attributes.colorA.needsUpdate = true;
|
|
481
|
+
scalarArray[base + S_COLOR_A] = startValues.startOpacity[particleIndex] * multiplier;
|
|
457
482
|
}
|
|
458
483
|
if (normalizedConfig.colorOverLifetime.isActive) {
|
|
459
484
|
const rMultiplier = calculateValue(
|
|
@@ -471,16 +496,12 @@ var applyModifiers = ({
|
|
|
471
496
|
normalizedConfig.colorOverLifetime.b,
|
|
472
497
|
particleLifetimePercentage
|
|
473
498
|
);
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
attributes.colorR.needsUpdate = true;
|
|
478
|
-
attributes.colorG.needsUpdate = true;
|
|
479
|
-
attributes.colorB.needsUpdate = true;
|
|
499
|
+
scalarArray[base + S_COLOR_R] = startValues.startColorR[particleIndex] * rMultiplier;
|
|
500
|
+
scalarArray[base + S_COLOR_G] = startValues.startColorG[particleIndex] * gMultiplier;
|
|
501
|
+
scalarArray[base + S_COLOR_B] = startValues.startColorB[particleIndex] * bMultiplier;
|
|
480
502
|
}
|
|
481
503
|
if (lifetimeValues.rotationOverLifetime) {
|
|
482
|
-
|
|
483
|
-
attributes.rotation.needsUpdate = true;
|
|
504
|
+
scalarArray[base + S_ROTATION] += lifetimeValues.rotationOverLifetime[particleIndex] * delta * 0.02;
|
|
484
505
|
}
|
|
485
506
|
if (noise.isActive) {
|
|
486
507
|
const {
|
|
@@ -498,12 +519,10 @@ var applyModifiers = ({
|
|
|
498
519
|
noiseOnPosition = sampler.get3(noiseInput);
|
|
499
520
|
positionArr[positionIndex] += noiseOnPosition * noisePower * positionAmount;
|
|
500
521
|
if (rotationAmount !== 0) {
|
|
501
|
-
|
|
502
|
-
attributes.rotation.needsUpdate = true;
|
|
522
|
+
scalarArray[base + S_ROTATION] += noiseOnPosition * noisePower * rotationAmount;
|
|
503
523
|
}
|
|
504
524
|
if (sizeAmount !== 0) {
|
|
505
|
-
|
|
506
|
-
attributes.size.needsUpdate = true;
|
|
525
|
+
scalarArray[base + S_SIZE] += noiseOnPosition * noisePower * sizeAmount;
|
|
507
526
|
}
|
|
508
527
|
noiseInput.set(noisePosition, noisePosition, 0);
|
|
509
528
|
noiseOnPosition = sampler.get3(noiseInput);
|
|
@@ -514,7 +533,7 @@ var applyModifiers = ({
|
|
|
514
533
|
attributes.position.needsUpdate = true;
|
|
515
534
|
}
|
|
516
535
|
if (attributes.quat) {
|
|
517
|
-
const rotZ =
|
|
536
|
+
const rotZ = scalarArray[base + S_ROTATION];
|
|
518
537
|
const halfZ = rotZ * 0.5;
|
|
519
538
|
const qi = particleIndex * 4;
|
|
520
539
|
attributes.quat.array[qi] = 0;
|
|
@@ -525,6 +544,21 @@ var applyModifiers = ({
|
|
|
525
544
|
}
|
|
526
545
|
};
|
|
527
546
|
|
|
547
|
+
// src/js/effects/three-particles/three-particles-renderer-detect.ts
|
|
548
|
+
function isComputeCapableRenderer(renderer) {
|
|
549
|
+
return renderer !== null && renderer !== void 0 && typeof renderer === "object" && "compute" in renderer && typeof renderer.compute === "function" && "hasFeature" in renderer && typeof renderer.hasFeature === "function";
|
|
550
|
+
}
|
|
551
|
+
function resolveSimulationBackend(renderer, preference = "AUTO" /* AUTO */) {
|
|
552
|
+
const gpuCapable = isComputeCapableRenderer(renderer);
|
|
553
|
+
if (preference === "CPU" /* CPU */) {
|
|
554
|
+
return "CPU" /* CPU */;
|
|
555
|
+
}
|
|
556
|
+
if (preference === "GPU" /* GPU */) {
|
|
557
|
+
return gpuCapable ? "GPU" /* GPU */ : "CPU" /* CPU */;
|
|
558
|
+
}
|
|
559
|
+
return gpuCapable ? "GPU" /* GPU */ : "CPU" /* CPU */;
|
|
560
|
+
}
|
|
561
|
+
|
|
528
562
|
// src/js/effects/three-particles/shaders/instanced-particle-fragment-shader.glsl.ts
|
|
529
563
|
var InstancedParticleFragmentShader = `
|
|
530
564
|
uniform sampler2D map;
|
|
@@ -616,10 +650,7 @@ var instanced_particle_fragment_shader_glsl_default = InstancedParticleFragmentS
|
|
|
616
650
|
// src/js/effects/three-particles/shaders/instanced-particle-vertex-shader.glsl.ts
|
|
617
651
|
var InstancedParticleVertexShader = `
|
|
618
652
|
attribute float instanceSize;
|
|
619
|
-
attribute
|
|
620
|
-
attribute float instanceColorG;
|
|
621
|
-
attribute float instanceColorB;
|
|
622
|
-
attribute float instanceColorA;
|
|
653
|
+
attribute vec4 instanceColor;
|
|
623
654
|
attribute float instanceLifetime;
|
|
624
655
|
attribute float instanceStartLifetime;
|
|
625
656
|
attribute float instanceRotation;
|
|
@@ -641,7 +672,14 @@ var InstancedParticleVertexShader = `
|
|
|
641
672
|
|
|
642
673
|
void main()
|
|
643
674
|
{
|
|
644
|
-
|
|
675
|
+
// Early-out for dead particles: skip all transforms and emit a degenerate
|
|
676
|
+
// position that produces zero-area triangles.
|
|
677
|
+
if (instanceColor.a <= 0.0) {
|
|
678
|
+
gl_Position = vec4(0.0, 0.0, 0.0, 0.0);
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
vColor = instanceColor;
|
|
645
683
|
vLifetime = instanceLifetime;
|
|
646
684
|
vStartLifetime = instanceStartLifetime;
|
|
647
685
|
vStartFrame = instanceStartFrame;
|
|
@@ -766,10 +804,7 @@ var mesh_particle_fragment_shader_glsl_default = MeshParticleFragmentShader;
|
|
|
766
804
|
// src/js/effects/three-particles/shaders/mesh-particle-vertex-shader.glsl.ts
|
|
767
805
|
var MeshParticleVertexShader = `
|
|
768
806
|
attribute float instanceSize;
|
|
769
|
-
attribute
|
|
770
|
-
attribute float instanceColorG;
|
|
771
|
-
attribute float instanceColorB;
|
|
772
|
-
attribute float instanceColorA;
|
|
807
|
+
attribute vec4 instanceColor;
|
|
773
808
|
attribute float instanceLifetime;
|
|
774
809
|
attribute float instanceStartLifetime;
|
|
775
810
|
attribute float instanceRotation;
|
|
@@ -796,7 +831,14 @@ var MeshParticleVertexShader = `
|
|
|
796
831
|
|
|
797
832
|
void main()
|
|
798
833
|
{
|
|
799
|
-
|
|
834
|
+
// Early-out for dead particles: skip all expensive transforms and emit
|
|
835
|
+
// a degenerate position that produces zero-area triangles.
|
|
836
|
+
if (instanceColor.a <= 0.0) {
|
|
837
|
+
gl_Position = vec4(0.0, 0.0, 0.0, 0.0);
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
vColor = instanceColor;
|
|
800
842
|
vLifetime = instanceLifetime;
|
|
801
843
|
vStartLifetime = instanceStartLifetime;
|
|
802
844
|
vStartFrame = instanceStartFrame;
|
|
@@ -922,10 +964,7 @@ var particle_system_fragment_shader_glsl_default = ParticleSystemFragmentShader;
|
|
|
922
964
|
// src/js/effects/three-particles/shaders/particle-system-vertex-shader.glsl.ts
|
|
923
965
|
var ParticleSystemVertexShader = `
|
|
924
966
|
attribute float size;
|
|
925
|
-
attribute
|
|
926
|
-
attribute float colorG;
|
|
927
|
-
attribute float colorB;
|
|
928
|
-
attribute float colorA;
|
|
967
|
+
attribute vec4 color;
|
|
929
968
|
attribute float lifetime;
|
|
930
969
|
attribute float startLifetime;
|
|
931
970
|
attribute float rotation;
|
|
@@ -944,7 +983,7 @@ var ParticleSystemVertexShader = `
|
|
|
944
983
|
|
|
945
984
|
void main()
|
|
946
985
|
{
|
|
947
|
-
vColor =
|
|
986
|
+
vColor = color;
|
|
948
987
|
vLifetime = lifetime;
|
|
949
988
|
vStartLifetime = startLifetime;
|
|
950
989
|
vRotation = rotation;
|
|
@@ -1088,7 +1127,69 @@ var TrailVertexShader = `
|
|
|
1088
1127
|
}
|
|
1089
1128
|
`;
|
|
1090
1129
|
var trail_vertex_shader_glsl_default = TrailVertexShader;
|
|
1091
|
-
var
|
|
1130
|
+
var _planeToParticle = new THREE5.Vector3();
|
|
1131
|
+
var _normalComponent = new THREE5.Vector3();
|
|
1132
|
+
var applyCollisionPlanes = ({
|
|
1133
|
+
collisionPlanes,
|
|
1134
|
+
velocity,
|
|
1135
|
+
positionArr,
|
|
1136
|
+
positionIndex,
|
|
1137
|
+
scalarArr,
|
|
1138
|
+
scalarBase,
|
|
1139
|
+
deactivateParticle,
|
|
1140
|
+
particleIndex
|
|
1141
|
+
}) => {
|
|
1142
|
+
for (let i = 0; i < collisionPlanes.length; i++) {
|
|
1143
|
+
const plane = collisionPlanes[i];
|
|
1144
|
+
if (!plane.isActive) continue;
|
|
1145
|
+
const normal = plane.normal;
|
|
1146
|
+
const planePos = plane.position;
|
|
1147
|
+
_planeToParticle.set(
|
|
1148
|
+
positionArr[positionIndex] - planePos.x,
|
|
1149
|
+
positionArr[positionIndex + 1] - planePos.y,
|
|
1150
|
+
positionArr[positionIndex + 2] - planePos.z
|
|
1151
|
+
);
|
|
1152
|
+
const signedDistance = _planeToParticle.dot(normal);
|
|
1153
|
+
if (signedDistance >= 0) continue;
|
|
1154
|
+
switch (plane.mode) {
|
|
1155
|
+
case "KILL" /* KILL */:
|
|
1156
|
+
deactivateParticle(particleIndex);
|
|
1157
|
+
return true;
|
|
1158
|
+
case "CLAMP" /* CLAMP */:
|
|
1159
|
+
positionArr[positionIndex] = positionArr[positionIndex] - signedDistance * normal.x;
|
|
1160
|
+
positionArr[positionIndex + 1] = positionArr[positionIndex + 1] - signedDistance * normal.y;
|
|
1161
|
+
positionArr[positionIndex + 2] = positionArr[positionIndex + 2] - signedDistance * normal.z;
|
|
1162
|
+
const velDotNormal = velocity.x * normal.x + velocity.y * normal.y + velocity.z * normal.z;
|
|
1163
|
+
if (velDotNormal < 0) {
|
|
1164
|
+
velocity.x -= velDotNormal * normal.x;
|
|
1165
|
+
velocity.y -= velDotNormal * normal.y;
|
|
1166
|
+
velocity.z -= velDotNormal * normal.z;
|
|
1167
|
+
}
|
|
1168
|
+
break;
|
|
1169
|
+
case "BOUNCE" /* BOUNCE */: {
|
|
1170
|
+
positionArr[positionIndex] = positionArr[positionIndex] - signedDistance * normal.x;
|
|
1171
|
+
positionArr[positionIndex + 1] = positionArr[positionIndex + 1] - signedDistance * normal.y;
|
|
1172
|
+
positionArr[positionIndex + 2] = positionArr[positionIndex + 2] - signedDistance * normal.z;
|
|
1173
|
+
const vDotN = velocity.x * normal.x + velocity.y * normal.y + velocity.z * normal.z;
|
|
1174
|
+
_normalComponent.set(
|
|
1175
|
+
2 * vDotN * normal.x,
|
|
1176
|
+
2 * vDotN * normal.y,
|
|
1177
|
+
2 * vDotN * normal.z
|
|
1178
|
+
);
|
|
1179
|
+
velocity.x = (velocity.x - _normalComponent.x) * plane.dampen;
|
|
1180
|
+
velocity.y = (velocity.y - _normalComponent.y) * plane.dampen;
|
|
1181
|
+
velocity.z = (velocity.z - _normalComponent.z) * plane.dampen;
|
|
1182
|
+
if (plane.lifetimeLoss > 0) {
|
|
1183
|
+
const startLifetime = scalarArr[scalarBase + S_START_LIFETIME];
|
|
1184
|
+
scalarArr[scalarBase + S_LIFETIME] += plane.lifetimeLoss * startLifetime;
|
|
1185
|
+
}
|
|
1186
|
+
break;
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
return false;
|
|
1191
|
+
};
|
|
1192
|
+
var _forceDirection = new THREE5.Vector3();
|
|
1092
1193
|
var applyPointForce = (field, strength, velocity, positionArr, positionIndex, delta) => {
|
|
1093
1194
|
_forceDirection.set(
|
|
1094
1195
|
field.position.x - positionArr[positionIndex],
|
|
@@ -1169,15 +1270,29 @@ var normalizeTrailCurve = (curve, defaultCurve) => {
|
|
|
1169
1270
|
};
|
|
1170
1271
|
var _particleSystemId = 0;
|
|
1171
1272
|
var createdParticleSystems = [];
|
|
1172
|
-
var
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
var
|
|
1176
|
-
|
|
1273
|
+
var setUniformFloat = (u, v) => {
|
|
1274
|
+
u.value = v;
|
|
1275
|
+
};
|
|
1276
|
+
var setUniformVec3 = (u, x, y, z) => {
|
|
1277
|
+
u.value.set(x, y, z);
|
|
1278
|
+
};
|
|
1279
|
+
var _tslMaterialFactory = null;
|
|
1280
|
+
var registerTSLMaterialFactory = (factory) => {
|
|
1281
|
+
_tslMaterialFactory = factory;
|
|
1282
|
+
};
|
|
1283
|
+
var _subEmitterPosition = new THREE5.Vector3();
|
|
1284
|
+
var _shadowOrbitalEuler = new THREE5.Euler(0, 0, 0, "XYZ");
|
|
1285
|
+
var _lastWorldPositionSnapshot = new THREE5.Vector3();
|
|
1286
|
+
var _localForceFieldPos = new THREE5.Vector3();
|
|
1287
|
+
var _localForceFieldDir = new THREE5.Vector3();
|
|
1288
|
+
var _inverseQuat = new THREE5.Quaternion();
|
|
1177
1289
|
var _localForceFields = [];
|
|
1178
|
-
new
|
|
1179
|
-
new
|
|
1180
|
-
|
|
1290
|
+
var _localCollisionPlanePos = new THREE5.Vector3();
|
|
1291
|
+
var _localCollisionPlaneNormal = new THREE5.Vector3();
|
|
1292
|
+
var _localCollisionPlanes = [];
|
|
1293
|
+
new THREE5.Vector3();
|
|
1294
|
+
new THREE5.Vector3();
|
|
1295
|
+
new THREE5.Vector3();
|
|
1181
1296
|
var _distanceStep = { x: 0, y: 0, z: 0 };
|
|
1182
1297
|
var _tempPosition = { x: 0, y: 0, z: 0 };
|
|
1183
1298
|
var _modifierParams = {
|
|
@@ -1185,32 +1300,41 @@ var _modifierParams = {
|
|
|
1185
1300
|
generalData: null,
|
|
1186
1301
|
normalizedConfig: null,
|
|
1187
1302
|
attributes: null,
|
|
1303
|
+
scalarArray: null,
|
|
1188
1304
|
particleLifetimePercentage: 0,
|
|
1189
1305
|
particleIndex: 0
|
|
1190
1306
|
};
|
|
1191
|
-
var toVector3 = (v, fallback) => v ? new
|
|
1307
|
+
var toVector3 = (v, fallback) => v ? new THREE5.Vector3(v.x ?? 0, v.y ?? 0, v.z ?? 0) : fallback.clone();
|
|
1192
1308
|
var normalizeForceFields = (rawForceFields) => (rawForceFields ?? []).map((ff) => ({
|
|
1193
1309
|
isActive: ff.isActive ?? true,
|
|
1194
1310
|
type: ff.type ?? "POINT" /* POINT */,
|
|
1195
|
-
position: toVector3(ff.position, new
|
|
1196
|
-
direction: toVector3(ff.direction, new
|
|
1311
|
+
position: toVector3(ff.position, new THREE5.Vector3(0, 0, 0)),
|
|
1312
|
+
direction: toVector3(ff.direction, new THREE5.Vector3(0, 1, 0)).normalize(),
|
|
1197
1313
|
strength: ff.strength ?? 1,
|
|
1198
1314
|
range: Math.max(0, ff.range ?? Infinity),
|
|
1199
1315
|
falloff: ff.falloff ?? "LINEAR" /* LINEAR */
|
|
1200
1316
|
}));
|
|
1317
|
+
var normalizeCollisionPlanes = (rawPlanes) => (rawPlanes ?? []).map((cp) => ({
|
|
1318
|
+
isActive: cp.isActive ?? true,
|
|
1319
|
+
position: toVector3(cp.position, new THREE5.Vector3(0, 0, 0)),
|
|
1320
|
+
normal: toVector3(cp.normal, new THREE5.Vector3(0, 1, 0)).normalize(),
|
|
1321
|
+
mode: cp.mode ?? "KILL" /* KILL */,
|
|
1322
|
+
dampen: Math.max(0, Math.min(1, cp.dampen ?? 0.5)),
|
|
1323
|
+
lifetimeLoss: Math.max(0, Math.min(1, cp.lifetimeLoss ?? 0))
|
|
1324
|
+
}));
|
|
1201
1325
|
var blendingMap = {
|
|
1202
|
-
"THREE.NoBlending":
|
|
1203
|
-
"THREE.NormalBlending":
|
|
1204
|
-
"THREE.AdditiveBlending":
|
|
1205
|
-
"THREE.SubtractiveBlending":
|
|
1206
|
-
"THREE.MultiplyBlending":
|
|
1326
|
+
"THREE.NoBlending": THREE5.NoBlending,
|
|
1327
|
+
"THREE.NormalBlending": THREE5.NormalBlending,
|
|
1328
|
+
"THREE.AdditiveBlending": THREE5.AdditiveBlending,
|
|
1329
|
+
"THREE.SubtractiveBlending": THREE5.SubtractiveBlending,
|
|
1330
|
+
"THREE.MultiplyBlending": THREE5.MultiplyBlending
|
|
1207
1331
|
};
|
|
1208
1332
|
var getDefaultParticleSystemConfig = () => JSON.parse(JSON.stringify(DEFAULT_PARTICLE_SYSTEM_CONFIG));
|
|
1209
1333
|
var DEFAULT_PARTICLE_SYSTEM_CONFIG = {
|
|
1210
1334
|
transform: {
|
|
1211
|
-
position: new
|
|
1212
|
-
rotation: new
|
|
1213
|
-
scale: new
|
|
1335
|
+
position: new THREE5.Vector3(),
|
|
1336
|
+
rotation: new THREE5.Vector3(),
|
|
1337
|
+
scale: new THREE5.Vector3(1, 1, 1)
|
|
1214
1338
|
},
|
|
1215
1339
|
duration: 5,
|
|
1216
1340
|
looping: true,
|
|
@@ -1226,6 +1350,7 @@ var DEFAULT_PARTICLE_SYSTEM_CONFIG = {
|
|
|
1226
1350
|
},
|
|
1227
1351
|
gravity: 0,
|
|
1228
1352
|
simulationSpace: "LOCAL" /* LOCAL */,
|
|
1353
|
+
simulationBackend: "AUTO" /* AUTO */,
|
|
1229
1354
|
maxParticles: 100,
|
|
1230
1355
|
emission: {
|
|
1231
1356
|
rateOverTime: 10,
|
|
@@ -1262,7 +1387,7 @@ var DEFAULT_PARTICLE_SYSTEM_CONFIG = {
|
|
|
1262
1387
|
},
|
|
1263
1388
|
map: void 0,
|
|
1264
1389
|
renderer: {
|
|
1265
|
-
blending:
|
|
1390
|
+
blending: THREE5.NormalBlending,
|
|
1266
1391
|
discardBackgroundColor: false,
|
|
1267
1392
|
backgroundColorTolerance: 1,
|
|
1268
1393
|
backgroundColor: { r: 1, g: 1, b: 1 },
|
|
@@ -1352,30 +1477,13 @@ var DEFAULT_PARTICLE_SYSTEM_CONFIG = {
|
|
|
1352
1477
|
sizeAmount: 0
|
|
1353
1478
|
},
|
|
1354
1479
|
textureSheetAnimation: {
|
|
1355
|
-
tiles: new
|
|
1480
|
+
tiles: new THREE5.Vector2(1, 1),
|
|
1356
1481
|
timeMode: "LIFETIME" /* LIFETIME */,
|
|
1357
1482
|
fps: 30,
|
|
1358
1483
|
startFrame: 0
|
|
1359
1484
|
},
|
|
1360
|
-
forceFields: []
|
|
1361
|
-
|
|
1362
|
-
var createFloat32Attributes = ({
|
|
1363
|
-
geometry,
|
|
1364
|
-
propertyName,
|
|
1365
|
-
maxParticles,
|
|
1366
|
-
factory,
|
|
1367
|
-
instanced
|
|
1368
|
-
}) => {
|
|
1369
|
-
const array = new Float32Array(maxParticles);
|
|
1370
|
-
if (typeof factory === "function") {
|
|
1371
|
-
for (let i = 0; i < maxParticles; i++) {
|
|
1372
|
-
array[i] = factory(void 0, i);
|
|
1373
|
-
}
|
|
1374
|
-
} else {
|
|
1375
|
-
array.fill(factory);
|
|
1376
|
-
}
|
|
1377
|
-
const attr = instanced ? new THREE4.InstancedBufferAttribute(array, 1) : new THREE4.BufferAttribute(array, 1);
|
|
1378
|
-
geometry.setAttribute(propertyName, attr);
|
|
1485
|
+
forceFields: [],
|
|
1486
|
+
collisionPlanes: []
|
|
1379
1487
|
};
|
|
1380
1488
|
var calculatePositionAndVelocity = (generalData, { shape, sphere, cone, circle, rectangle, box }, startSpeed, position, velocity) => {
|
|
1381
1489
|
const calculatedStartSpeed = calculateValue(
|
|
@@ -1467,14 +1575,14 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1467
1575
|
particleSystemId: _particleSystemId++,
|
|
1468
1576
|
normalizedLifetimePercentage: 0,
|
|
1469
1577
|
distanceFromLastEmitByDistance: 0,
|
|
1470
|
-
lastWorldPosition: new
|
|
1471
|
-
currentWorldPosition: new
|
|
1472
|
-
worldPositionChange: new
|
|
1473
|
-
worldQuaternion: new
|
|
1474
|
-
wrapperQuaternion: new
|
|
1475
|
-
lastWorldQuaternion: new
|
|
1476
|
-
worldEuler: new
|
|
1477
|
-
gravityVelocity: new
|
|
1578
|
+
lastWorldPosition: new THREE5.Vector3(-99999),
|
|
1579
|
+
currentWorldPosition: new THREE5.Vector3(-99999),
|
|
1580
|
+
worldPositionChange: new THREE5.Vector3(),
|
|
1581
|
+
worldQuaternion: new THREE5.Quaternion(),
|
|
1582
|
+
wrapperQuaternion: new THREE5.Quaternion(),
|
|
1583
|
+
lastWorldQuaternion: new THREE5.Quaternion(-99999),
|
|
1584
|
+
worldEuler: new THREE5.Euler(),
|
|
1585
|
+
gravityVelocity: new THREE5.Vector3(0, 0, 0),
|
|
1478
1586
|
startValues: {},
|
|
1479
1587
|
linearVelocityData: void 0,
|
|
1480
1588
|
orbitalVelocityData: void 0,
|
|
@@ -1484,9 +1592,11 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1484
1592
|
isActive: false,
|
|
1485
1593
|
strength: 0,
|
|
1486
1594
|
noisePower: 0,
|
|
1595
|
+
frequency: 0.5,
|
|
1487
1596
|
positionAmount: 0,
|
|
1488
1597
|
rotationAmount: 0,
|
|
1489
|
-
sizeAmount: 0
|
|
1598
|
+
sizeAmount: 0,
|
|
1599
|
+
fbmMax: 1
|
|
1490
1600
|
},
|
|
1491
1601
|
isEnabled: true
|
|
1492
1602
|
};
|
|
@@ -1496,6 +1606,10 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1496
1606
|
{ applyToFirstObject: false, skippedProperties: [] }
|
|
1497
1607
|
);
|
|
1498
1608
|
let particleMap = normalizedConfig.map || (normalizedConfig.renderer.rendererType === "MESH" /* MESH */ ? createDefaultMeshTexture() : createDefaultParticleTexture());
|
|
1609
|
+
if (particleMap) {
|
|
1610
|
+
particleMap.wrapS = THREE5.ClampToEdgeWrapping;
|
|
1611
|
+
particleMap.wrapT = THREE5.ClampToEdgeWrapping;
|
|
1612
|
+
}
|
|
1499
1613
|
const {
|
|
1500
1614
|
transform,
|
|
1501
1615
|
duration,
|
|
@@ -1522,15 +1636,16 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1522
1636
|
forceFields: rawForceFields
|
|
1523
1637
|
} = normalizedConfig;
|
|
1524
1638
|
const normalizedForceFields = normalizeForceFields(rawForceFields);
|
|
1639
|
+
const normalizedCollisionPlanes = normalizeCollisionPlanes(normalizedConfig.collisionPlanes);
|
|
1525
1640
|
if (typeof renderer?.blending === "string")
|
|
1526
1641
|
renderer.blending = blendingMap[renderer.blending];
|
|
1527
1642
|
const startPositions = Array.from(
|
|
1528
1643
|
{ length: maxParticles },
|
|
1529
|
-
() => new
|
|
1644
|
+
() => new THREE5.Vector3()
|
|
1530
1645
|
);
|
|
1531
1646
|
const velocities = Array.from(
|
|
1532
1647
|
{ length: maxParticles },
|
|
1533
|
-
() => new
|
|
1648
|
+
() => new THREE5.Vector3()
|
|
1534
1649
|
);
|
|
1535
1650
|
generalData.creationTimes = Array.from({ length: maxParticles }, () => 0);
|
|
1536
1651
|
const freeList = Array.from(
|
|
@@ -1541,7 +1656,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1541
1656
|
generalData.linearVelocityData = Array.from(
|
|
1542
1657
|
{ length: maxParticles },
|
|
1543
1658
|
() => ({
|
|
1544
|
-
speed: new
|
|
1659
|
+
speed: new THREE5.Vector3(
|
|
1545
1660
|
velocityOverLifetime.linear.x ? calculateValue(
|
|
1546
1661
|
generalData.particleSystemId,
|
|
1547
1662
|
velocityOverLifetime.linear.x,
|
|
@@ -1577,7 +1692,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1577
1692
|
generalData.orbitalVelocityData = Array.from(
|
|
1578
1693
|
{ length: maxParticles },
|
|
1579
1694
|
() => ({
|
|
1580
|
-
speed: new
|
|
1695
|
+
speed: new THREE5.Vector3(
|
|
1581
1696
|
velocityOverLifetime.orbital.x ? calculateValue(
|
|
1582
1697
|
generalData.particleSystemId,
|
|
1583
1698
|
velocityOverLifetime.orbital.x,
|
|
@@ -1608,7 +1723,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1608
1723
|
velocityOverLifetime.orbital.z
|
|
1609
1724
|
) : void 0
|
|
1610
1725
|
},
|
|
1611
|
-
positionOffset: new
|
|
1726
|
+
positionOffset: new THREE5.Vector3()
|
|
1612
1727
|
})
|
|
1613
1728
|
);
|
|
1614
1729
|
}
|
|
@@ -1646,16 +1761,19 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1646
1761
|
if (value.isActive)
|
|
1647
1762
|
generalData.lifetimeValues[key] = Array.from(
|
|
1648
1763
|
{ length: maxParticles },
|
|
1649
|
-
() =>
|
|
1764
|
+
() => THREE5.MathUtils.randFloat(value.min, value.max)
|
|
1650
1765
|
);
|
|
1651
1766
|
});
|
|
1767
|
+
const fbmMax = 2 - Math.pow(2, -noise.octaves);
|
|
1652
1768
|
generalData.noise = {
|
|
1653
1769
|
isActive: noise.isActive,
|
|
1654
1770
|
strength: noise.strength,
|
|
1655
1771
|
noisePower: 0.15 * noise.strength,
|
|
1772
|
+
frequency: noise.frequency,
|
|
1656
1773
|
positionAmount: noise.positionAmount,
|
|
1657
1774
|
rotationAmount: noise.rotationAmount,
|
|
1658
1775
|
sizeAmount: noise.sizeAmount,
|
|
1776
|
+
fbmMax,
|
|
1659
1777
|
sampler: noise.isActive ? new FBM({
|
|
1660
1778
|
seed: Math.random(),
|
|
1661
1779
|
scale: noise.frequency,
|
|
@@ -1727,7 +1845,12 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1727
1845
|
const sharedUniforms = {
|
|
1728
1846
|
elapsed: { value: 0 },
|
|
1729
1847
|
map: { value: particleMap },
|
|
1730
|
-
tiles: {
|
|
1848
|
+
tiles: {
|
|
1849
|
+
value: new THREE5.Vector2(
|
|
1850
|
+
textureSheetAnimation.tiles?.x ?? 1,
|
|
1851
|
+
textureSheetAnimation.tiles?.y ?? 1
|
|
1852
|
+
)
|
|
1853
|
+
},
|
|
1731
1854
|
fps: { value: textureSheetAnimation.fps },
|
|
1732
1855
|
useFPSForFrameIndex: {
|
|
1733
1856
|
value: textureSheetAnimation.timeMode === "FPS" /* FPS */
|
|
@@ -1743,7 +1866,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1743
1866
|
sceneDepthTexture: {
|
|
1744
1867
|
value: renderer.softParticles?.depthTexture ?? null
|
|
1745
1868
|
},
|
|
1746
|
-
cameraNearFar: { value: new
|
|
1869
|
+
cameraNearFar: { value: new THREE5.Vector2(0.1, 1e3) }
|
|
1747
1870
|
};
|
|
1748
1871
|
const getVertexShader = () => {
|
|
1749
1872
|
if (useMesh) return mesh_particle_vertex_shader_glsl_default;
|
|
@@ -1755,14 +1878,41 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1755
1878
|
if (useInstancing) return instanced_particle_fragment_shader_glsl_default;
|
|
1756
1879
|
return particle_system_fragment_shader_glsl_default;
|
|
1757
1880
|
};
|
|
1758
|
-
const
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1881
|
+
const useTSL = _tslMaterialFactory !== null;
|
|
1882
|
+
const useGPUCompute = useTSL && !useTrail && normalizedConfig.simulationBackend !== "CPU" /* CPU */ && !!_tslMaterialFactory?.createComputePipeline && !!_tslMaterialFactory.writeParticleToModifierBuffers && !!_tslMaterialFactory.deactivateParticleInModifierBuffers && !!_tslMaterialFactory.flushEmitQueue;
|
|
1883
|
+
let gpuPipeline = null;
|
|
1884
|
+
if (useGPUCompute) {
|
|
1885
|
+
gpuPipeline = _tslMaterialFactory.createComputePipeline(
|
|
1886
|
+
maxParticles,
|
|
1887
|
+
useInstancedAttributes,
|
|
1888
|
+
normalizedConfig,
|
|
1889
|
+
generalData.particleSystemId,
|
|
1890
|
+
normalizedForceFields.length,
|
|
1891
|
+
normalizedCollisionPlanes.length
|
|
1892
|
+
);
|
|
1893
|
+
if (gpuPipeline && _tslMaterialFactory.registerCurveDataLength) {
|
|
1894
|
+
_tslMaterialFactory.registerCurveDataLength(
|
|
1895
|
+
gpuPipeline.buffers,
|
|
1896
|
+
gpuPipeline.curveDataLength
|
|
1897
|
+
);
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
const rendererConfig = {
|
|
1762
1901
|
transparent: renderer.transparent,
|
|
1763
1902
|
blending: renderer.blending,
|
|
1764
1903
|
depthTest: renderer.depthTest,
|
|
1765
1904
|
depthWrite: renderer.depthWrite
|
|
1905
|
+
};
|
|
1906
|
+
const material = useTSL ? _tslMaterialFactory.createTSLParticleMaterial(
|
|
1907
|
+
renderer.rendererType ?? "POINTS" /* POINTS */,
|
|
1908
|
+
sharedUniforms,
|
|
1909
|
+
rendererConfig,
|
|
1910
|
+
useGPUCompute
|
|
1911
|
+
) : new THREE5.ShaderMaterial({
|
|
1912
|
+
uniforms: sharedUniforms,
|
|
1913
|
+
vertexShader: getVertexShader(),
|
|
1914
|
+
fragmentShader: getFragmentShader(),
|
|
1915
|
+
...rendererConfig
|
|
1766
1916
|
});
|
|
1767
1917
|
let geometry;
|
|
1768
1918
|
if (useMesh) {
|
|
@@ -1772,7 +1922,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1772
1922
|
"RendererType.MESH requires a mesh configuration with a geometry. Set renderer.mesh.geometry to a THREE.BufferGeometry instance."
|
|
1773
1923
|
);
|
|
1774
1924
|
}
|
|
1775
|
-
const instancedGeometry = new
|
|
1925
|
+
const instancedGeometry = new THREE5.InstancedBufferGeometry();
|
|
1776
1926
|
const sourceGeom = meshConfig.geometry;
|
|
1777
1927
|
const srcPos = sourceGeom.getAttribute("position");
|
|
1778
1928
|
if (srcPos) instancedGeometry.setAttribute("position", srcPos);
|
|
@@ -1785,7 +1935,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1785
1935
|
instancedGeometry.instanceCount = maxParticles;
|
|
1786
1936
|
geometry = instancedGeometry;
|
|
1787
1937
|
} else if (useInstancing) {
|
|
1788
|
-
const instancedGeometry = new
|
|
1938
|
+
const instancedGeometry = new THREE5.InstancedBufferGeometry();
|
|
1789
1939
|
const quadPositions = new Float32Array([
|
|
1790
1940
|
-0.5,
|
|
1791
1941
|
-0.5,
|
|
@@ -1803,13 +1953,13 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1803
1953
|
const quadIndices = new Uint16Array([0, 1, 2, 0, 2, 3]);
|
|
1804
1954
|
instancedGeometry.setAttribute(
|
|
1805
1955
|
"position",
|
|
1806
|
-
new
|
|
1956
|
+
new THREE5.BufferAttribute(quadPositions, 3)
|
|
1807
1957
|
);
|
|
1808
|
-
instancedGeometry.setIndex(new
|
|
1958
|
+
instancedGeometry.setIndex(new THREE5.BufferAttribute(quadIndices, 1));
|
|
1809
1959
|
instancedGeometry.instanceCount = maxParticles;
|
|
1810
1960
|
geometry = instancedGeometry;
|
|
1811
1961
|
} else {
|
|
1812
|
-
geometry = new
|
|
1962
|
+
geometry = new THREE5.BufferGeometry();
|
|
1813
1963
|
}
|
|
1814
1964
|
for (let i = 0; i < maxParticles; i++)
|
|
1815
1965
|
calculatePositionAndVelocity(
|
|
@@ -1819,116 +1969,126 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1819
1969
|
startPositions[i],
|
|
1820
1970
|
velocities[i]
|
|
1821
1971
|
);
|
|
1822
|
-
const
|
|
1972
|
+
const scalarArray = new Float32Array(maxParticles * SCALAR_STRIDE);
|
|
1823
1973
|
for (let i = 0; i < maxParticles; i++) {
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
geometry.setAttribute(posAttr, positionAttribute);
|
|
1830
|
-
createFloat32Attributes({
|
|
1831
|
-
geometry,
|
|
1832
|
-
propertyName: attr("isActive"),
|
|
1833
|
-
maxParticles,
|
|
1834
|
-
factory: 0,
|
|
1835
|
-
instanced: useInstancedAttributes
|
|
1836
|
-
});
|
|
1837
|
-
createFloat32Attributes({
|
|
1838
|
-
geometry,
|
|
1839
|
-
propertyName: attr("lifetime"),
|
|
1840
|
-
maxParticles,
|
|
1841
|
-
factory: 0,
|
|
1842
|
-
instanced: useInstancedAttributes
|
|
1843
|
-
});
|
|
1844
|
-
createFloat32Attributes({
|
|
1845
|
-
geometry,
|
|
1846
|
-
propertyName: attr("startLifetime"),
|
|
1847
|
-
maxParticles,
|
|
1848
|
-
factory: () => calculateValue(generalData.particleSystemId, startLifetime, 0) * 1e3,
|
|
1849
|
-
instanced: useInstancedAttributes
|
|
1850
|
-
});
|
|
1851
|
-
createFloat32Attributes({
|
|
1852
|
-
geometry,
|
|
1853
|
-
propertyName: attr("startFrame"),
|
|
1854
|
-
maxParticles,
|
|
1855
|
-
factory: () => textureSheetAnimation.startFrame ? calculateValue(
|
|
1974
|
+
const base = i * SCALAR_STRIDE;
|
|
1975
|
+
scalarArray[base + S_IS_ACTIVE] = 0;
|
|
1976
|
+
scalarArray[base + S_LIFETIME] = 0;
|
|
1977
|
+
scalarArray[base + S_START_LIFETIME] = calculateValue(generalData.particleSystemId, startLifetime, 0) * 1e3;
|
|
1978
|
+
scalarArray[base + S_START_FRAME] = textureSheetAnimation.startFrame ? calculateValue(
|
|
1856
1979
|
generalData.particleSystemId,
|
|
1857
1980
|
textureSheetAnimation.startFrame,
|
|
1858
1981
|
0
|
|
1859
|
-
) : 0
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
}
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
geometry
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1982
|
+
) : 0;
|
|
1983
|
+
scalarArray[base + S_SIZE] = generalData.startValues.startSize[i];
|
|
1984
|
+
scalarArray[base + S_ROTATION] = 0;
|
|
1985
|
+
const colorRandomRatio = Math.random();
|
|
1986
|
+
scalarArray[base + S_COLOR_R] = startColor.min.r + colorRandomRatio * (startColor.max.r - startColor.min.r);
|
|
1987
|
+
scalarArray[base + S_COLOR_G] = startColor.min.g + colorRandomRatio * (startColor.max.g - startColor.min.g);
|
|
1988
|
+
scalarArray[base + S_COLOR_B] = startColor.min.b + colorRandomRatio * (startColor.max.b - startColor.min.b);
|
|
1989
|
+
scalarArray[base + S_COLOR_A] = 0;
|
|
1990
|
+
}
|
|
1991
|
+
const scalarInterleavedBuffer = useInstancedAttributes ? new THREE5.InstancedInterleavedBuffer(scalarArray, SCALAR_STRIDE) : new THREE5.InterleavedBuffer(scalarArray, SCALAR_STRIDE);
|
|
1992
|
+
if (useGPUCompute && gpuPipeline) {
|
|
1993
|
+
const gpuBuf = gpuPipeline.buffers;
|
|
1994
|
+
geometry.setAttribute(posAttr, gpuBuf.position);
|
|
1995
|
+
geometry.setAttribute(attr("color"), gpuBuf.color);
|
|
1996
|
+
geometry.setAttribute(attr("particleState"), gpuBuf.particleState);
|
|
1997
|
+
geometry.setAttribute(attr("startValues"), gpuBuf.startValues);
|
|
1998
|
+
} else {
|
|
1999
|
+
const positionArray = new Float32Array(maxParticles * 3);
|
|
2000
|
+
for (let i = 0; i < maxParticles; i++) {
|
|
2001
|
+
positionArray[i * 3] = startPositions[i].x;
|
|
2002
|
+
positionArray[i * 3 + 1] = startPositions[i].y;
|
|
2003
|
+
positionArray[i * 3 + 2] = startPositions[i].z;
|
|
2004
|
+
}
|
|
2005
|
+
const positionAttribute = useInstancedAttributes ? new THREE5.InstancedBufferAttribute(positionArray, 3) : new THREE5.BufferAttribute(positionArray, 3);
|
|
2006
|
+
geometry.setAttribute(posAttr, positionAttribute);
|
|
2007
|
+
geometry.setAttribute(
|
|
2008
|
+
attr("isActive"),
|
|
2009
|
+
new THREE5.InterleavedBufferAttribute(
|
|
2010
|
+
scalarInterleavedBuffer,
|
|
2011
|
+
1,
|
|
2012
|
+
S_IS_ACTIVE
|
|
2013
|
+
)
|
|
2014
|
+
);
|
|
2015
|
+
geometry.setAttribute(
|
|
2016
|
+
attr("lifetime"),
|
|
2017
|
+
new THREE5.InterleavedBufferAttribute(
|
|
2018
|
+
scalarInterleavedBuffer,
|
|
2019
|
+
1,
|
|
2020
|
+
S_LIFETIME
|
|
2021
|
+
)
|
|
2022
|
+
);
|
|
2023
|
+
geometry.setAttribute(
|
|
2024
|
+
attr("startLifetime"),
|
|
2025
|
+
new THREE5.InterleavedBufferAttribute(
|
|
2026
|
+
scalarInterleavedBuffer,
|
|
2027
|
+
1,
|
|
2028
|
+
S_START_LIFETIME
|
|
2029
|
+
)
|
|
2030
|
+
);
|
|
2031
|
+
geometry.setAttribute(
|
|
2032
|
+
attr("startFrame"),
|
|
2033
|
+
new THREE5.InterleavedBufferAttribute(
|
|
2034
|
+
scalarInterleavedBuffer,
|
|
2035
|
+
1,
|
|
2036
|
+
S_START_FRAME
|
|
2037
|
+
)
|
|
2038
|
+
);
|
|
2039
|
+
geometry.setAttribute(
|
|
2040
|
+
attr("size"),
|
|
2041
|
+
new THREE5.InterleavedBufferAttribute(scalarInterleavedBuffer, 1, S_SIZE)
|
|
2042
|
+
);
|
|
2043
|
+
geometry.setAttribute(
|
|
2044
|
+
attr("rotation"),
|
|
2045
|
+
new THREE5.InterleavedBufferAttribute(
|
|
2046
|
+
scalarInterleavedBuffer,
|
|
2047
|
+
1,
|
|
2048
|
+
S_ROTATION
|
|
2049
|
+
)
|
|
2050
|
+
);
|
|
2051
|
+
geometry.setAttribute(
|
|
2052
|
+
attr("color"),
|
|
2053
|
+
new THREE5.InterleavedBufferAttribute(
|
|
2054
|
+
scalarInterleavedBuffer,
|
|
2055
|
+
4,
|
|
2056
|
+
S_COLOR_R
|
|
2057
|
+
)
|
|
2058
|
+
);
|
|
2059
|
+
}
|
|
2060
|
+
if (useMesh && !useGPUCompute) {
|
|
1906
2061
|
const quatArray = new Float32Array(maxParticles * 4);
|
|
1907
2062
|
for (let i = 0; i < maxParticles; i++) {
|
|
1908
2063
|
quatArray[i * 4 + 3] = 1;
|
|
1909
2064
|
}
|
|
1910
2065
|
geometry.setAttribute(
|
|
1911
2066
|
attr("quat"),
|
|
1912
|
-
new
|
|
2067
|
+
new THREE5.InstancedBufferAttribute(quatArray, 4)
|
|
1913
2068
|
);
|
|
1914
2069
|
}
|
|
1915
2070
|
const a = geometry.attributes;
|
|
1916
2071
|
const aIsActive = a[attr("isActive")];
|
|
1917
|
-
const
|
|
1918
|
-
const aColorG = a[attr("colorG")];
|
|
1919
|
-
const aColorB = a[attr("colorB")];
|
|
1920
|
-
const aColorA = a[attr("colorA")];
|
|
2072
|
+
const aColor = a[attr("color")];
|
|
1921
2073
|
const aStartFrame = a[attr("startFrame")];
|
|
1922
2074
|
const aStartLifetime = a[attr("startLifetime")];
|
|
1923
2075
|
const aSize = a[attr("size")];
|
|
1924
2076
|
const aRotation = a[attr("rotation")];
|
|
1925
2077
|
const aLifetime = a[attr("lifetime")];
|
|
1926
2078
|
const aPosition = a[posAttr];
|
|
1927
|
-
const aQuat = useMesh ? a[attr("quat")] : void 0;
|
|
2079
|
+
const aQuat = useMesh && !useGPUCompute ? a[attr("quat")] : void 0;
|
|
1928
2080
|
const deactivateParticle = (particleIndex) => {
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
2081
|
+
const base = particleIndex * SCALAR_STRIDE;
|
|
2082
|
+
scalarArray[base + S_IS_ACTIVE] = 0;
|
|
2083
|
+
scalarArray[base + S_COLOR_A] = 0;
|
|
2084
|
+
if (useGPUCompute && gpuPipeline) {
|
|
2085
|
+
_tslMaterialFactory.deactivateParticleInModifierBuffers(
|
|
2086
|
+
gpuPipeline.buffers,
|
|
2087
|
+
particleIndex
|
|
2088
|
+
);
|
|
2089
|
+
} else {
|
|
2090
|
+
scalarInterleavedBuffer.needsUpdate = true;
|
|
2091
|
+
}
|
|
1932
2092
|
freeList.push(particleIndex);
|
|
1933
2093
|
};
|
|
1934
2094
|
const activateParticle = ({
|
|
@@ -1936,7 +2096,8 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1936
2096
|
activationTime,
|
|
1937
2097
|
position
|
|
1938
2098
|
}) => {
|
|
1939
|
-
|
|
2099
|
+
const base = particleIndex * SCALAR_STRIDE;
|
|
2100
|
+
scalarArray[base + S_IS_ACTIVE] = 1;
|
|
1940
2101
|
generalData.creationTimes[particleIndex] = activationTime;
|
|
1941
2102
|
if (generalData.positionHistoryCount) {
|
|
1942
2103
|
generalData.positionHistoryCount[particleIndex] = 0;
|
|
@@ -1956,51 +2117,43 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1956
2117
|
}
|
|
1957
2118
|
if (generalData.noise.offsets)
|
|
1958
2119
|
generalData.noise.offsets[particleIndex] = Math.random() * 100;
|
|
1959
|
-
const
|
|
2120
|
+
const colorRandomRatio = Math.random();
|
|
1960
2121
|
const cfgStartColor = normalizedConfig.startColor;
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
generalData.startValues.startColorG[particleIndex] = aColorG.array[particleIndex];
|
|
1969
|
-
generalData.startValues.startColorB[particleIndex] = aColorB.array[particleIndex];
|
|
1970
|
-
aStartFrame.array[particleIndex] = normalizedConfig.textureSheetAnimation.startFrame ? calculateValue(
|
|
2122
|
+
scalarArray[base + S_COLOR_R] = cfgStartColor.min.r + colorRandomRatio * (cfgStartColor.max.r - cfgStartColor.min.r);
|
|
2123
|
+
scalarArray[base + S_COLOR_G] = cfgStartColor.min.g + colorRandomRatio * (cfgStartColor.max.g - cfgStartColor.min.g);
|
|
2124
|
+
scalarArray[base + S_COLOR_B] = cfgStartColor.min.b + colorRandomRatio * (cfgStartColor.max.b - cfgStartColor.min.b);
|
|
2125
|
+
generalData.startValues.startColorR[particleIndex] = scalarArray[base + S_COLOR_R];
|
|
2126
|
+
generalData.startValues.startColorG[particleIndex] = scalarArray[base + S_COLOR_G];
|
|
2127
|
+
generalData.startValues.startColorB[particleIndex] = scalarArray[base + S_COLOR_B];
|
|
2128
|
+
scalarArray[base + S_START_FRAME] = normalizedConfig.textureSheetAnimation.startFrame ? calculateValue(
|
|
1971
2129
|
generalData.particleSystemId,
|
|
1972
2130
|
normalizedConfig.textureSheetAnimation.startFrame,
|
|
1973
2131
|
0
|
|
1974
2132
|
) : 0;
|
|
1975
|
-
|
|
1976
|
-
aStartLifetime.array[particleIndex] = calculateValue(
|
|
2133
|
+
scalarArray[base + S_START_LIFETIME] = calculateValue(
|
|
1977
2134
|
generalData.particleSystemId,
|
|
1978
2135
|
normalizedConfig.startLifetime,
|
|
1979
2136
|
generalData.normalizedLifetimePercentage
|
|
1980
2137
|
) * 1e3;
|
|
1981
|
-
aStartLifetime.needsUpdate = true;
|
|
1982
2138
|
generalData.startValues.startSize[particleIndex] = calculateValue(
|
|
1983
2139
|
generalData.particleSystemId,
|
|
1984
2140
|
normalizedConfig.startSize,
|
|
1985
2141
|
generalData.normalizedLifetimePercentage
|
|
1986
2142
|
);
|
|
1987
|
-
|
|
1988
|
-
aSize.needsUpdate = true;
|
|
2143
|
+
scalarArray[base + S_SIZE] = generalData.startValues.startSize[particleIndex];
|
|
1989
2144
|
generalData.startValues.startOpacity[particleIndex] = calculateValue(
|
|
1990
2145
|
generalData.particleSystemId,
|
|
1991
2146
|
normalizedConfig.startOpacity,
|
|
1992
2147
|
generalData.normalizedLifetimePercentage
|
|
1993
2148
|
);
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
aRotation.array[particleIndex] = calculateValue(
|
|
2149
|
+
scalarArray[base + S_COLOR_A] = generalData.startValues.startOpacity[particleIndex];
|
|
2150
|
+
scalarArray[base + S_ROTATION] = calculateValue(
|
|
1997
2151
|
generalData.particleSystemId,
|
|
1998
2152
|
normalizedConfig.startRotation,
|
|
1999
2153
|
generalData.normalizedLifetimePercentage
|
|
2000
2154
|
);
|
|
2001
|
-
aRotation.needsUpdate = true;
|
|
2002
2155
|
if (aQuat) {
|
|
2003
|
-
const rotZ =
|
|
2156
|
+
const rotZ = scalarArray[base + S_ROTATION];
|
|
2004
2157
|
const halfZ = rotZ * 0.5;
|
|
2005
2158
|
const qi = particleIndex * 4;
|
|
2006
2159
|
aQuat.array[qi] = 0;
|
|
@@ -2010,7 +2163,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
2010
2163
|
aQuat.needsUpdate = true;
|
|
2011
2164
|
}
|
|
2012
2165
|
if (normalizedConfig.rotationOverLifetime.isActive)
|
|
2013
|
-
generalData.lifetimeValues.rotationOverLifetime[particleIndex] =
|
|
2166
|
+
generalData.lifetimeValues.rotationOverLifetime[particleIndex] = THREE5.MathUtils.randFloat(
|
|
2014
2167
|
normalizedConfig.rotationOverLifetime.min,
|
|
2015
2168
|
normalizedConfig.rotationOverLifetime.max
|
|
2016
2169
|
);
|
|
@@ -2021,11 +2174,15 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
2021
2174
|
startPositions[particleIndex],
|
|
2022
2175
|
velocities[particleIndex]
|
|
2023
2176
|
);
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2177
|
+
{
|
|
2178
|
+
const positionIndex = particleIndex * 3;
|
|
2179
|
+
aPosition.array[positionIndex] = position.x + startPositions[particleIndex].x;
|
|
2180
|
+
aPosition.array[positionIndex + 1] = position.y + startPositions[particleIndex].y;
|
|
2181
|
+
aPosition.array[positionIndex + 2] = position.z + startPositions[particleIndex].z;
|
|
2182
|
+
if (!useGPUCompute) {
|
|
2183
|
+
aPosition.needsUpdate = true;
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2029
2186
|
if (generalData.linearVelocityData) {
|
|
2030
2187
|
generalData.linearVelocityData[particleIndex].speed.set(
|
|
2031
2188
|
normalizedConfig.velocityOverLifetime.linear.x ? calculateValue(
|
|
@@ -2069,16 +2226,56 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
2069
2226
|
startPositions[particleIndex].z
|
|
2070
2227
|
);
|
|
2071
2228
|
}
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2229
|
+
scalarArray[base + S_LIFETIME] = 0;
|
|
2230
|
+
if (useGPUCompute && gpuPipeline) {
|
|
2231
|
+
_tslMaterialFactory.writeParticleToModifierBuffers(
|
|
2232
|
+
gpuPipeline.buffers,
|
|
2233
|
+
particleIndex,
|
|
2234
|
+
{
|
|
2235
|
+
position: {
|
|
2236
|
+
x: position.x + startPositions[particleIndex].x,
|
|
2237
|
+
y: position.y + startPositions[particleIndex].y,
|
|
2238
|
+
z: position.z + startPositions[particleIndex].z
|
|
2239
|
+
},
|
|
2240
|
+
velocity: {
|
|
2241
|
+
x: velocities[particleIndex].x,
|
|
2242
|
+
y: velocities[particleIndex].y,
|
|
2243
|
+
z: velocities[particleIndex].z
|
|
2244
|
+
},
|
|
2245
|
+
startLifetime: scalarArray[base + S_START_LIFETIME],
|
|
2246
|
+
colorA: scalarArray[base + S_COLOR_A],
|
|
2247
|
+
size: scalarArray[base + S_SIZE],
|
|
2248
|
+
rotation: scalarArray[base + S_ROTATION],
|
|
2249
|
+
colorR: scalarArray[base + S_COLOR_R],
|
|
2250
|
+
colorG: scalarArray[base + S_COLOR_G],
|
|
2251
|
+
colorB: scalarArray[base + S_COLOR_B],
|
|
2252
|
+
startSize: generalData.startValues.startSize[particleIndex],
|
|
2253
|
+
startOpacity: generalData.startValues.startOpacity[particleIndex],
|
|
2254
|
+
startColorR: generalData.startValues.startColorR[particleIndex],
|
|
2255
|
+
startColorG: generalData.startValues.startColorG[particleIndex],
|
|
2256
|
+
startColorB: generalData.startValues.startColorB[particleIndex],
|
|
2257
|
+
rotationSpeed: generalData.lifetimeValues.rotationOverLifetime ? generalData.lifetimeValues.rotationOverLifetime[particleIndex] : 0,
|
|
2258
|
+
noiseOffset: generalData.noise.offsets ? generalData.noise.offsets[particleIndex] : 0,
|
|
2259
|
+
startFrame: scalarArray[base + S_START_FRAME],
|
|
2260
|
+
orbitalOffset: {
|
|
2261
|
+
x: startPositions[particleIndex].x,
|
|
2262
|
+
y: startPositions[particleIndex].y,
|
|
2263
|
+
z: startPositions[particleIndex].z
|
|
2264
|
+
}
|
|
2265
|
+
}
|
|
2266
|
+
);
|
|
2267
|
+
} else {
|
|
2268
|
+
scalarInterleavedBuffer.needsUpdate = true;
|
|
2269
|
+
applyModifiers({
|
|
2270
|
+
delta: 0,
|
|
2271
|
+
generalData,
|
|
2272
|
+
normalizedConfig,
|
|
2273
|
+
attributes: mappedAttributes,
|
|
2274
|
+
scalarArray,
|
|
2275
|
+
particleLifetimePercentage: 0,
|
|
2276
|
+
particleIndex
|
|
2277
|
+
});
|
|
2278
|
+
}
|
|
2082
2279
|
};
|
|
2083
2280
|
const subEmitterArr = subEmitters ?? [];
|
|
2084
2281
|
const deathSubEmitters = subEmitterArr.filter(
|
|
@@ -2094,17 +2291,17 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
2094
2291
|
const cleanupCompletedInstances = (instances) => {
|
|
2095
2292
|
for (let i = instances.length - 1; i >= 0; i--) {
|
|
2096
2293
|
const sub = instances[i];
|
|
2097
|
-
const obj3d = sub.instance instanceof
|
|
2294
|
+
const obj3d = sub.instance instanceof THREE5.Points || sub.instance instanceof THREE5.Mesh ? sub.instance : sub.instance.children[0];
|
|
2098
2295
|
const geomAttrs = obj3d?.geometry?.attributes;
|
|
2099
|
-
const
|
|
2100
|
-
if (!
|
|
2296
|
+
const isActiveAttr = geomAttrs ? geomAttrs.isActive ?? geomAttrs.instanceIsActive : void 0;
|
|
2297
|
+
if (!isActiveAttr) {
|
|
2101
2298
|
sub.dispose();
|
|
2102
2299
|
instances.splice(i, 1);
|
|
2103
2300
|
continue;
|
|
2104
2301
|
}
|
|
2105
2302
|
let hasActive = false;
|
|
2106
|
-
for (let j = 0; j <
|
|
2107
|
-
if (
|
|
2303
|
+
for (let j = 0; j < isActiveAttr.count; j++) {
|
|
2304
|
+
if (isActiveAttr.getX(j)) {
|
|
2108
2305
|
hasActive = true;
|
|
2109
2306
|
break;
|
|
2110
2307
|
}
|
|
@@ -2128,9 +2325,12 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
2128
2325
|
{
|
|
2129
2326
|
...subConfig.config,
|
|
2130
2327
|
looping: false,
|
|
2328
|
+
// Sub-emitters must always use CPU simulation because their compute
|
|
2329
|
+
// nodes cannot be dispatched independently by the parent system.
|
|
2330
|
+
simulationBackend: "CPU" /* CPU */,
|
|
2131
2331
|
transform: {
|
|
2132
2332
|
...subConfig.config.transform,
|
|
2133
|
-
position: new
|
|
2333
|
+
position: new THREE5.Vector3(position.x, position.y, position.z)
|
|
2134
2334
|
},
|
|
2135
2335
|
renderer: {
|
|
2136
2336
|
...subConfig.config.renderer ?? {},
|
|
@@ -2165,7 +2365,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
2165
2365
|
const totalVertices = maxParticles * verticesPerParticle;
|
|
2166
2366
|
const indicesPerParticle = (trailLength - 1) * 6;
|
|
2167
2367
|
const totalIndices = maxParticles * indicesPerParticle;
|
|
2168
|
-
trailGeometry = new
|
|
2368
|
+
trailGeometry = new THREE5.BufferGeometry();
|
|
2169
2369
|
const trailPositions = new Float32Array(totalVertices * 3);
|
|
2170
2370
|
const trailNextPositions = new Float32Array(totalVertices * 3);
|
|
2171
2371
|
const trailAlphas = new Float32Array(totalVertices);
|
|
@@ -2192,63 +2392,63 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
2192
2392
|
trailIndices[i + 5] = v + 2;
|
|
2193
2393
|
}
|
|
2194
2394
|
}
|
|
2195
|
-
trailPositionAttr = new
|
|
2196
|
-
trailPositionAttr.setUsage(
|
|
2197
|
-
trailNextAttr = new
|
|
2198
|
-
trailNextAttr.setUsage(
|
|
2199
|
-
trailAlphaAttr = new
|
|
2200
|
-
trailAlphaAttr.setUsage(
|
|
2201
|
-
trailColorAttr = new
|
|
2202
|
-
trailColorAttr.setUsage(
|
|
2203
|
-
trailHalfWidthAttr = new
|
|
2204
|
-
trailHalfWidthAttr.setUsage(
|
|
2205
|
-
trailUVAttr = new
|
|
2206
|
-
trailUVAttr.setUsage(
|
|
2207
|
-
trailIndexAttr = new
|
|
2395
|
+
trailPositionAttr = new THREE5.BufferAttribute(trailPositions, 3);
|
|
2396
|
+
trailPositionAttr.setUsage(THREE5.DynamicDrawUsage);
|
|
2397
|
+
trailNextAttr = new THREE5.BufferAttribute(trailNextPositions, 3);
|
|
2398
|
+
trailNextAttr.setUsage(THREE5.DynamicDrawUsage);
|
|
2399
|
+
trailAlphaAttr = new THREE5.BufferAttribute(trailAlphas, 1);
|
|
2400
|
+
trailAlphaAttr.setUsage(THREE5.DynamicDrawUsage);
|
|
2401
|
+
trailColorAttr = new THREE5.BufferAttribute(trailColors, 4);
|
|
2402
|
+
trailColorAttr.setUsage(THREE5.DynamicDrawUsage);
|
|
2403
|
+
trailHalfWidthAttr = new THREE5.BufferAttribute(trailHalfWidths, 1);
|
|
2404
|
+
trailHalfWidthAttr.setUsage(THREE5.DynamicDrawUsage);
|
|
2405
|
+
trailUVAttr = new THREE5.BufferAttribute(trailUVs, 2);
|
|
2406
|
+
trailUVAttr.setUsage(THREE5.DynamicDrawUsage);
|
|
2407
|
+
trailIndexAttr = new THREE5.BufferAttribute(trailIndices, 1);
|
|
2208
2408
|
trailGeometry.setAttribute("position", trailPositionAttr);
|
|
2209
2409
|
trailGeometry.setAttribute("trailNext", trailNextAttr);
|
|
2210
2410
|
trailGeometry.setAttribute("trailAlpha", trailAlphaAttr);
|
|
2211
2411
|
trailGeometry.setAttribute("trailColor", trailColorAttr);
|
|
2212
2412
|
trailGeometry.setAttribute(
|
|
2213
2413
|
"trailOffset",
|
|
2214
|
-
new
|
|
2414
|
+
new THREE5.BufferAttribute(trailOffsets, 1)
|
|
2215
2415
|
);
|
|
2216
2416
|
trailGeometry.setAttribute("trailHalfWidth", trailHalfWidthAttr);
|
|
2217
2417
|
trailGeometry.setAttribute("trailUV", trailUVAttr);
|
|
2218
2418
|
trailGeometry.setIndex(trailIndexAttr);
|
|
2219
|
-
const
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
value: renderer.softParticles?.depthTexture ?? null
|
|
2232
|
-
},
|
|
2233
|
-
cameraNearFar: { value: new THREE4.Vector2(0.1, 1e3) }
|
|
2419
|
+
const trailUniformValues = {
|
|
2420
|
+
map: { value: particleMap },
|
|
2421
|
+
useMap: { value: !!particleMap },
|
|
2422
|
+
discardBackgroundColor: { value: renderer.discardBackgroundColor },
|
|
2423
|
+
backgroundColor: { value: renderer.backgroundColor },
|
|
2424
|
+
backgroundColorTolerance: { value: renderer.backgroundColorTolerance },
|
|
2425
|
+
softParticlesEnabled: { value: softParticlesEnabled },
|
|
2426
|
+
softParticlesIntensity: {
|
|
2427
|
+
value: Math.max(renderer.softParticles?.intensity ?? 1, 1e-3)
|
|
2428
|
+
},
|
|
2429
|
+
sceneDepthTexture: {
|
|
2430
|
+
value: renderer.softParticles?.depthTexture ?? null
|
|
2234
2431
|
},
|
|
2432
|
+
cameraNearFar: { value: new THREE5.Vector2(0.1, 1e3) }
|
|
2433
|
+
};
|
|
2434
|
+
const trailMaterial = useTSL ? _tslMaterialFactory.createTSLTrailMaterial(
|
|
2435
|
+
trailUniformValues,
|
|
2436
|
+
rendererConfig
|
|
2437
|
+
) : new THREE5.ShaderMaterial({
|
|
2438
|
+
uniforms: trailUniformValues,
|
|
2235
2439
|
vertexShader: trail_vertex_shader_glsl_default,
|
|
2236
2440
|
fragmentShader: trail_fragment_shader_glsl_default,
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
depthTest: renderer.depthTest,
|
|
2240
|
-
depthWrite: renderer.depthWrite,
|
|
2241
|
-
side: THREE4.DoubleSide
|
|
2441
|
+
...rendererConfig,
|
|
2442
|
+
side: THREE5.DoubleSide
|
|
2242
2443
|
});
|
|
2243
|
-
trailMesh = new
|
|
2444
|
+
trailMesh = new THREE5.Mesh(trailGeometry, trailMaterial);
|
|
2244
2445
|
trailMesh.frustumCulled = false;
|
|
2245
|
-
const trailCameraPos = new
|
|
2446
|
+
const trailCameraPos = new THREE5.Vector3();
|
|
2246
2447
|
trailMesh.onBeforeRender = (_renderer, _scene, camera) => {
|
|
2247
2448
|
camera.getWorldPosition(trailCameraPos);
|
|
2248
2449
|
if (softParticlesEnabled && camera.isPerspectiveCamera) {
|
|
2249
2450
|
const perspCam = camera;
|
|
2250
|
-
|
|
2251
|
-
trailUniforms.cameraNearFar.value.set(
|
|
2451
|
+
trailUniformValues.cameraNearFar.value.set(
|
|
2252
2452
|
perspCam.near,
|
|
2253
2453
|
perspCam.far
|
|
2254
2454
|
);
|
|
@@ -2280,11 +2480,11 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
2280
2480
|
};
|
|
2281
2481
|
}
|
|
2282
2482
|
}
|
|
2283
|
-
let particleSystem = useInstancing || useMesh ? new
|
|
2284
|
-
if (useInstancing || softParticlesEnabled) {
|
|
2483
|
+
let particleSystem = useInstancing || useMesh ? new THREE5.Mesh(geometry, material) : new THREE5.Points(geometry, material);
|
|
2484
|
+
if (useInstancing || softParticlesEnabled || useGPUCompute) {
|
|
2285
2485
|
particleSystem.onBeforeRender = (glRenderer, _scene, camera) => {
|
|
2286
2486
|
if (useInstancing) {
|
|
2287
|
-
const size = glRenderer.getSize(new
|
|
2487
|
+
const size = glRenderer.getSize(new THREE5.Vector2());
|
|
2288
2488
|
sharedUniforms.viewportHeight.value = size.y * glRenderer.getPixelRatio();
|
|
2289
2489
|
}
|
|
2290
2490
|
if (softParticlesEnabled && camera.isPerspectiveCamera) {
|
|
@@ -2301,9 +2501,9 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
2301
2501
|
particleSystem.add(trailMesh);
|
|
2302
2502
|
}
|
|
2303
2503
|
particleSystem.position.copy(transform.position);
|
|
2304
|
-
particleSystem.rotation.x =
|
|
2305
|
-
particleSystem.rotation.y =
|
|
2306
|
-
particleSystem.rotation.z =
|
|
2504
|
+
particleSystem.rotation.x = THREE5.MathUtils.degToRad(transform.rotation.x);
|
|
2505
|
+
particleSystem.rotation.y = THREE5.MathUtils.degToRad(transform.rotation.y);
|
|
2506
|
+
particleSystem.rotation.z = THREE5.MathUtils.degToRad(transform.rotation.z);
|
|
2307
2507
|
particleSystem.scale.copy(transform.scale);
|
|
2308
2508
|
const mappedAttributes = {
|
|
2309
2509
|
position: aPosition,
|
|
@@ -2313,10 +2513,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
2313
2513
|
startFrame: aStartFrame,
|
|
2314
2514
|
size: aSize,
|
|
2315
2515
|
rotation: aRotation,
|
|
2316
|
-
|
|
2317
|
-
colorG: aColorG,
|
|
2318
|
-
colorB: aColorB,
|
|
2319
|
-
colorA: aColorA,
|
|
2516
|
+
color: aColor,
|
|
2320
2517
|
...useMesh ? { quat: aQuat } : {}
|
|
2321
2518
|
};
|
|
2322
2519
|
const calculatedCreationTime = now + calculateValue(generalData.particleSystemId, startDelay) * 1e3;
|
|
@@ -2334,6 +2531,9 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
2334
2531
|
positionArr[posIdx + 1],
|
|
2335
2532
|
positionArr[posIdx + 2]
|
|
2336
2533
|
);
|
|
2534
|
+
if (simulationSpace === "LOCAL" /* LOCAL */) {
|
|
2535
|
+
particleSystem.localToWorld(_subEmitterPosition);
|
|
2536
|
+
}
|
|
2337
2537
|
spawnSubEmitters(
|
|
2338
2538
|
deathSubEmitters,
|
|
2339
2539
|
_subEmitterPosition,
|
|
@@ -2348,6 +2548,9 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
2348
2548
|
positionArr[posIdx + 1],
|
|
2349
2549
|
positionArr[posIdx + 2]
|
|
2350
2550
|
);
|
|
2551
|
+
if (simulationSpace === "LOCAL" /* LOCAL */) {
|
|
2552
|
+
particleSystem.localToWorld(_subEmitterPosition);
|
|
2553
|
+
}
|
|
2351
2554
|
spawnSubEmitters(
|
|
2352
2555
|
birthSubEmitters,
|
|
2353
2556
|
_subEmitterPosition,
|
|
@@ -2359,7 +2562,9 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
2359
2562
|
particleSystem,
|
|
2360
2563
|
wrapper,
|
|
2361
2564
|
mappedAttributes,
|
|
2362
|
-
|
|
2565
|
+
scalarArray,
|
|
2566
|
+
scalarInterleavedBuffer,
|
|
2567
|
+
elapsedUniform: sharedUniforms.elapsed,
|
|
2363
2568
|
generalData,
|
|
2364
2569
|
onUpdate,
|
|
2365
2570
|
onComplete,
|
|
@@ -2370,6 +2575,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
2370
2575
|
simulationSpace,
|
|
2371
2576
|
gravity,
|
|
2372
2577
|
normalizedForceFields,
|
|
2578
|
+
normalizedCollisionPlanes,
|
|
2373
2579
|
emission,
|
|
2374
2580
|
normalizedConfig,
|
|
2375
2581
|
iterationCount: 0,
|
|
@@ -2379,6 +2585,9 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
2379
2585
|
activateParticle,
|
|
2380
2586
|
onParticleDeath,
|
|
2381
2587
|
onParticleBirth,
|
|
2588
|
+
useGPUCompute: useGPUCompute && gpuPipeline !== null,
|
|
2589
|
+
computePipeline: gpuPipeline ?? void 0,
|
|
2590
|
+
computeDispatchReady: false,
|
|
2382
2591
|
...useTrail ? {
|
|
2383
2592
|
trailMesh,
|
|
2384
2593
|
trailPositionAttr,
|
|
@@ -2440,15 +2649,22 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
2440
2649
|
cfg.forceFields
|
|
2441
2650
|
);
|
|
2442
2651
|
}
|
|
2652
|
+
if (partialConfig.collisionPlanes !== void 0) {
|
|
2653
|
+
instanceData.normalizedCollisionPlanes = normalizeCollisionPlanes(
|
|
2654
|
+
cfg.collisionPlanes
|
|
2655
|
+
);
|
|
2656
|
+
}
|
|
2443
2657
|
if (partialConfig.noise !== void 0) {
|
|
2444
2658
|
const n = cfg.noise;
|
|
2445
2659
|
generalData.noise = {
|
|
2446
2660
|
isActive: n.isActive,
|
|
2447
2661
|
strength: n.strength,
|
|
2448
2662
|
noisePower: 0.15 * n.strength,
|
|
2663
|
+
frequency: n.frequency,
|
|
2449
2664
|
positionAmount: n.positionAmount,
|
|
2450
2665
|
rotationAmount: n.rotationAmount,
|
|
2451
2666
|
sizeAmount: n.sizeAmount,
|
|
2667
|
+
fbmMax: 2 - Math.pow(2, -n.octaves),
|
|
2452
2668
|
sampler: n.isActive ? new FBM({
|
|
2453
2669
|
seed: Math.random(),
|
|
2454
2670
|
scale: n.frequency,
|
|
@@ -2464,7 +2680,8 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
2464
2680
|
pauseEmitter,
|
|
2465
2681
|
dispose,
|
|
2466
2682
|
update,
|
|
2467
|
-
updateConfig
|
|
2683
|
+
updateConfig,
|
|
2684
|
+
computeNode: gpuPipeline?.computeNode ?? null
|
|
2468
2685
|
};
|
|
2469
2686
|
};
|
|
2470
2687
|
var updateParticleSystemInstance = (props, { now, delta, elapsed }) => {
|
|
@@ -2489,11 +2706,15 @@ var updateParticleSystemInstance = (props, { now, delta, elapsed }) => {
|
|
|
2489
2706
|
simulationSpace,
|
|
2490
2707
|
gravity,
|
|
2491
2708
|
normalizedForceFields,
|
|
2709
|
+
normalizedCollisionPlanes,
|
|
2492
2710
|
onParticleDeath,
|
|
2493
2711
|
onParticleBirth,
|
|
2494
|
-
mappedAttributes: ma
|
|
2712
|
+
mappedAttributes: ma,
|
|
2713
|
+
useGPUCompute,
|
|
2714
|
+
computePipeline
|
|
2495
2715
|
} = props;
|
|
2496
2716
|
const hasForceFields = normalizedForceFields.length > 0;
|
|
2717
|
+
const hasCollisionPlanes = normalizedCollisionPlanes.length > 0;
|
|
2497
2718
|
const lifetime = now - creationTime;
|
|
2498
2719
|
const normalizedLifetime = lifetime % (duration * 1e3);
|
|
2499
2720
|
generalData.normalizedLifetimePercentage = Math.max(
|
|
@@ -2547,8 +2768,8 @@ var updateParticleSystemInstance = (props, { now, delta, elapsed }) => {
|
|
|
2547
2768
|
dst = {
|
|
2548
2769
|
isActive: true,
|
|
2549
2770
|
type: "POINT" /* POINT */,
|
|
2550
|
-
position: new
|
|
2551
|
-
direction: new
|
|
2771
|
+
position: new THREE5.Vector3(),
|
|
2772
|
+
direction: new THREE5.Vector3(),
|
|
2552
2773
|
strength: 0,
|
|
2553
2774
|
range: 0,
|
|
2554
2775
|
falloff: "LINEAR" /* LINEAR */
|
|
@@ -2568,42 +2789,123 @@ var updateParticleSystemInstance = (props, { now, delta, elapsed }) => {
|
|
|
2568
2789
|
dst.direction.copy(_localForceFieldDir);
|
|
2569
2790
|
}
|
|
2570
2791
|
}
|
|
2792
|
+
if (hasCollisionPlanes) {
|
|
2793
|
+
if (!hasForceFields) _inverseQuat.copy(worldQuaternion).invert();
|
|
2794
|
+
_localCollisionPlanes.length = normalizedCollisionPlanes.length;
|
|
2795
|
+
for (let i = 0; i < normalizedCollisionPlanes.length; i++) {
|
|
2796
|
+
const src = normalizedCollisionPlanes[i];
|
|
2797
|
+
let dst = _localCollisionPlanes[i];
|
|
2798
|
+
if (!dst) {
|
|
2799
|
+
dst = {
|
|
2800
|
+
isActive: true,
|
|
2801
|
+
position: new THREE5.Vector3(),
|
|
2802
|
+
normal: new THREE5.Vector3(),
|
|
2803
|
+
mode: "KILL" /* KILL */,
|
|
2804
|
+
dampen: 0.5,
|
|
2805
|
+
lifetimeLoss: 0
|
|
2806
|
+
};
|
|
2807
|
+
_localCollisionPlanes[i] = dst;
|
|
2808
|
+
}
|
|
2809
|
+
dst.isActive = src.isActive;
|
|
2810
|
+
dst.mode = src.mode;
|
|
2811
|
+
dst.dampen = src.dampen;
|
|
2812
|
+
dst.lifetimeLoss = src.lifetimeLoss;
|
|
2813
|
+
_localCollisionPlanePos.copy(src.position);
|
|
2814
|
+
particleSystem.worldToLocal(_localCollisionPlanePos);
|
|
2815
|
+
dst.position.copy(_localCollisionPlanePos);
|
|
2816
|
+
_localCollisionPlaneNormal.copy(src.normal);
|
|
2817
|
+
_localCollisionPlaneNormal.applyQuaternion(_inverseQuat);
|
|
2818
|
+
dst.normal.copy(_localCollisionPlaneNormal);
|
|
2819
|
+
}
|
|
2820
|
+
}
|
|
2571
2821
|
const creationTimes = generalData.creationTimes;
|
|
2572
|
-
const
|
|
2573
|
-
const startLifetimeArr = ma.startLifetime.array;
|
|
2822
|
+
const scalarArr = props.scalarArray;
|
|
2574
2823
|
const positionArr = ma.position.array;
|
|
2575
|
-
const lifetimeArr = ma.lifetime.array;
|
|
2576
2824
|
const creationTimesLength = creationTimes.length;
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2825
|
+
if (useGPUCompute && computePipeline) {
|
|
2826
|
+
const cp = computePipeline;
|
|
2827
|
+
setUniformFloat(cp.uniforms.delta, delta);
|
|
2828
|
+
setUniformFloat(cp.uniforms.deltaMs, delta * 1e3);
|
|
2829
|
+
setUniformVec3(
|
|
2830
|
+
cp.uniforms.gravityVelocity,
|
|
2831
|
+
gravityVelocity.x,
|
|
2832
|
+
gravityVelocity.y,
|
|
2833
|
+
gravityVelocity.z
|
|
2834
|
+
);
|
|
2835
|
+
setUniformVec3(
|
|
2836
|
+
cp.uniforms.worldPositionChange,
|
|
2837
|
+
generalData.worldPositionChange.x,
|
|
2838
|
+
generalData.worldPositionChange.y,
|
|
2839
|
+
generalData.worldPositionChange.z
|
|
2840
|
+
);
|
|
2841
|
+
setUniformFloat(
|
|
2842
|
+
cp.uniforms.simulationSpaceWorld,
|
|
2843
|
+
simulationSpace === "WORLD" /* WORLD */ ? 1 : 0
|
|
2844
|
+
);
|
|
2845
|
+
const noiseData = generalData.noise;
|
|
2846
|
+
setUniformFloat(cp.uniforms.noiseStrength, noiseData.strength);
|
|
2847
|
+
setUniformFloat(
|
|
2848
|
+
cp.uniforms.noisePower,
|
|
2849
|
+
noiseData.noisePower / noiseData.fbmMax
|
|
2850
|
+
);
|
|
2851
|
+
setUniformFloat(cp.uniforms.noiseFrequency, noiseData.frequency);
|
|
2852
|
+
setUniformFloat(cp.uniforms.noisePositionAmount, noiseData.positionAmount);
|
|
2853
|
+
setUniformFloat(cp.uniforms.noiseRotationAmount, noiseData.rotationAmount);
|
|
2854
|
+
setUniformFloat(cp.uniforms.noiseSizeAmount, noiseData.sizeAmount);
|
|
2855
|
+
if (cp.forceFieldInfo && hasForceFields && _tslMaterialFactory?.encodeForceFieldsForGPU) {
|
|
2856
|
+
const encodedFF = _tslMaterialFactory.encodeForceFieldsForGPU(
|
|
2857
|
+
_localForceFields,
|
|
2858
|
+
generalData.particleSystemId,
|
|
2859
|
+
generalData.normalizedLifetimePercentage
|
|
2860
|
+
);
|
|
2861
|
+
const curveArr = cp.buffers.curveData.array;
|
|
2862
|
+
curveArr.set(encodedFF, cp.forceFieldInfo.offset);
|
|
2863
|
+
cp.buffers.curveData.needsUpdate = true;
|
|
2864
|
+
setUniformFloat(
|
|
2865
|
+
cp.forceFieldInfo.countUniform,
|
|
2866
|
+
normalizedForceFields.length
|
|
2867
|
+
);
|
|
2868
|
+
}
|
|
2869
|
+
if (cp.collisionPlaneInfo && hasCollisionPlanes && _tslMaterialFactory?.encodeCollisionPlanesForGPU) {
|
|
2870
|
+
const encodedCP = _tslMaterialFactory.encodeCollisionPlanesForGPU(
|
|
2871
|
+
_localCollisionPlanes
|
|
2872
|
+
);
|
|
2873
|
+
const curveArr = cp.buffers.curveData.array;
|
|
2874
|
+
curveArr.set(encodedCP, cp.collisionPlaneInfo.offset);
|
|
2875
|
+
cp.buffers.curveData.needsUpdate = true;
|
|
2876
|
+
setUniformFloat(
|
|
2877
|
+
cp.collisionPlaneInfo.countUniform,
|
|
2878
|
+
normalizedCollisionPlanes.length
|
|
2879
|
+
);
|
|
2880
|
+
}
|
|
2881
|
+
if (_tslMaterialFactory?.flushEmitQueue) {
|
|
2882
|
+
_tslMaterialFactory.flushEmitQueue(cp.buffers);
|
|
2883
|
+
}
|
|
2884
|
+
props.computeDispatchReady = true;
|
|
2885
|
+
for (let index = 0; index < creationTimesLength; index++) {
|
|
2886
|
+
const base = index * SCALAR_STRIDE;
|
|
2887
|
+
if (scalarArr[base + S_IS_ACTIVE]) {
|
|
2888
|
+
const particleLifetime = now - creationTimes[index];
|
|
2889
|
+
if (particleLifetime > scalarArr[base + S_START_LIFETIME]) {
|
|
2890
|
+
if (onParticleDeath)
|
|
2891
|
+
onParticleDeath(index, positionArr, velocities[index], now);
|
|
2892
|
+
deactivateParticle(index);
|
|
2893
|
+
} else if (onParticleDeath) {
|
|
2894
|
+
const velocity = velocities[index];
|
|
2895
|
+
velocity.x -= gravityVelocity.x * delta;
|
|
2896
|
+
velocity.y -= gravityVelocity.y * delta;
|
|
2897
|
+
velocity.z -= gravityVelocity.z * delta;
|
|
2898
|
+
if (hasForceFields) {
|
|
2899
|
+
applyForceFields({
|
|
2900
|
+
particleSystemId: generalData.particleSystemId,
|
|
2901
|
+
forceFields: _localForceFields,
|
|
2902
|
+
velocity,
|
|
2903
|
+
positionArr,
|
|
2904
|
+
positionIndex: index * 3,
|
|
2905
|
+
delta,
|
|
2906
|
+
systemLifetimePercentage: generalData.normalizedLifetimePercentage
|
|
2907
|
+
});
|
|
2908
|
+
}
|
|
2607
2909
|
const positionIndex = index * 3;
|
|
2608
2910
|
if (simulationSpace === "WORLD" /* WORLD */) {
|
|
2609
2911
|
positionArr[positionIndex] -= worldPositionChange.x;
|
|
@@ -2613,18 +2915,116 @@ var updateParticleSystemInstance = (props, { now, delta, elapsed }) => {
|
|
|
2613
2915
|
positionArr[positionIndex] += velocity.x * delta;
|
|
2614
2916
|
positionArr[positionIndex + 1] += velocity.y * delta;
|
|
2615
2917
|
positionArr[positionIndex + 2] += velocity.z * delta;
|
|
2616
|
-
|
|
2918
|
+
if (generalData.orbitalVelocityData) {
|
|
2919
|
+
const orbData = generalData.orbitalVelocityData[index];
|
|
2920
|
+
const { speed, positionOffset, valueModifiers } = orbData;
|
|
2921
|
+
const pctLife = particleLifetime / scalarArr[base + S_START_LIFETIME];
|
|
2922
|
+
positionArr[positionIndex] -= positionOffset.x;
|
|
2923
|
+
positionArr[positionIndex + 1] -= positionOffset.y;
|
|
2924
|
+
positionArr[positionIndex + 2] -= positionOffset.z;
|
|
2925
|
+
const sx = valueModifiers.x ? valueModifiers.x(pctLife) : speed.x;
|
|
2926
|
+
const sy = valueModifiers.y ? valueModifiers.y(pctLife) : speed.y;
|
|
2927
|
+
const sz = valueModifiers.z ? valueModifiers.z(pctLife) : speed.z;
|
|
2928
|
+
_shadowOrbitalEuler.set(sx * delta, sz * delta, sy * delta);
|
|
2929
|
+
positionOffset.applyEuler(_shadowOrbitalEuler);
|
|
2930
|
+
positionArr[positionIndex] += positionOffset.x;
|
|
2931
|
+
positionArr[positionIndex + 1] += positionOffset.y;
|
|
2932
|
+
positionArr[positionIndex + 2] += positionOffset.z;
|
|
2933
|
+
}
|
|
2934
|
+
if (hasCollisionPlanes) {
|
|
2935
|
+
applyCollisionPlanes({
|
|
2936
|
+
collisionPlanes: _localCollisionPlanes,
|
|
2937
|
+
velocity,
|
|
2938
|
+
positionArr,
|
|
2939
|
+
positionIndex,
|
|
2940
|
+
scalarArr,
|
|
2941
|
+
scalarBase: base,
|
|
2942
|
+
deactivateParticle: (pi) => {
|
|
2943
|
+
if (onParticleDeath)
|
|
2944
|
+
onParticleDeath(pi, positionArr, velocities[pi], now);
|
|
2945
|
+
deactivateParticle(pi);
|
|
2946
|
+
},
|
|
2947
|
+
particleIndex: index
|
|
2948
|
+
});
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
}
|
|
2952
|
+
}
|
|
2953
|
+
} else {
|
|
2954
|
+
let positionNeedsUpdate = false;
|
|
2955
|
+
let scalarNeedsUpdate = false;
|
|
2956
|
+
_modifierParams.delta = delta;
|
|
2957
|
+
_modifierParams.generalData = generalData;
|
|
2958
|
+
_modifierParams.normalizedConfig = normalizedConfig;
|
|
2959
|
+
_modifierParams.attributes = ma;
|
|
2960
|
+
_modifierParams.scalarArray = scalarArr;
|
|
2961
|
+
for (let index = 0; index < creationTimesLength; index++) {
|
|
2962
|
+
const base = index * SCALAR_STRIDE;
|
|
2963
|
+
if (scalarArr[base + S_IS_ACTIVE]) {
|
|
2964
|
+
const particleLifetime = now - creationTimes[index];
|
|
2965
|
+
if (particleLifetime > scalarArr[base + S_START_LIFETIME]) {
|
|
2966
|
+
if (onParticleDeath)
|
|
2967
|
+
onParticleDeath(index, positionArr, velocities[index], now);
|
|
2968
|
+
deactivateParticle(index);
|
|
2969
|
+
} else {
|
|
2970
|
+
const velocity = velocities[index];
|
|
2971
|
+
velocity.x -= gravityVelocity.x * delta;
|
|
2972
|
+
velocity.y -= gravityVelocity.y * delta;
|
|
2973
|
+
velocity.z -= gravityVelocity.z * delta;
|
|
2974
|
+
if (hasForceFields) {
|
|
2975
|
+
applyForceFields({
|
|
2976
|
+
particleSystemId: generalData.particleSystemId,
|
|
2977
|
+
forceFields: _localForceFields,
|
|
2978
|
+
velocity,
|
|
2979
|
+
positionArr,
|
|
2980
|
+
positionIndex: index * 3,
|
|
2981
|
+
delta,
|
|
2982
|
+
systemLifetimePercentage: generalData.normalizedLifetimePercentage
|
|
2983
|
+
});
|
|
2984
|
+
}
|
|
2985
|
+
if (gravity !== 0 || velocity.x !== 0 || velocity.y !== 0 || velocity.z !== 0 || worldPositionChange.x !== 0 || worldPositionChange.y !== 0 || worldPositionChange.z !== 0) {
|
|
2986
|
+
const positionIndex = index * 3;
|
|
2987
|
+
if (simulationSpace === "WORLD" /* WORLD */) {
|
|
2988
|
+
positionArr[positionIndex] -= worldPositionChange.x;
|
|
2989
|
+
positionArr[positionIndex + 1] -= worldPositionChange.y;
|
|
2990
|
+
positionArr[positionIndex + 2] -= worldPositionChange.z;
|
|
2991
|
+
}
|
|
2992
|
+
positionArr[positionIndex] += velocity.x * delta;
|
|
2993
|
+
positionArr[positionIndex + 1] += velocity.y * delta;
|
|
2994
|
+
positionArr[positionIndex + 2] += velocity.z * delta;
|
|
2995
|
+
positionNeedsUpdate = true;
|
|
2996
|
+
}
|
|
2997
|
+
if (hasCollisionPlanes) {
|
|
2998
|
+
const killed = applyCollisionPlanes({
|
|
2999
|
+
collisionPlanes: _localCollisionPlanes,
|
|
3000
|
+
velocity,
|
|
3001
|
+
positionArr,
|
|
3002
|
+
positionIndex: index * 3,
|
|
3003
|
+
scalarArr,
|
|
3004
|
+
scalarBase: base,
|
|
3005
|
+
deactivateParticle: (pi) => {
|
|
3006
|
+
if (onParticleDeath)
|
|
3007
|
+
onParticleDeath(pi, positionArr, velocities[pi], now);
|
|
3008
|
+
deactivateParticle(pi);
|
|
3009
|
+
},
|
|
3010
|
+
particleIndex: index
|
|
3011
|
+
});
|
|
3012
|
+
if (killed) {
|
|
3013
|
+
positionNeedsUpdate = true;
|
|
3014
|
+
continue;
|
|
3015
|
+
}
|
|
3016
|
+
}
|
|
3017
|
+
scalarArr[base + S_LIFETIME] = particleLifetime;
|
|
3018
|
+
scalarNeedsUpdate = true;
|
|
3019
|
+
_modifierParams.particleLifetimePercentage = particleLifetime / scalarArr[base + S_START_LIFETIME];
|
|
3020
|
+
_modifierParams.particleIndex = index;
|
|
3021
|
+
applyModifiers(_modifierParams);
|
|
2617
3022
|
}
|
|
2618
|
-
lifetimeArr[index] = particleLifetime;
|
|
2619
|
-
lifetimeNeedsUpdate = true;
|
|
2620
|
-
_modifierParams.particleLifetimePercentage = particleLifetime / startLifetimeArr[index];
|
|
2621
|
-
_modifierParams.particleIndex = index;
|
|
2622
|
-
applyModifiers(_modifierParams);
|
|
2623
3023
|
}
|
|
2624
3024
|
}
|
|
3025
|
+
if (positionNeedsUpdate) ma.position.needsUpdate = true;
|
|
3026
|
+
if (scalarNeedsUpdate) props.scalarInterleavedBuffer.needsUpdate = true;
|
|
2625
3027
|
}
|
|
2626
|
-
if (positionNeedsUpdate) ma.position.needsUpdate = true;
|
|
2627
|
-
if (lifetimeNeedsUpdate) ma.lifetime.needsUpdate = true;
|
|
2628
3028
|
if (isEnabled && (looping || lifetime < duration * 1e3)) {
|
|
2629
3029
|
const emissionDelta = now - lastEmissionTime;
|
|
2630
3030
|
const neededParticlesByTime = emission.rateOverTime ? Math.floor(
|
|
@@ -2841,12 +3241,8 @@ var updateTrailGeometry = (props, now) => {
|
|
|
2841
3241
|
const subdivisions = trailConfig.smoothingSubdivisions;
|
|
2842
3242
|
const useTwistPrevention = trailConfig.twistPrevention;
|
|
2843
3243
|
const ribbonId = trailConfig.ribbonId;
|
|
2844
|
-
const
|
|
3244
|
+
const trailScalarArr = props.scalarArray;
|
|
2845
3245
|
const positionArr = ma.position.array;
|
|
2846
|
-
const colorRArr = ma.colorR.array;
|
|
2847
|
-
const colorGArr = ma.colorG.array;
|
|
2848
|
-
const colorBArr = ma.colorB.array;
|
|
2849
|
-
const colorAArr = ma.colorA.array;
|
|
2850
3246
|
const trailPosArr = trailPositionAttr.array;
|
|
2851
3247
|
const trailAlphaArr = trailAlphaAttr.array;
|
|
2852
3248
|
const trailColorArr = trailColorAttr.array;
|
|
@@ -2865,7 +3261,8 @@ var updateTrailGeometry = (props, now) => {
|
|
|
2865
3261
|
}
|
|
2866
3262
|
_ribbonCount = 0;
|
|
2867
3263
|
for (let i = 0; i < creationTimesLength; i++) {
|
|
2868
|
-
if (
|
|
3264
|
+
if (trailScalarArr[i * SCALAR_STRIDE + S_IS_ACTIVE])
|
|
3265
|
+
_ribbonIndices[_ribbonCount++] = i;
|
|
2869
3266
|
}
|
|
2870
3267
|
for (let i = 1; i < _ribbonCount; i++) {
|
|
2871
3268
|
const key = _ribbonIndices[i];
|
|
@@ -2881,7 +3278,7 @@ var updateTrailGeometry = (props, now) => {
|
|
|
2881
3278
|
}
|
|
2882
3279
|
for (let index = 0; index < creationTimesLength; index++) {
|
|
2883
3280
|
const vertBase = index * verticesPerParticle;
|
|
2884
|
-
if (
|
|
3281
|
+
if (trailScalarArr[index * SCALAR_STRIDE + S_IS_ACTIVE]) {
|
|
2885
3282
|
if (useRibbon && _ribbonCount >= 2 && index !== ribbonLeader) {
|
|
2886
3283
|
const posIdx2 = index * 3;
|
|
2887
3284
|
const px2 = positionArr[posIdx2];
|
|
@@ -2947,10 +3344,11 @@ var updateTrailGeometry = (props, now) => {
|
|
|
2947
3344
|
}
|
|
2948
3345
|
const count = effectiveCount;
|
|
2949
3346
|
const ribbonWidth = trailConfig.width;
|
|
2950
|
-
const
|
|
2951
|
-
const
|
|
2952
|
-
const
|
|
2953
|
-
const
|
|
3347
|
+
const trailBase = index * SCALAR_STRIDE;
|
|
3348
|
+
const cr = trailScalarArr[trailBase + S_COLOR_R];
|
|
3349
|
+
const cg = trailScalarArr[trailBase + S_COLOR_G];
|
|
3350
|
+
const cb = trailScalarArr[trailBase + S_COLOR_B];
|
|
3351
|
+
const ca = trailScalarArr[trailBase + S_COLOR_A];
|
|
2954
3352
|
const ringOff = index * trailLength * 3;
|
|
2955
3353
|
const rawPtsSize = count * 3;
|
|
2956
3354
|
if (!_rawPoints || _rawPointsSize < rawPtsSize) {
|
|
@@ -3290,10 +3688,11 @@ var updateTrailGeometry = (props, now) => {
|
|
|
3290
3688
|
_rawPoints[(wi - 1) * 3 + 2] = positionArr[lastPIdx + 2];
|
|
3291
3689
|
}
|
|
3292
3690
|
}
|
|
3293
|
-
const
|
|
3294
|
-
const
|
|
3295
|
-
const
|
|
3296
|
-
const
|
|
3691
|
+
const leaderBase = leader * SCALAR_STRIDE;
|
|
3692
|
+
const leaderCr = trailScalarArr[leaderBase + S_COLOR_R];
|
|
3693
|
+
const leaderCg = trailScalarArr[leaderBase + S_COLOR_G];
|
|
3694
|
+
const leaderCb = trailScalarArr[leaderBase + S_COLOR_B];
|
|
3695
|
+
const leaderCa = trailScalarArr[leaderBase + S_COLOR_A];
|
|
3297
3696
|
for (let s = 0; s < trailLength; s++) {
|
|
3298
3697
|
const vIdx = (leaderVertBase + s * 2) * 3;
|
|
3299
3698
|
const cIdx = (leaderVertBase + s * 2) * 4;
|
|
@@ -3493,6 +3892,253 @@ var updateParticleSystems = (cycleData) => {
|
|
|
3493
3892
|
);
|
|
3494
3893
|
};
|
|
3495
3894
|
|
|
3496
|
-
|
|
3895
|
+
// src/js/effects/three-particles/three-particles-serialization.ts
|
|
3896
|
+
var SERIALIZATION_VERSION = 1;
|
|
3897
|
+
var reverseBlendingMap = new Map(
|
|
3898
|
+
Object.entries(blendingMap).map(([k, v]) => [
|
|
3899
|
+
v,
|
|
3900
|
+
k
|
|
3901
|
+
])
|
|
3902
|
+
);
|
|
3903
|
+
var reverseCurveFunctionMap = /* @__PURE__ */ new Map();
|
|
3904
|
+
for (const [id, fn] of Object.entries(curveFunctionIdMap)) {
|
|
3905
|
+
if (fn) reverseCurveFunctionMap.set(fn, id);
|
|
3906
|
+
}
|
|
3907
|
+
function serializeAny(value, key) {
|
|
3908
|
+
if (value === null || value === void 0) return value;
|
|
3909
|
+
if (value instanceof THREE5.Vector3)
|
|
3910
|
+
return { x: value.x, y: value.y, z: value.z };
|
|
3911
|
+
if (value instanceof THREE5.Vector2) return { x: value.x, y: value.y };
|
|
3912
|
+
if (value instanceof THREE5.Texture) return void 0;
|
|
3913
|
+
if (typeof value === "function") return void 0;
|
|
3914
|
+
if (Array.isArray(value)) return value.map((item) => serializeAny(item));
|
|
3915
|
+
if (typeof value === "object") {
|
|
3916
|
+
const obj = value;
|
|
3917
|
+
if (obj["type"] === "EASING" /* EASING */ && typeof obj["curveFunction"] === "function") {
|
|
3918
|
+
const id = reverseCurveFunctionMap.get(
|
|
3919
|
+
obj["curveFunction"]
|
|
3920
|
+
);
|
|
3921
|
+
if (!id) {
|
|
3922
|
+
throw new Error(
|
|
3923
|
+
"Cannot serialize a custom curveFunction. Use a predefined CurveFunctionId instead."
|
|
3924
|
+
);
|
|
3925
|
+
}
|
|
3926
|
+
return {
|
|
3927
|
+
type: "EASING" /* EASING */,
|
|
3928
|
+
curveFunctionId: id,
|
|
3929
|
+
...obj["scale"] !== void 0 ? { scale: obj["scale"] } : {}
|
|
3930
|
+
};
|
|
3931
|
+
}
|
|
3932
|
+
const result = {};
|
|
3933
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
3934
|
+
if (k === "onUpdate" || k === "onComplete") continue;
|
|
3935
|
+
if (k === "blending" && typeof v === "number") {
|
|
3936
|
+
result[k] = reverseBlendingMap.get(v) ?? v;
|
|
3937
|
+
continue;
|
|
3938
|
+
}
|
|
3939
|
+
const serialized = serializeAny(v);
|
|
3940
|
+
if (serialized !== void 0) result[k] = serialized;
|
|
3941
|
+
}
|
|
3942
|
+
return result;
|
|
3943
|
+
}
|
|
3944
|
+
return value;
|
|
3945
|
+
}
|
|
3946
|
+
function serializeParticleSystem(config) {
|
|
3947
|
+
const serialized = serializeAny(config);
|
|
3948
|
+
return JSON.stringify({ _version: SERIALIZATION_VERSION, ...serialized });
|
|
3949
|
+
}
|
|
3950
|
+
function deserializeCurve(raw) {
|
|
3951
|
+
const obj = raw;
|
|
3952
|
+
if (Array.isArray(obj["bezierPoints"]) && !obj["type"]) {
|
|
3953
|
+
return { type: "BEZIER" /* BEZIER */, ...obj };
|
|
3954
|
+
}
|
|
3955
|
+
if (obj["type"] === "EASING" /* EASING */) {
|
|
3956
|
+
const id = obj["curveFunctionId"];
|
|
3957
|
+
const fn = getCurveFunction(id);
|
|
3958
|
+
if (!fn) {
|
|
3959
|
+
throw new Error(
|
|
3960
|
+
`Unknown curveFunctionId: "${id}". Use a value from CurveFunctionId.`
|
|
3961
|
+
);
|
|
3962
|
+
}
|
|
3963
|
+
const curve = {
|
|
3964
|
+
type: "EASING" /* EASING */,
|
|
3965
|
+
curveFunction: fn
|
|
3966
|
+
};
|
|
3967
|
+
if (obj["scale"] !== void 0) curve.scale = obj["scale"];
|
|
3968
|
+
return curve;
|
|
3969
|
+
}
|
|
3970
|
+
return obj;
|
|
3971
|
+
}
|
|
3972
|
+
function deserializeCurveOrValue(value) {
|
|
3973
|
+
if (typeof value === "number") return value;
|
|
3974
|
+
if (!value || typeof value !== "object") return value;
|
|
3975
|
+
const obj = value;
|
|
3976
|
+
const looksLikeCurve = Array.isArray(obj["bezierPoints"]) || obj["type"] === "BEZIER" /* BEZIER */ || obj["type"] === "EASING" /* EASING */ || typeof obj["curveFunctionId"] === "string";
|
|
3977
|
+
if (looksLikeCurve) return deserializeCurve(obj);
|
|
3978
|
+
return obj;
|
|
3979
|
+
}
|
|
3980
|
+
function deserializeVector3(raw) {
|
|
3981
|
+
if (!raw || typeof raw !== "object") return void 0;
|
|
3982
|
+
const { x = 0, y = 0, z = 0 } = raw;
|
|
3983
|
+
return new THREE5.Vector3(x, y, z);
|
|
3984
|
+
}
|
|
3985
|
+
function deserializeVector2(raw) {
|
|
3986
|
+
if (!raw || typeof raw !== "object") return void 0;
|
|
3987
|
+
const { x = 1, y = 1 } = raw;
|
|
3988
|
+
return new THREE5.Vector2(x, y);
|
|
3989
|
+
}
|
|
3990
|
+
function deserializeConfig(raw) {
|
|
3991
|
+
const config = {};
|
|
3992
|
+
if (raw["transform"] && typeof raw["transform"] === "object") {
|
|
3993
|
+
const t = raw["transform"];
|
|
3994
|
+
config.transform = {
|
|
3995
|
+
position: deserializeVector3(t["position"]),
|
|
3996
|
+
rotation: deserializeVector3(t["rotation"]),
|
|
3997
|
+
scale: deserializeVector3(t["scale"])
|
|
3998
|
+
};
|
|
3999
|
+
}
|
|
4000
|
+
for (const field of [
|
|
4001
|
+
"duration",
|
|
4002
|
+
"looping",
|
|
4003
|
+
"gravity",
|
|
4004
|
+
"simulationSpace",
|
|
4005
|
+
"simulationBackend",
|
|
4006
|
+
"maxParticles"
|
|
4007
|
+
]) {
|
|
4008
|
+
if (field in raw) config[field] = raw[field];
|
|
4009
|
+
}
|
|
4010
|
+
for (const field of [
|
|
4011
|
+
"startDelay",
|
|
4012
|
+
"startLifetime",
|
|
4013
|
+
"startSpeed",
|
|
4014
|
+
"startSize",
|
|
4015
|
+
"startOpacity",
|
|
4016
|
+
"startRotation"
|
|
4017
|
+
]) {
|
|
4018
|
+
if (field in raw)
|
|
4019
|
+
config[field] = deserializeCurveOrValue(raw[field]);
|
|
4020
|
+
}
|
|
4021
|
+
if ("startColor" in raw)
|
|
4022
|
+
config.startColor = raw["startColor"];
|
|
4023
|
+
if (raw["emission"] && typeof raw["emission"] === "object") {
|
|
4024
|
+
const e = raw["emission"];
|
|
4025
|
+
config.emission = {
|
|
4026
|
+
rateOverTime: deserializeCurveOrValue(e["rateOverTime"]),
|
|
4027
|
+
rateOverDistance: deserializeCurveOrValue(
|
|
4028
|
+
e["rateOverDistance"]
|
|
4029
|
+
),
|
|
4030
|
+
bursts: Array.isArray(e["bursts"]) ? e["bursts"] : []
|
|
4031
|
+
};
|
|
4032
|
+
}
|
|
4033
|
+
if ("shape" in raw)
|
|
4034
|
+
config.shape = raw["shape"];
|
|
4035
|
+
if (raw["renderer"] && typeof raw["renderer"] === "object") {
|
|
4036
|
+
const r = raw["renderer"];
|
|
4037
|
+
const blending = typeof r["blending"] === "string" ? blendingMap[r["blending"]] ?? THREE5.NormalBlending : r["blending"] ?? THREE5.NormalBlending;
|
|
4038
|
+
config.renderer = { ...r, blending };
|
|
4039
|
+
}
|
|
4040
|
+
if (raw["velocityOverLifetime"] && typeof raw["velocityOverLifetime"] === "object") {
|
|
4041
|
+
const vol = raw["velocityOverLifetime"];
|
|
4042
|
+
const deserializeAxis = (axis) => {
|
|
4043
|
+
if (!axis || typeof axis !== "object") return {};
|
|
4044
|
+
const a = axis;
|
|
4045
|
+
return {
|
|
4046
|
+
...a["x"] !== void 0 ? { x: deserializeCurveOrValue(a["x"]) } : {},
|
|
4047
|
+
...a["y"] !== void 0 ? { y: deserializeCurveOrValue(a["y"]) } : {},
|
|
4048
|
+
...a["z"] !== void 0 ? { z: deserializeCurveOrValue(a["z"]) } : {}
|
|
4049
|
+
};
|
|
4050
|
+
};
|
|
4051
|
+
config.velocityOverLifetime = {
|
|
4052
|
+
isActive: vol["isActive"] ?? false,
|
|
4053
|
+
linear: deserializeAxis(vol["linear"]),
|
|
4054
|
+
orbital: deserializeAxis(vol["orbital"])
|
|
4055
|
+
};
|
|
4056
|
+
}
|
|
4057
|
+
for (const field of ["sizeOverLifetime", "opacityOverLifetime"]) {
|
|
4058
|
+
if (raw[field] && typeof raw[field] === "object") {
|
|
4059
|
+
const m = raw[field];
|
|
4060
|
+
config[field] = {
|
|
4061
|
+
isActive: m["isActive"] ?? false,
|
|
4062
|
+
lifetimeCurve: deserializeCurve(m["lifetimeCurve"])
|
|
4063
|
+
};
|
|
4064
|
+
}
|
|
4065
|
+
}
|
|
4066
|
+
if (raw["colorOverLifetime"] && typeof raw["colorOverLifetime"] === "object") {
|
|
4067
|
+
const col = raw["colorOverLifetime"];
|
|
4068
|
+
config.colorOverLifetime = {
|
|
4069
|
+
isActive: col["isActive"] ?? true,
|
|
4070
|
+
r: deserializeCurve(col["r"]),
|
|
4071
|
+
g: deserializeCurve(col["g"]),
|
|
4072
|
+
b: deserializeCurve(col["b"])
|
|
4073
|
+
};
|
|
4074
|
+
}
|
|
4075
|
+
if (raw["rotationOverLifetime"] && typeof raw["rotationOverLifetime"] === "object") {
|
|
4076
|
+
config.rotationOverLifetime = raw["rotationOverLifetime"];
|
|
4077
|
+
}
|
|
4078
|
+
if (raw["noise"] && typeof raw["noise"] === "object") {
|
|
4079
|
+
config.noise = raw["noise"];
|
|
4080
|
+
}
|
|
4081
|
+
if (raw["textureSheetAnimation"] && typeof raw["textureSheetAnimation"] === "object") {
|
|
4082
|
+
const tsa = raw["textureSheetAnimation"];
|
|
4083
|
+
config.textureSheetAnimation = {
|
|
4084
|
+
...tsa,
|
|
4085
|
+
tiles: deserializeVector2(tsa["tiles"]),
|
|
4086
|
+
startFrame: deserializeCurveOrValue(tsa["startFrame"])
|
|
4087
|
+
};
|
|
4088
|
+
}
|
|
4089
|
+
if (Array.isArray(raw["subEmitters"])) {
|
|
4090
|
+
config.subEmitters = raw["subEmitters"].map((se) => ({
|
|
4091
|
+
...se,
|
|
4092
|
+
config: deserializeConfig(se["config"])
|
|
4093
|
+
}));
|
|
4094
|
+
}
|
|
4095
|
+
if (Array.isArray(raw["forceFields"])) {
|
|
4096
|
+
config.forceFields = raw["forceFields"].map((ff) => {
|
|
4097
|
+
const result = {};
|
|
4098
|
+
if ("isActive" in ff) result.isActive = ff["isActive"];
|
|
4099
|
+
if ("type" in ff) result.type = ff["type"];
|
|
4100
|
+
if (ff["position"]) result.position = deserializeVector3(ff["position"]);
|
|
4101
|
+
if (ff["direction"])
|
|
4102
|
+
result.direction = deserializeVector3(ff["direction"]);
|
|
4103
|
+
if ("strength" in ff)
|
|
4104
|
+
result.strength = deserializeCurveOrValue(
|
|
4105
|
+
ff["strength"]
|
|
4106
|
+
);
|
|
4107
|
+
if ("range" in ff)
|
|
4108
|
+
result.range = ff["range"] === null ? Infinity : ff["range"];
|
|
4109
|
+
if ("falloff" in ff) result.falloff = ff["falloff"];
|
|
4110
|
+
return result;
|
|
4111
|
+
});
|
|
4112
|
+
}
|
|
4113
|
+
if (Array.isArray(raw["collisionPlanes"])) {
|
|
4114
|
+
config.collisionPlanes = raw["collisionPlanes"].map(
|
|
4115
|
+
(cp) => {
|
|
4116
|
+
const result = {};
|
|
4117
|
+
if ("isActive" in cp) result.isActive = cp["isActive"];
|
|
4118
|
+
if ("mode" in cp) result.mode = cp["mode"];
|
|
4119
|
+
if (cp["position"])
|
|
4120
|
+
result.position = deserializeVector3(cp["position"]);
|
|
4121
|
+
if (cp["normal"]) result.normal = deserializeVector3(cp["normal"]);
|
|
4122
|
+
if ("dampen" in cp) result.dampen = cp["dampen"];
|
|
4123
|
+
if ("lifetimeLoss" in cp)
|
|
4124
|
+
result.lifetimeLoss = cp["lifetimeLoss"];
|
|
4125
|
+
return result;
|
|
4126
|
+
}
|
|
4127
|
+
);
|
|
4128
|
+
}
|
|
4129
|
+
for (const key of Object.keys(raw)) {
|
|
4130
|
+
if (!(key in config) && key !== "_version" && raw[key] !== null) {
|
|
4131
|
+
config[key] = raw[key];
|
|
4132
|
+
}
|
|
4133
|
+
}
|
|
4134
|
+
return config;
|
|
4135
|
+
}
|
|
4136
|
+
function deserializeParticleSystem(json) {
|
|
4137
|
+
const parsed = JSON.parse(json);
|
|
4138
|
+
const { _version: _, ...raw } = parsed;
|
|
4139
|
+
return deserializeConfig(raw);
|
|
4140
|
+
}
|
|
4141
|
+
|
|
4142
|
+
export { CollisionPlaneMode, CurveFunctionId, EmitFrom, ForceFieldFalloff, ForceFieldType, LifeTimeCurve, RendererType, SCALAR_STRIDE, S_COLOR_A, S_COLOR_B, S_COLOR_G, S_COLOR_R, S_IS_ACTIVE, S_LIFETIME, S_ROTATION, S_SIZE, S_START_FRAME, S_START_LIFETIME, Shape, SimulationBackend, SimulationSpace, SubEmitterTrigger, TimeMode, applyModifiers, blendingMap, calculateRandomPositionAndVelocityOnBox, calculateRandomPositionAndVelocityOnCircle, calculateRandomPositionAndVelocityOnCone, calculateRandomPositionAndVelocityOnRectangle, calculateRandomPositionAndVelocityOnSphere, calculateValue, createBezierCurveFunction, createDefaultMeshTexture, createDefaultParticleTexture, createParticleSystem, curveFunctionIdMap, deserializeParticleSystem, getBezierCacheSize, getCurveFunction, getCurveFunctionFromConfig, getDefaultParticleSystemConfig, isComputeCapableRenderer, isLifeTimeCurve, registerTSLMaterialFactory, removeBezierCurveFunction, resolveSimulationBackend, serializeParticleSystem, updateParticleSystems };
|
|
3497
4143
|
//# sourceMappingURL=index.js.map
|
|
3498
4144
|
//# sourceMappingURL=index.js.map
|