@newkrok/three-particles 2.9.0 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/index.d.ts +134 -1
- package/dist/index.js +154 -48
- 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/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,6 +16,9 @@ Particle system for ThreeJS.
|
|
|
16
16
|
* Visual editor for creating and fine-tuning effects: [THREE Particles Editor](https://github.com/NewKrok/three-particles-editor)
|
|
17
17
|
* Highly customizable particle properties (position, velocity, size, color, alpha, rotation, etc.).
|
|
18
18
|
* Support for various emitter shapes and parameters.
|
|
19
|
+
* Force fields and attractors for dynamic particle behavior (point attraction/repulsion, directional wind).
|
|
20
|
+
* Sub-emitters triggered on particle birth or death events.
|
|
21
|
+
* Serialization support for saving and loading particle system configs.
|
|
19
22
|
* TypeDoc API documentation available.
|
|
20
23
|
|
|
21
24
|
# Live Demo & Examples
|
package/dist/index.d.ts
CHANGED
|
@@ -133,6 +133,45 @@ declare const enum SubEmitterTrigger {
|
|
|
133
133
|
*/
|
|
134
134
|
DEATH = "DEATH"
|
|
135
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Defines the type of force field that affects particles.
|
|
138
|
+
*
|
|
139
|
+
* @enum {string}
|
|
140
|
+
*/
|
|
141
|
+
declare const enum ForceFieldType {
|
|
142
|
+
/**
|
|
143
|
+
* Attract or repel particles toward/from a point in space.
|
|
144
|
+
* Positive strength attracts, negative strength repels.
|
|
145
|
+
* Configure with position, strength, range, and falloff.
|
|
146
|
+
*/
|
|
147
|
+
POINT = "POINT",
|
|
148
|
+
/**
|
|
149
|
+
* Apply a constant directional force to all particles (like wind).
|
|
150
|
+
* Configure with direction and strength.
|
|
151
|
+
*/
|
|
152
|
+
DIRECTIONAL = "DIRECTIONAL"
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Defines how force diminishes with distance from a POINT force field center.
|
|
156
|
+
* Only applicable to {@link ForceFieldType.POINT} force fields.
|
|
157
|
+
*
|
|
158
|
+
* @enum {string}
|
|
159
|
+
*/
|
|
160
|
+
declare const enum ForceFieldFalloff {
|
|
161
|
+
/**
|
|
162
|
+
* No falloff — force is constant within range.
|
|
163
|
+
*/
|
|
164
|
+
NONE = "NONE",
|
|
165
|
+
/**
|
|
166
|
+
* Force decreases linearly with distance: `1 - d/range`.
|
|
167
|
+
*/
|
|
168
|
+
LINEAR = "LINEAR",
|
|
169
|
+
/**
|
|
170
|
+
* Force decreases with the square of distance: `1 - (d/range)²`.
|
|
171
|
+
* More physically realistic than linear falloff.
|
|
172
|
+
*/
|
|
173
|
+
QUADRATIC = "QUADRATIC"
|
|
174
|
+
}
|
|
136
175
|
|
|
137
176
|
/**
|
|
138
177
|
* A fixed numerical value.
|
|
@@ -753,6 +792,78 @@ type SubEmitterConfig = {
|
|
|
753
792
|
*/
|
|
754
793
|
maxInstances?: number;
|
|
755
794
|
};
|
|
795
|
+
/**
|
|
796
|
+
* Configuration for a force field that affects particle velocities.
|
|
797
|
+
* Force fields can attract, repel, or push particles in a direction.
|
|
798
|
+
*
|
|
799
|
+
* @example
|
|
800
|
+
* ```typescript
|
|
801
|
+
* // Point attractor at origin
|
|
802
|
+
* const attractor: ForceFieldConfig = {
|
|
803
|
+
* type: ForceFieldType.POINT,
|
|
804
|
+
* position: new THREE.Vector3(0, 0, 0),
|
|
805
|
+
* strength: 5.0,
|
|
806
|
+
* range: 10,
|
|
807
|
+
* falloff: ForceFieldFalloff.QUADRATIC,
|
|
808
|
+
* };
|
|
809
|
+
*
|
|
810
|
+
* // Repulsion shield
|
|
811
|
+
* const shield: ForceFieldConfig = {
|
|
812
|
+
* type: ForceFieldType.POINT,
|
|
813
|
+
* position: new THREE.Vector3(0, 0, 0),
|
|
814
|
+
* strength: -3.0,
|
|
815
|
+
* range: 5,
|
|
816
|
+
* falloff: ForceFieldFalloff.LINEAR,
|
|
817
|
+
* };
|
|
818
|
+
*
|
|
819
|
+
* // Wind effect
|
|
820
|
+
* const wind: ForceFieldConfig = {
|
|
821
|
+
* type: ForceFieldType.DIRECTIONAL,
|
|
822
|
+
* direction: new THREE.Vector3(1, 0, 0),
|
|
823
|
+
* strength: 2.0,
|
|
824
|
+
* };
|
|
825
|
+
* ```
|
|
826
|
+
*/
|
|
827
|
+
type ForceFieldConfig = {
|
|
828
|
+
/** Whether this force field is active. @default true */
|
|
829
|
+
isActive?: boolean;
|
|
830
|
+
/** Type of the force field. @default ForceFieldType.POINT */
|
|
831
|
+
type?: ForceFieldType;
|
|
832
|
+
/** Position in 3D space for POINT type force fields. @default (0,0,0) */
|
|
833
|
+
position?: THREE.Vector3;
|
|
834
|
+
/** Direction vector for DIRECTIONAL type force fields. @default (0,1,0) */
|
|
835
|
+
direction?: THREE.Vector3;
|
|
836
|
+
/**
|
|
837
|
+
* Force strength. Positive = attract (POINT) or push along direction (DIRECTIONAL).
|
|
838
|
+
* Negative = repel (POINT) or push against direction (DIRECTIONAL).
|
|
839
|
+
* Supports constant, random range, or lifetime curve (evaluated against system lifetime).
|
|
840
|
+
* @default 1
|
|
841
|
+
*/
|
|
842
|
+
strength?: Constant | RandomBetweenTwoConstants | LifetimeCurve;
|
|
843
|
+
/**
|
|
844
|
+
* Maximum effective range for POINT type. Particles beyond this distance are unaffected.
|
|
845
|
+
* @default Infinity
|
|
846
|
+
*/
|
|
847
|
+
range?: number;
|
|
848
|
+
/**
|
|
849
|
+
* How force diminishes with distance for POINT type.
|
|
850
|
+
* @default ForceFieldFalloff.LINEAR
|
|
851
|
+
*/
|
|
852
|
+
falloff?: ForceFieldFalloff;
|
|
853
|
+
};
|
|
854
|
+
/**
|
|
855
|
+
* Internal normalized force field configuration where all properties are required.
|
|
856
|
+
* Created during particle system initialization from user-provided {@link ForceFieldConfig}.
|
|
857
|
+
*/
|
|
858
|
+
type NormalizedForceFieldConfig = {
|
|
859
|
+
isActive: boolean;
|
|
860
|
+
type: ForceFieldType;
|
|
861
|
+
position: THREE.Vector3;
|
|
862
|
+
direction: THREE.Vector3;
|
|
863
|
+
strength: Constant | RandomBetweenTwoConstants | LifetimeCurve;
|
|
864
|
+
range: number;
|
|
865
|
+
falloff: ForceFieldFalloff;
|
|
866
|
+
};
|
|
756
867
|
/**
|
|
757
868
|
* Configuration object for the particle system.
|
|
758
869
|
* Defines all aspects of the particle system, including its appearance, behavior, and runtime events.
|
|
@@ -1256,6 +1367,27 @@ type ParticleSystemConfig = {
|
|
|
1256
1367
|
* ```
|
|
1257
1368
|
*/
|
|
1258
1369
|
subEmitters?: Array<SubEmitterConfig>;
|
|
1370
|
+
/**
|
|
1371
|
+
* Force fields that affect particle velocities.
|
|
1372
|
+
* Each force field can attract, repel, or push particles in a direction.
|
|
1373
|
+
* Multiple force fields are applied cumulatively.
|
|
1374
|
+
*
|
|
1375
|
+
* @default []
|
|
1376
|
+
*
|
|
1377
|
+
* @example
|
|
1378
|
+
* ```typescript
|
|
1379
|
+
* forceFields: [
|
|
1380
|
+
* {
|
|
1381
|
+
* type: ForceFieldType.POINT,
|
|
1382
|
+
* position: new THREE.Vector3(0, 0, 0),
|
|
1383
|
+
* strength: 5.0,
|
|
1384
|
+
* range: 10,
|
|
1385
|
+
* falloff: ForceFieldFalloff.QUADRATIC,
|
|
1386
|
+
* },
|
|
1387
|
+
* ]
|
|
1388
|
+
* ```
|
|
1389
|
+
*/
|
|
1390
|
+
forceFields?: Array<ForceFieldConfig>;
|
|
1259
1391
|
/**
|
|
1260
1392
|
* Called on every update frame with particle system data.
|
|
1261
1393
|
*/
|
|
@@ -1345,6 +1477,7 @@ type ParticleSystemInstance = {
|
|
|
1345
1477
|
looping: boolean;
|
|
1346
1478
|
simulationSpace: SimulationSpace;
|
|
1347
1479
|
gravity: number;
|
|
1480
|
+
normalizedForceFields: Array<NormalizedForceFieldConfig>;
|
|
1348
1481
|
emission: Emission;
|
|
1349
1482
|
normalizedConfig: NormalizedParticleSystemConfig;
|
|
1350
1483
|
iterationCount: number;
|
|
@@ -1852,4 +1985,4 @@ declare const getDefaultParticleSystemConfig: () => any;
|
|
|
1852
1985
|
declare const createParticleSystem: (config?: ParticleSystemConfig, externalNow?: number) => ParticleSystem;
|
|
1853
1986
|
declare const updateParticleSystems: (cycleData: CycleData) => void;
|
|
1854
1987
|
|
|
1855
|
-
export { type BezierCurve, type BezierPoint, type Box, type Burst, type BurstState, type Circle, type Cone, type Constant, type CurveBase, type CurveFunction, CurveFunctionId, type CycleData, type EasingCurve, type Emission, EmitFrom, type GeneralData, LifeTimeCurve, type LifetimeCurve, type MinMaxColor, type Noise, type NoiseConfig, type NormalizedParticleSystemConfig, type ParticleSystem, type ParticleSystemConfig, type ParticleSystemInstance, type Point3D, type RandomBetweenTwoConstants, type Rectangle, type Renderer, type Rgb, Shape, type ShapeConfig, SimulationSpace, type Sphere, type SubEmitterConfig, SubEmitterTrigger, type TextureSheetAnimation, TimeMode, type Transform, type VelocityOverLifetime, applyModifiers, blendingMap, calculateRandomPositionAndVelocityOnBox, calculateRandomPositionAndVelocityOnCircle, calculateRandomPositionAndVelocityOnCone, calculateRandomPositionAndVelocityOnRectangle, calculateRandomPositionAndVelocityOnSphere, calculateValue, createBezierCurveFunction, createDefaultParticleTexture, createParticleSystem, curveFunctionIdMap, getBezierCacheSize, getCurveFunction, getCurveFunctionFromConfig, getDefaultParticleSystemConfig, isLifeTimeCurve, removeBezierCurveFunction, updateParticleSystems };
|
|
1988
|
+
export { type BezierCurve, type BezierPoint, type Box, type Burst, type BurstState, type Circle, type Cone, type Constant, type CurveBase, type CurveFunction, CurveFunctionId, type CycleData, type EasingCurve, type Emission, EmitFrom, type ForceFieldConfig, ForceFieldFalloff, ForceFieldType, type GeneralData, LifeTimeCurve, type LifetimeCurve, type MinMaxColor, type Noise, type NoiseConfig, type NormalizedForceFieldConfig, type NormalizedParticleSystemConfig, type ParticleSystem, type ParticleSystemConfig, type ParticleSystemInstance, type Point3D, type RandomBetweenTwoConstants, type Rectangle, type Renderer, type Rgb, Shape, type ShapeConfig, SimulationSpace, type Sphere, type SubEmitterConfig, SubEmitterTrigger, type TextureSheetAnimation, TimeMode, type Transform, type VelocityOverLifetime, applyModifiers, blendingMap, calculateRandomPositionAndVelocityOnBox, calculateRandomPositionAndVelocityOnCircle, calculateRandomPositionAndVelocityOnCone, calculateRandomPositionAndVelocityOnRectangle, calculateRandomPositionAndVelocityOnSphere, calculateValue, createBezierCurveFunction, createDefaultParticleTexture, createParticleSystem, curveFunctionIdMap, getBezierCacheSize, getCurveFunction, getCurveFunctionFromConfig, getDefaultParticleSystemConfig, isLifeTimeCurve, removeBezierCurveFunction, updateParticleSystems };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Easing from 'easing-functions';
|
|
2
|
-
import * as
|
|
2
|
+
import * as THREE4 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';
|
|
@@ -165,6 +165,17 @@ var SubEmitterTrigger = /* @__PURE__ */ ((SubEmitterTrigger2) => {
|
|
|
165
165
|
SubEmitterTrigger2["DEATH"] = "DEATH";
|
|
166
166
|
return SubEmitterTrigger2;
|
|
167
167
|
})(SubEmitterTrigger || {});
|
|
168
|
+
var ForceFieldType = /* @__PURE__ */ ((ForceFieldType2) => {
|
|
169
|
+
ForceFieldType2["POINT"] = "POINT";
|
|
170
|
+
ForceFieldType2["DIRECTIONAL"] = "DIRECTIONAL";
|
|
171
|
+
return ForceFieldType2;
|
|
172
|
+
})(ForceFieldType || {});
|
|
173
|
+
var ForceFieldFalloff = /* @__PURE__ */ ((ForceFieldFalloff2) => {
|
|
174
|
+
ForceFieldFalloff2["NONE"] = "NONE";
|
|
175
|
+
ForceFieldFalloff2["LINEAR"] = "LINEAR";
|
|
176
|
+
ForceFieldFalloff2["QUADRATIC"] = "QUADRATIC";
|
|
177
|
+
return ForceFieldFalloff2;
|
|
178
|
+
})(ForceFieldFalloff || {});
|
|
168
179
|
var calculateRandomPositionAndVelocityOnSphere = (position, quaternion, velocity, speed, {
|
|
169
180
|
radius,
|
|
170
181
|
radiusThickness,
|
|
@@ -209,7 +220,7 @@ var calculateRandomPositionAndVelocityOnCone = (position, quaternion, velocity,
|
|
|
209
220
|
position.applyQuaternion(quaternion);
|
|
210
221
|
const positionLength = position.length();
|
|
211
222
|
const normalizedAngle = Math.abs(
|
|
212
|
-
positionLength / radius *
|
|
223
|
+
positionLength / radius * THREE4.MathUtils.degToRad(angle)
|
|
213
224
|
);
|
|
214
225
|
const sinNormalizedAngle = Math.sin(normalizedAngle);
|
|
215
226
|
const speedMultiplierByPosition = 1 / positionLength;
|
|
@@ -284,8 +295,8 @@ var calculateRandomPositionAndVelocityOnRectangle = (position, quaternion, veloc
|
|
|
284
295
|
const _rotation = rotation;
|
|
285
296
|
const xOffset = Math.random() * _scale.x - _scale.x / 2;
|
|
286
297
|
const yOffset = Math.random() * _scale.y - _scale.y / 2;
|
|
287
|
-
const rotationX =
|
|
288
|
-
const rotationY =
|
|
298
|
+
const rotationX = THREE4.MathUtils.degToRad(_rotation.x);
|
|
299
|
+
const rotationY = THREE4.MathUtils.degToRad(_rotation.y);
|
|
289
300
|
position.x = xOffset * Math.cos(rotationY);
|
|
290
301
|
position.y = yOffset * Math.cos(rotationX);
|
|
291
302
|
position.z = xOffset * Math.sin(rotationY) - yOffset * Math.sin(rotationX);
|
|
@@ -308,7 +319,7 @@ var createDefaultParticleTexture = () => {
|
|
|
308
319
|
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
|
|
309
320
|
context.fillStyle = "white";
|
|
310
321
|
context.fill();
|
|
311
|
-
const texture = new
|
|
322
|
+
const texture = new THREE4.CanvasTexture(canvas);
|
|
312
323
|
texture.needsUpdate = true;
|
|
313
324
|
return texture;
|
|
314
325
|
} else {
|
|
@@ -345,15 +356,15 @@ var calculateValue = (particleSystemId, value, time = 0) => {
|
|
|
345
356
|
if (value.min === value.max) {
|
|
346
357
|
return value.min ?? 0;
|
|
347
358
|
}
|
|
348
|
-
return
|
|
359
|
+
return THREE4.MathUtils.randFloat(value.min ?? 0, value.max ?? 1);
|
|
349
360
|
}
|
|
350
361
|
const lifetimeCurve = value;
|
|
351
362
|
return getCurveFunctionFromConfig(particleSystemId, lifetimeCurve)(time) * (lifetimeCurve.scale ?? 1);
|
|
352
363
|
};
|
|
353
364
|
|
|
354
365
|
// src/js/effects/three-particles/three-particles-modifiers.ts
|
|
355
|
-
var noiseInput = new
|
|
356
|
-
var orbitalEuler = new
|
|
366
|
+
var noiseInput = new THREE4.Vector3(0, 0, 0);
|
|
367
|
+
var orbitalEuler = new THREE4.Euler();
|
|
357
368
|
var applyModifiers = ({
|
|
358
369
|
delta,
|
|
359
370
|
generalData,
|
|
@@ -590,12 +601,81 @@ var ParticleSystemVertexShader = `
|
|
|
590
601
|
}
|
|
591
602
|
`;
|
|
592
603
|
var particle_system_vertex_shader_glsl_default = ParticleSystemVertexShader;
|
|
604
|
+
var _forceDirection = new THREE4.Vector3();
|
|
605
|
+
var applyPointForce = (field, strength, velocity, positionArr, positionIndex, delta) => {
|
|
606
|
+
_forceDirection.set(
|
|
607
|
+
field.position.x - positionArr[positionIndex],
|
|
608
|
+
field.position.y - positionArr[positionIndex + 1],
|
|
609
|
+
field.position.z - positionArr[positionIndex + 2]
|
|
610
|
+
);
|
|
611
|
+
const distance = _forceDirection.length();
|
|
612
|
+
if (distance < 1e-4) return;
|
|
613
|
+
if (field.range !== Infinity && distance > field.range) return;
|
|
614
|
+
_forceDirection.divideScalar(distance);
|
|
615
|
+
let falloffMultiplier = 1;
|
|
616
|
+
if (field.range !== Infinity) {
|
|
617
|
+
const normalizedDistance = distance / field.range;
|
|
618
|
+
switch (field.falloff) {
|
|
619
|
+
case "LINEAR" /* LINEAR */:
|
|
620
|
+
falloffMultiplier = 1 - normalizedDistance;
|
|
621
|
+
break;
|
|
622
|
+
case "QUADRATIC" /* QUADRATIC */:
|
|
623
|
+
falloffMultiplier = 1 - normalizedDistance * normalizedDistance;
|
|
624
|
+
break;
|
|
625
|
+
case "NONE" /* NONE */:
|
|
626
|
+
falloffMultiplier = 1;
|
|
627
|
+
break;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
const force = strength * falloffMultiplier * delta;
|
|
631
|
+
velocity.x += _forceDirection.x * force;
|
|
632
|
+
velocity.y += _forceDirection.y * force;
|
|
633
|
+
velocity.z += _forceDirection.z * force;
|
|
634
|
+
};
|
|
635
|
+
var applyDirectionalForce = (field, strength, velocity, delta) => {
|
|
636
|
+
const force = strength * delta;
|
|
637
|
+
velocity.x += field.direction.x * force;
|
|
638
|
+
velocity.y += field.direction.y * force;
|
|
639
|
+
velocity.z += field.direction.z * force;
|
|
640
|
+
};
|
|
641
|
+
var applyForceFields = ({
|
|
642
|
+
particleSystemId,
|
|
643
|
+
forceFields,
|
|
644
|
+
velocity,
|
|
645
|
+
positionArr,
|
|
646
|
+
positionIndex,
|
|
647
|
+
delta,
|
|
648
|
+
systemLifetimePercentage
|
|
649
|
+
}) => {
|
|
650
|
+
for (let i = 0; i < forceFields.length; i++) {
|
|
651
|
+
const field = forceFields[i];
|
|
652
|
+
if (!field.isActive) continue;
|
|
653
|
+
const strength = calculateValue(
|
|
654
|
+
particleSystemId,
|
|
655
|
+
field.strength,
|
|
656
|
+
systemLifetimePercentage
|
|
657
|
+
);
|
|
658
|
+
if (strength === 0) continue;
|
|
659
|
+
if (field.type === "POINT" /* POINT */) {
|
|
660
|
+
applyPointForce(
|
|
661
|
+
field,
|
|
662
|
+
strength,
|
|
663
|
+
velocity,
|
|
664
|
+
positionArr,
|
|
665
|
+
positionIndex,
|
|
666
|
+
delta
|
|
667
|
+
);
|
|
668
|
+
} else if (field.type === "DIRECTIONAL" /* DIRECTIONAL */) {
|
|
669
|
+
applyDirectionalForce(field, strength, velocity, delta);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
};
|
|
593
673
|
|
|
594
674
|
// src/js/effects/three-particles/three-particles.ts
|
|
595
675
|
var _particleSystemId = 0;
|
|
596
676
|
var createdParticleSystems = [];
|
|
597
|
-
var _subEmitterPosition = new
|
|
598
|
-
var _lastWorldPositionSnapshot = new
|
|
677
|
+
var _subEmitterPosition = new THREE4.Vector3();
|
|
678
|
+
var _lastWorldPositionSnapshot = new THREE4.Vector3();
|
|
599
679
|
var _distanceStep = { x: 0, y: 0, z: 0 };
|
|
600
680
|
var _tempPosition = { x: 0, y: 0, z: 0 };
|
|
601
681
|
var _modifierParams = {
|
|
@@ -607,18 +687,18 @@ var _modifierParams = {
|
|
|
607
687
|
particleIndex: 0
|
|
608
688
|
};
|
|
609
689
|
var blendingMap = {
|
|
610
|
-
"THREE.NoBlending":
|
|
611
|
-
"THREE.NormalBlending":
|
|
612
|
-
"THREE.AdditiveBlending":
|
|
613
|
-
"THREE.SubtractiveBlending":
|
|
614
|
-
"THREE.MultiplyBlending":
|
|
690
|
+
"THREE.NoBlending": THREE4.NoBlending,
|
|
691
|
+
"THREE.NormalBlending": THREE4.NormalBlending,
|
|
692
|
+
"THREE.AdditiveBlending": THREE4.AdditiveBlending,
|
|
693
|
+
"THREE.SubtractiveBlending": THREE4.SubtractiveBlending,
|
|
694
|
+
"THREE.MultiplyBlending": THREE4.MultiplyBlending
|
|
615
695
|
};
|
|
616
696
|
var getDefaultParticleSystemConfig = () => JSON.parse(JSON.stringify(DEFAULT_PARTICLE_SYSTEM_CONFIG));
|
|
617
697
|
var DEFAULT_PARTICLE_SYSTEM_CONFIG = {
|
|
618
698
|
transform: {
|
|
619
|
-
position: new
|
|
620
|
-
rotation: new
|
|
621
|
-
scale: new
|
|
699
|
+
position: new THREE4.Vector3(),
|
|
700
|
+
rotation: new THREE4.Vector3(),
|
|
701
|
+
scale: new THREE4.Vector3(1, 1, 1)
|
|
622
702
|
},
|
|
623
703
|
duration: 5,
|
|
624
704
|
looping: true,
|
|
@@ -670,7 +750,7 @@ var DEFAULT_PARTICLE_SYSTEM_CONFIG = {
|
|
|
670
750
|
},
|
|
671
751
|
map: void 0,
|
|
672
752
|
renderer: {
|
|
673
|
-
blending:
|
|
753
|
+
blending: THREE4.NormalBlending,
|
|
674
754
|
discardBackgroundColor: false,
|
|
675
755
|
backgroundColorTolerance: 1,
|
|
676
756
|
backgroundColor: { r: 1, g: 1, b: 1 },
|
|
@@ -756,11 +836,12 @@ var DEFAULT_PARTICLE_SYSTEM_CONFIG = {
|
|
|
756
836
|
sizeAmount: 0
|
|
757
837
|
},
|
|
758
838
|
textureSheetAnimation: {
|
|
759
|
-
tiles: new
|
|
839
|
+
tiles: new THREE4.Vector2(1, 1),
|
|
760
840
|
timeMode: "LIFETIME" /* LIFETIME */,
|
|
761
841
|
fps: 30,
|
|
762
842
|
startFrame: 0
|
|
763
|
-
}
|
|
843
|
+
},
|
|
844
|
+
forceFields: []
|
|
764
845
|
};
|
|
765
846
|
var createFloat32Attributes = ({
|
|
766
847
|
geometry,
|
|
@@ -776,7 +857,7 @@ var createFloat32Attributes = ({
|
|
|
776
857
|
} else {
|
|
777
858
|
array.fill(factory);
|
|
778
859
|
}
|
|
779
|
-
geometry.setAttribute(propertyName, new
|
|
860
|
+
geometry.setAttribute(propertyName, new THREE4.BufferAttribute(array, 1));
|
|
780
861
|
};
|
|
781
862
|
var calculatePositionAndVelocity = (generalData, { shape, sphere, cone, circle, rectangle, box }, startSpeed, position, velocity) => {
|
|
782
863
|
const calculatedStartSpeed = calculateValue(
|
|
@@ -860,14 +941,14 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
860
941
|
particleSystemId: _particleSystemId++,
|
|
861
942
|
normalizedLifetimePercentage: 0,
|
|
862
943
|
distanceFromLastEmitByDistance: 0,
|
|
863
|
-
lastWorldPosition: new
|
|
864
|
-
currentWorldPosition: new
|
|
865
|
-
worldPositionChange: new
|
|
866
|
-
worldQuaternion: new
|
|
867
|
-
wrapperQuaternion: new
|
|
868
|
-
lastWorldQuaternion: new
|
|
869
|
-
worldEuler: new
|
|
870
|
-
gravityVelocity: new
|
|
944
|
+
lastWorldPosition: new THREE4.Vector3(-99999),
|
|
945
|
+
currentWorldPosition: new THREE4.Vector3(-99999),
|
|
946
|
+
worldPositionChange: new THREE4.Vector3(),
|
|
947
|
+
worldQuaternion: new THREE4.Quaternion(),
|
|
948
|
+
wrapperQuaternion: new THREE4.Quaternion(),
|
|
949
|
+
lastWorldQuaternion: new THREE4.Quaternion(-99999),
|
|
950
|
+
worldEuler: new THREE4.Euler(),
|
|
951
|
+
gravityVelocity: new THREE4.Vector3(0, 0, 0),
|
|
871
952
|
startValues: {},
|
|
872
953
|
linearVelocityData: void 0,
|
|
873
954
|
orbitalVelocityData: void 0,
|
|
@@ -911,17 +992,28 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
911
992
|
onUpdate,
|
|
912
993
|
onComplete,
|
|
913
994
|
textureSheetAnimation,
|
|
914
|
-
subEmitters
|
|
995
|
+
subEmitters,
|
|
996
|
+
forceFields: rawForceFields
|
|
915
997
|
} = normalizedConfig;
|
|
998
|
+
const toVector3 = (v, fallback) => v ? new THREE4.Vector3(v.x ?? 0, v.y ?? 0, v.z ?? 0) : fallback.clone();
|
|
999
|
+
const normalizedForceFields = (rawForceFields ?? []).map((ff) => ({
|
|
1000
|
+
isActive: ff.isActive ?? true,
|
|
1001
|
+
type: ff.type ?? "POINT" /* POINT */,
|
|
1002
|
+
position: toVector3(ff.position, new THREE4.Vector3(0, 0, 0)),
|
|
1003
|
+
direction: toVector3(ff.direction, new THREE4.Vector3(0, 1, 0)).normalize(),
|
|
1004
|
+
strength: ff.strength ?? 1,
|
|
1005
|
+
range: Math.max(0, ff.range ?? Infinity),
|
|
1006
|
+
falloff: ff.falloff ?? "LINEAR" /* LINEAR */
|
|
1007
|
+
}));
|
|
916
1008
|
if (typeof renderer?.blending === "string")
|
|
917
1009
|
renderer.blending = blendingMap[renderer.blending];
|
|
918
1010
|
const startPositions = Array.from(
|
|
919
1011
|
{ length: maxParticles },
|
|
920
|
-
() => new
|
|
1012
|
+
() => new THREE4.Vector3()
|
|
921
1013
|
);
|
|
922
1014
|
const velocities = Array.from(
|
|
923
1015
|
{ length: maxParticles },
|
|
924
|
-
() => new
|
|
1016
|
+
() => new THREE4.Vector3()
|
|
925
1017
|
);
|
|
926
1018
|
generalData.creationTimes = Array.from({ length: maxParticles }, () => 0);
|
|
927
1019
|
const freeList = Array.from(
|
|
@@ -932,7 +1024,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
932
1024
|
generalData.linearVelocityData = Array.from(
|
|
933
1025
|
{ length: maxParticles },
|
|
934
1026
|
() => ({
|
|
935
|
-
speed: new
|
|
1027
|
+
speed: new THREE4.Vector3(
|
|
936
1028
|
velocityOverLifetime.linear.x ? calculateValue(
|
|
937
1029
|
generalData.particleSystemId,
|
|
938
1030
|
velocityOverLifetime.linear.x,
|
|
@@ -968,7 +1060,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
968
1060
|
generalData.orbitalVelocityData = Array.from(
|
|
969
1061
|
{ length: maxParticles },
|
|
970
1062
|
() => ({
|
|
971
|
-
speed: new
|
|
1063
|
+
speed: new THREE4.Vector3(
|
|
972
1064
|
velocityOverLifetime.orbital.x ? calculateValue(
|
|
973
1065
|
generalData.particleSystemId,
|
|
974
1066
|
velocityOverLifetime.orbital.x,
|
|
@@ -999,7 +1091,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
999
1091
|
velocityOverLifetime.orbital.z
|
|
1000
1092
|
) : void 0
|
|
1001
1093
|
},
|
|
1002
|
-
positionOffset: new
|
|
1094
|
+
positionOffset: new THREE4.Vector3()
|
|
1003
1095
|
})
|
|
1004
1096
|
);
|
|
1005
1097
|
}
|
|
@@ -1037,7 +1129,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1037
1129
|
if (value.isActive)
|
|
1038
1130
|
generalData.lifetimeValues[key] = Array.from(
|
|
1039
1131
|
{ length: maxParticles },
|
|
1040
|
-
() =>
|
|
1132
|
+
() => THREE4.MathUtils.randFloat(value.min, value.max)
|
|
1041
1133
|
);
|
|
1042
1134
|
});
|
|
1043
1135
|
generalData.noise = {
|
|
@@ -1061,7 +1153,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1061
1153
|
probabilityPassed: false
|
|
1062
1154
|
}));
|
|
1063
1155
|
}
|
|
1064
|
-
const material = new
|
|
1156
|
+
const material = new THREE4.ShaderMaterial({
|
|
1065
1157
|
uniforms: {
|
|
1066
1158
|
elapsed: {
|
|
1067
1159
|
value: 0
|
|
@@ -1095,7 +1187,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1095
1187
|
depthTest: renderer.depthTest,
|
|
1096
1188
|
depthWrite: renderer.depthWrite
|
|
1097
1189
|
});
|
|
1098
|
-
const geometry = new
|
|
1190
|
+
const geometry = new THREE4.BufferGeometry();
|
|
1099
1191
|
for (let i = 0; i < maxParticles; i++)
|
|
1100
1192
|
calculatePositionAndVelocity(
|
|
1101
1193
|
generalData,
|
|
@@ -1112,7 +1204,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1112
1204
|
}
|
|
1113
1205
|
geometry.setAttribute(
|
|
1114
1206
|
"position",
|
|
1115
|
-
new
|
|
1207
|
+
new THREE4.BufferAttribute(positionArray, 3)
|
|
1116
1208
|
);
|
|
1117
1209
|
createFloat32Attributes({
|
|
1118
1210
|
geometry,
|
|
@@ -1249,7 +1341,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1249
1341
|
);
|
|
1250
1342
|
geometry.attributes.rotation.needsUpdate = true;
|
|
1251
1343
|
if (normalizedConfig.rotationOverLifetime.isActive)
|
|
1252
|
-
generalData.lifetimeValues.rotationOverLifetime[particleIndex] =
|
|
1344
|
+
generalData.lifetimeValues.rotationOverLifetime[particleIndex] = THREE4.MathUtils.randFloat(
|
|
1253
1345
|
normalizedConfig.rotationOverLifetime.min,
|
|
1254
1346
|
normalizedConfig.rotationOverLifetime.max
|
|
1255
1347
|
);
|
|
@@ -1333,7 +1425,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1333
1425
|
const cleanupCompletedInstances = (instances) => {
|
|
1334
1426
|
for (let i = instances.length - 1; i >= 0; i--) {
|
|
1335
1427
|
const sub = instances[i];
|
|
1336
|
-
const points = sub.instance instanceof
|
|
1428
|
+
const points = sub.instance instanceof THREE4.Points ? sub.instance : sub.instance.children[0];
|
|
1337
1429
|
const isActiveArr = points?.geometry?.attributes?.isActive?.array;
|
|
1338
1430
|
if (!isActiveArr) {
|
|
1339
1431
|
sub.dispose();
|
|
@@ -1368,7 +1460,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1368
1460
|
looping: false,
|
|
1369
1461
|
transform: {
|
|
1370
1462
|
...subConfig.config.transform,
|
|
1371
|
-
position: new
|
|
1463
|
+
position: new THREE4.Vector3(position.x, position.y, position.z)
|
|
1372
1464
|
},
|
|
1373
1465
|
...inheritVelocity > 0 ? {
|
|
1374
1466
|
startSpeed: (typeof subConfig.config.startSpeed === "number" ? subConfig.config.startSpeed : typeof subConfig.config.startSpeed === "object" && subConfig.config.startSpeed !== null && "min" in subConfig.config.startSpeed ? subConfig.config.startSpeed.min ?? 0 : 0) + velocity.length() * inheritVelocity
|
|
@@ -1381,11 +1473,11 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1381
1473
|
instances.push(subSystem);
|
|
1382
1474
|
}
|
|
1383
1475
|
};
|
|
1384
|
-
let particleSystem = new
|
|
1476
|
+
let particleSystem = new THREE4.Points(geometry, material);
|
|
1385
1477
|
particleSystem.position.copy(transform.position);
|
|
1386
|
-
particleSystem.rotation.x =
|
|
1387
|
-
particleSystem.rotation.y =
|
|
1388
|
-
particleSystem.rotation.z =
|
|
1478
|
+
particleSystem.rotation.x = THREE4.MathUtils.degToRad(transform.rotation.x);
|
|
1479
|
+
particleSystem.rotation.y = THREE4.MathUtils.degToRad(transform.rotation.y);
|
|
1480
|
+
particleSystem.rotation.z = THREE4.MathUtils.degToRad(transform.rotation.z);
|
|
1389
1481
|
particleSystem.scale.copy(transform.scale);
|
|
1390
1482
|
const calculatedCreationTime = now + calculateValue(generalData.particleSystemId, startDelay) * 1e3;
|
|
1391
1483
|
let wrapper;
|
|
@@ -1436,6 +1528,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1436
1528
|
looping,
|
|
1437
1529
|
simulationSpace,
|
|
1438
1530
|
gravity,
|
|
1531
|
+
normalizedForceFields,
|
|
1439
1532
|
emission,
|
|
1440
1533
|
normalizedConfig,
|
|
1441
1534
|
iterationCount: 0,
|
|
@@ -1491,9 +1584,11 @@ var updateParticleSystemInstance = (props, { now, delta, elapsed }) => {
|
|
|
1491
1584
|
activateParticle,
|
|
1492
1585
|
simulationSpace,
|
|
1493
1586
|
gravity,
|
|
1587
|
+
normalizedForceFields,
|
|
1494
1588
|
onParticleDeath,
|
|
1495
1589
|
onParticleBirth
|
|
1496
1590
|
} = props;
|
|
1591
|
+
const hasForceFields = normalizedForceFields.length > 0;
|
|
1497
1592
|
const lifetime = now - creationTime;
|
|
1498
1593
|
const normalizedLifetime = lifetime % (duration * 1e3);
|
|
1499
1594
|
generalData.normalizedLifetimePercentage = Math.max(
|
|
@@ -1562,6 +1657,17 @@ var updateParticleSystemInstance = (props, { now, delta, elapsed }) => {
|
|
|
1562
1657
|
velocity.x -= gravityVelocity.x * delta;
|
|
1563
1658
|
velocity.y -= gravityVelocity.y * delta;
|
|
1564
1659
|
velocity.z -= gravityVelocity.z * delta;
|
|
1660
|
+
if (hasForceFields) {
|
|
1661
|
+
applyForceFields({
|
|
1662
|
+
particleSystemId: generalData.particleSystemId,
|
|
1663
|
+
forceFields: normalizedForceFields,
|
|
1664
|
+
velocity,
|
|
1665
|
+
positionArr,
|
|
1666
|
+
positionIndex: index * 3,
|
|
1667
|
+
delta,
|
|
1668
|
+
systemLifetimePercentage: generalData.normalizedLifetimePercentage
|
|
1669
|
+
});
|
|
1670
|
+
}
|
|
1565
1671
|
if (gravity !== 0 || velocity.x !== 0 || velocity.y !== 0 || velocity.z !== 0 || worldPositionChange.x !== 0 || worldPositionChange.y !== 0 || worldPositionChange.z !== 0) {
|
|
1566
1672
|
const positionIndex = index * 3;
|
|
1567
1673
|
if (simulationSpace === "WORLD" /* WORLD */) {
|
|
@@ -1697,6 +1803,6 @@ var updateParticleSystems = (cycleData) => {
|
|
|
1697
1803
|
);
|
|
1698
1804
|
};
|
|
1699
1805
|
|
|
1700
|
-
export { CurveFunctionId, EmitFrom, LifeTimeCurve, Shape, SimulationSpace, SubEmitterTrigger, TimeMode, applyModifiers, blendingMap, calculateRandomPositionAndVelocityOnBox, calculateRandomPositionAndVelocityOnCircle, calculateRandomPositionAndVelocityOnCone, calculateRandomPositionAndVelocityOnRectangle, calculateRandomPositionAndVelocityOnSphere, calculateValue, createBezierCurveFunction, createDefaultParticleTexture, createParticleSystem, curveFunctionIdMap, getBezierCacheSize, getCurveFunction, getCurveFunctionFromConfig, getDefaultParticleSystemConfig, isLifeTimeCurve, removeBezierCurveFunction, updateParticleSystems };
|
|
1806
|
+
export { CurveFunctionId, EmitFrom, ForceFieldFalloff, ForceFieldType, LifeTimeCurve, Shape, SimulationSpace, SubEmitterTrigger, TimeMode, applyModifiers, blendingMap, calculateRandomPositionAndVelocityOnBox, calculateRandomPositionAndVelocityOnCircle, calculateRandomPositionAndVelocityOnCone, calculateRandomPositionAndVelocityOnRectangle, calculateRandomPositionAndVelocityOnSphere, calculateValue, createBezierCurveFunction, createDefaultParticleTexture, createParticleSystem, curveFunctionIdMap, getBezierCacheSize, getCurveFunction, getCurveFunctionFromConfig, getDefaultParticleSystemConfig, isLifeTimeCurve, removeBezierCurveFunction, updateParticleSystems };
|
|
1701
1807
|
//# sourceMappingURL=index.js.map
|
|
1702
1808
|
//# sourceMappingURL=index.js.map
|