@rzmps/rzmps 1.0.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.
Files changed (133) hide show
  1. package/README.md +1048 -0
  2. package/build/EmissionShape.d.ts +33 -0
  3. package/build/EmissionShape.js +129 -0
  4. package/build/Emitter.d.ts +58 -0
  5. package/build/Emitter.js +166 -0
  6. package/build/GpuModule.d.ts +28 -0
  7. package/build/GpuModule.js +28 -0
  8. package/build/Module.d.ts +19 -0
  9. package/build/Module.js +31 -0
  10. package/build/Particle.d.ts +60 -0
  11. package/build/Particle.js +52 -0
  12. package/build/ParticleForceField.d.ts +39 -0
  13. package/build/ParticleForceField.js +101 -0
  14. package/build/ParticleForceFieldHelper.d.ts +18 -0
  15. package/build/ParticleForceFieldHelper.js +103 -0
  16. package/build/ParticleSystem.d.ts +122 -0
  17. package/build/ParticleSystem.js +609 -0
  18. package/build/Renderer.d.ts +15 -0
  19. package/build/Renderer.js +11 -0
  20. package/build/assets/images/default.png +0 -0
  21. package/build/collision/ThreeCollisionBackend.d.ts +47 -0
  22. package/build/collision/ThreeCollisionBackend.js +340 -0
  23. package/build/enums/Axis.d.ts +6 -0
  24. package/build/enums/Axis.js +7 -0
  25. package/build/enums/DynamicValueType.d.ts +6 -0
  26. package/build/enums/DynamicValueType.js +7 -0
  27. package/build/enums/EmissionSource copy.d.ts +7 -0
  28. package/build/enums/EmissionSource copy.js +7 -0
  29. package/build/enums/EmissionSource.d.ts +7 -0
  30. package/build/enums/EmissionSource.js +7 -0
  31. package/build/enums/EndBehavior.d.ts +6 -0
  32. package/build/enums/EndBehavior.js +7 -0
  33. package/build/enums/SimulationSpace.d.ts +5 -0
  34. package/build/enums/SimulationSpace.js +6 -0
  35. package/build/enums/SpriteMaterialType.d.ts +5 -0
  36. package/build/enums/SpriteMaterialType.js +6 -0
  37. package/build/enums/TagSelectionMethod.d.ts +6 -0
  38. package/build/enums/TagSelectionMethod.js +7 -0
  39. package/build/enums/TrailMode copy.d.ts +5 -0
  40. package/build/enums/TrailMode copy.js +7 -0
  41. package/build/enums/TrailMode.d.ts +5 -0
  42. package/build/enums/TrailMode.js +7 -0
  43. package/build/enums/TrailTextureMode.d.ts +7 -0
  44. package/build/enums/TrailTextureMode.js +9 -0
  45. package/build/gpu/GpuDynamicValue.d.ts +9 -0
  46. package/build/gpu/GpuDynamicValue.js +113 -0
  47. package/build/gpu/GpuMath.d.ts +3 -0
  48. package/build/gpu/GpuMath.js +12 -0
  49. package/build/gpu/GpuParticleContext.d.ts +63 -0
  50. package/build/gpu/GpuParticleContext.js +291 -0
  51. package/build/helpers/acceptMultiple.d.ts +2 -0
  52. package/build/helpers/acceptMultiple.js +6 -0
  53. package/build/helpers/evaluateDynamic.d.ts +2 -0
  54. package/build/helpers/evaluateDynamic.js +18 -0
  55. package/build/helpers/evaluateDynamicColor.d.ts +3 -0
  56. package/build/helpers/evaluateDynamicColor.js +5 -0
  57. package/build/helpers/evaluateDynamicNumber.d.ts +2 -0
  58. package/build/helpers/evaluateDynamicNumber.js +4 -0
  59. package/build/helpers/evaluateDynamicVector3.d.ts +3 -0
  60. package/build/helpers/evaluateDynamicVector3.js +5 -0
  61. package/build/helpers/isPointInMesh.d.ts +2 -0
  62. package/build/helpers/isPointInMesh.js +8 -0
  63. package/build/helpers/particleRatio.d.ts +2 -0
  64. package/build/helpers/particleRatio.js +13 -0
  65. package/build/helpers/tagsIntersect.d.ts +2 -0
  66. package/build/helpers/tagsIntersect.js +4 -0
  67. package/build/index.d.ts +37 -0
  68. package/build/index.js +34 -0
  69. package/build/interfaces/ICollisionBackend.d.ts +21 -0
  70. package/build/interfaces/ICollisionBackend.js +1 -0
  71. package/build/interfaces/IParticleForceField.d.ts +5 -0
  72. package/build/interfaces/IParticleForceField.js +1 -0
  73. package/build/interfaces/InitialParticleValues.d.ts +18 -0
  74. package/build/interfaces/InitialParticleValues.js +1 -0
  75. package/build/materials/BasicSprite.d.ts +21 -0
  76. package/build/materials/BasicSprite.js +46 -0
  77. package/build/materials/UnlitSprite.d.ts +13 -0
  78. package/build/materials/UnlitSprite.js +31 -0
  79. package/build/materials/WebGPUBasicSprite.d.ts +8 -0
  80. package/build/materials/WebGPUBasicSprite.js +65 -0
  81. package/build/materials/WebGPUUnlitSprite.d.ts +8 -0
  82. package/build/materials/WebGPUUnlitSprite.js +49 -0
  83. package/build/modules/Audio.d.ts +60 -0
  84. package/build/modules/Audio.js +181 -0
  85. package/build/modules/Collision.d.ts +40 -0
  86. package/build/modules/Collision.js +162 -0
  87. package/build/modules/ColorBySpeed.d.ts +18 -0
  88. package/build/modules/ColorBySpeed.js +26 -0
  89. package/build/modules/ColorOverLifetime.d.ts +12 -0
  90. package/build/modules/ColorOverLifetime.js +17 -0
  91. package/build/modules/ExternalForces.d.ts +21 -0
  92. package/build/modules/ExternalForces.js +61 -0
  93. package/build/modules/ForceOverLifetime.d.ts +11 -0
  94. package/build/modules/ForceOverLifetime.js +12 -0
  95. package/build/modules/LimitVelocityOverLifetime.d.ts +16 -0
  96. package/build/modules/LimitVelocityOverLifetime.js +34 -0
  97. package/build/modules/MassOverLifetime.d.ts +11 -0
  98. package/build/modules/MassOverLifetime.js +15 -0
  99. package/build/modules/NoiseModule.d.ts +23 -0
  100. package/build/modules/NoiseModule.js +45 -0
  101. package/build/modules/RotationBySpeed.d.ts +14 -0
  102. package/build/modules/RotationBySpeed.js +19 -0
  103. package/build/modules/RotationOverLifetime.d.ts +11 -0
  104. package/build/modules/RotationOverLifetime.js +12 -0
  105. package/build/modules/ScaleBySpeed.d.ts +14 -0
  106. package/build/modules/ScaleBySpeed.js +19 -0
  107. package/build/modules/ScaleOverLifetime.d.ts +11 -0
  108. package/build/modules/ScaleOverLifetime.js +11 -0
  109. package/build/modules/TransformByNoise.d.ts +17 -0
  110. package/build/modules/TransformByNoise.js +32 -0
  111. package/build/modules/VelocityOverLifetime.d.ts +15 -0
  112. package/build/modules/VelocityOverLifetime.js +32 -0
  113. package/build/renderers/LightRenderer.d.ts +54 -0
  114. package/build/renderers/LightRenderer.js +141 -0
  115. package/build/renderers/MeshRenderer.d.ts +27 -0
  116. package/build/renderers/MeshRenderer.js +70 -0
  117. package/build/renderers/SpriteRenderer.d.ts +95 -0
  118. package/build/renderers/SpriteRenderer.js +456 -0
  119. package/build/renderers/TrailRenderer.d.ts +71 -0
  120. package/build/renderers/TrailRenderer.js +400 -0
  121. package/build/shaders/BasicSprite.frag.js +1 -0
  122. package/build/shaders/BasicSprite.vert.js +1 -0
  123. package/build/shaders/UnlitSprite.frag.js +1 -0
  124. package/build/shaders/UnlitSprite.vert.js +1 -0
  125. package/build/types/DynamicValue.d.ts +2 -0
  126. package/build/types/DynamicValue.js +1 -0
  127. package/build/types/EnumStringLiteral.d.ts +1 -0
  128. package/build/types/EnumStringLiteral.js +1 -0
  129. package/build/types/Multiple.d.ts +2 -0
  130. package/build/types/Multiple.js +1 -0
  131. package/build/types/Tag.d.ts +1 -0
  132. package/build/types/Tag.js +1 -0
  133. package/package.json +39 -0
@@ -0,0 +1,162 @@
1
+ import * as THREE from 'three';
2
+ import Module from '../Module';
3
+ import evaluateDynamicNumber from '../helpers/evaluateDynamicNumber';
4
+ import ThreeCollisionBackend from '../collision/ThreeCollisionBackend';
5
+ const ACTIVE_COLLISION_BACKEND_KEY = "__rzmps_activeCollisionBackend";
6
+ const PREVIOUS_POSITION_KEY = "__rzmps_collision_prevPosition";
7
+ class Collision extends Module {
8
+ constructor(options = {}) {
9
+ var _a, _b, _c, _d, _e, _f, _g;
10
+ // Priority > 0, occurs after movement
11
+ super((particle) => this.collide(particle), Object.assign(Object.assign({}, options), { priority: 1 }));
12
+ this.dampen = 0;
13
+ this.bounce = 1;
14
+ this.lifetimeLoss = 0;
15
+ this.applyImpulses = false;
16
+ this.radiusScale = 1;
17
+ this.minKillSpeed = 0;
18
+ this.maxKillSpeed = Number.POSITIVE_INFINITY;
19
+ this.collisionListeners = [];
20
+ // Priority < 0, cache position before movement
21
+ this.dependents = [
22
+ new Module((particle) => particle.data[PREVIOUS_POSITION_KEY] = particle.position.clone(), Object.assign(Object.assign({}, options), { priority: -1 }))
23
+ ];
24
+ this.dampen = (_a = options.dampen) !== null && _a !== void 0 ? _a : this.dampen;
25
+ this.bounce = (_b = options.bounce) !== null && _b !== void 0 ? _b : this.bounce;
26
+ this.lifetimeLoss = (_c = options.lifetimeLoss) !== null && _c !== void 0 ? _c : this.lifetimeLoss;
27
+ this.applyImpulses = (_d = options.applyImpulses) !== null && _d !== void 0 ? _d : this.applyImpulses;
28
+ this.radiusScale = (_e = options.radiusScale) !== null && _e !== void 0 ? _e : this.radiusScale;
29
+ this.minKillSpeed = (_f = options.minKillSpeed) !== null && _f !== void 0 ? _f : this.minKillSpeed;
30
+ this.maxKillSpeed = (_g = options.maxKillSpeed) !== null && _g !== void 0 ? _g : this.maxKillSpeed;
31
+ if (options.onCollision)
32
+ this.collisionListeners.push(options.onCollision);
33
+ }
34
+ onCollision(listener) {
35
+ this.collisionListeners.push(listener);
36
+ }
37
+ removeCollisionListener(listener) {
38
+ this.collisionListeners = this.collisionListeners.filter(l => l !== listener);
39
+ }
40
+ prepare(system, deltaTime) {
41
+ var _a, _b;
42
+ this._system = system;
43
+ if (system.scene) {
44
+ // Check if backend exists or needs to be updated
45
+ const cachedBackend = system.scene.userData[ACTIVE_COLLISION_BACKEND_KEY];
46
+ if (!this.backend || this.backend != cachedBackend) {
47
+ this.backend = cachedBackend !== null && cachedBackend !== void 0 ? cachedBackend : new ThreeCollisionBackend({ world: system.scene });
48
+ system.scene.userData[ACTIVE_COLLISION_BACKEND_KEY] =
49
+ this.backend;
50
+ }
51
+ }
52
+ (_b = (_a = this.backend) === null || _a === void 0 ? void 0 : _a.update) === null || _b === void 0 ? void 0 : _b.call(_a, deltaTime);
53
+ }
54
+ collide(particle) {
55
+ if (!this.backend || !this._system)
56
+ return;
57
+ const startPosition = particle.data[PREVIOUS_POSITION_KEY];
58
+ const endPosition = particle.position;
59
+ if (startPosition.equals(endPosition))
60
+ return;
61
+ this._system.updateWorldMatrix(true, false);
62
+ const start = this._system.simulationSpace === 'world'
63
+ ? startPosition.clone()
64
+ : this._system.localToWorld(startPosition.clone());
65
+ const end = this._system.simulationSpace === 'world'
66
+ ? endPosition.clone()
67
+ : this._system.localToWorld(endPosition.clone());
68
+ const radius = this.getParticleRadius(particle);
69
+ const hit = this.backend.collide({
70
+ particle,
71
+ start,
72
+ end,
73
+ radius,
74
+ });
75
+ if (!hit)
76
+ return;
77
+ // Collision callbacks
78
+ this.collisionListeners.forEach((listener) => listener(particle, hit));
79
+ this._system.notifyCollision(particle, hit);
80
+ if (this._system.simulationSpace === 'local') {
81
+ const inverseWorld = this._system.matrixWorld.clone().invert();
82
+ hit.point = this._system.worldToLocal(hit.point.clone());
83
+ if (hit.position) {
84
+ hit.position = this._system.worldToLocal(hit.position.clone());
85
+ }
86
+ hit.normal = hit.normal
87
+ .clone()
88
+ .transformDirection(inverseWorld)
89
+ .normalize();
90
+ }
91
+ this.resolvePosition(particle, hit, radius);
92
+ // Store previous veolocity for impulses
93
+ const incomingVelocity = particle.velocity.clone();
94
+ this.resolveVelocity(particle, hit);
95
+ this.resolveLifetime(particle);
96
+ if (particle.mass > 0
97
+ && this.applyImpulses
98
+ && this.backend.applyImpulse) {
99
+ const impulse = particle.velocity
100
+ .clone()
101
+ .sub(incomingVelocity)
102
+ .multiplyScalar(-particle.mass);
103
+ this.backend.applyImpulse(hit, impulse);
104
+ }
105
+ const speed = particle.velocity.length();
106
+ if (speed < this.minKillSpeed
107
+ || speed > this.maxKillSpeed) {
108
+ this.killParticle(particle);
109
+ }
110
+ }
111
+ resolvePosition(particle, hit, radius) {
112
+ if (hit.position) {
113
+ particle.position.copy(hit.position);
114
+ return;
115
+ }
116
+ particle.position
117
+ .copy(hit.point)
118
+ .addScaledVector(hit.normal, radius);
119
+ }
120
+ resolveVelocity(particle, hit) {
121
+ var _a, _b;
122
+ const normal = hit.normal.clone().normalize();
123
+ const bounce = THREE.MathUtils.clamp(evaluateDynamicNumber((_a = this.bounce) !== null && _a !== void 0 ? _a : 1, particle.time, particle.id), 0, 1);
124
+ const dampen = THREE.MathUtils.clamp(evaluateDynamicNumber((_b = this.dampen) !== null && _b !== void 0 ? _b : 0, particle.time, particle.id), 0, 1);
125
+ const normalSpeed = particle.velocity.dot(normal);
126
+ /*
127
+ * Don't bounce if we're already travelling away
128
+ * from the surface.
129
+ */
130
+ if (normalSpeed >= 0)
131
+ return;
132
+ const normalVelocity = normal
133
+ .clone()
134
+ .multiplyScalar(normalSpeed);
135
+ const tangentVelocity = particle.velocity
136
+ .clone()
137
+ .sub(normalVelocity);
138
+ particle.velocity
139
+ .copy(tangentVelocity)
140
+ .addScaledVector(normalVelocity, -bounce)
141
+ .multiplyScalar(1 - dampen);
142
+ }
143
+ resolveLifetime(particle) {
144
+ var _a;
145
+ const loss = THREE.MathUtils.clamp(evaluateDynamicNumber((_a = this.lifetimeLoss) !== null && _a !== void 0 ? _a : 0, particle.time, particle.id), 0, 1);
146
+ if (loss === 0)
147
+ return;
148
+ particle.lifetime -= particle.start.lifetime * loss;
149
+ if (particle.lifetime <= (particle.realtime / 1000)) {
150
+ this.killParticle(particle);
151
+ }
152
+ }
153
+ getParticleRadius(particle) {
154
+ var _a;
155
+ const size = Math.max(Math.abs(particle.scale.x), Math.abs(particle.scale.y), Math.abs(particle.scale.z));
156
+ return size * 0.5 * ((_a = this.radiusScale) !== null && _a !== void 0 ? _a : 1);
157
+ }
158
+ killParticle(particle) {
159
+ particle.lifetime = 0;
160
+ }
161
+ }
162
+ export default Collision;
@@ -0,0 +1,18 @@
1
+ import * as THREE from 'three';
2
+ import Module, { ModuleOptions } from '../Module';
3
+ import { DynamicValue } from '../types/DynamicValue';
4
+ export type SpeedRange = [number, number] | {
5
+ min: number;
6
+ max: number;
7
+ };
8
+ export interface ColorBySpeedOptions extends Partial<ModuleOptions> {
9
+ color?: DynamicValue<THREE.Color>;
10
+ alpha?: DynamicValue<number>;
11
+ speedRange?: SpeedRange;
12
+ }
13
+ declare class ColorBySpeed extends Module {
14
+ options: ColorBySpeedOptions;
15
+ constructor(options: ColorBySpeedOptions);
16
+ private getSpeedTime;
17
+ }
18
+ export default ColorBySpeed;
@@ -0,0 +1,26 @@
1
+ import Module from '../Module';
2
+ import evaluateDynamicColor from '../helpers/evaluateDynamicColor';
3
+ import evaluateDynamicNumber from '../helpers/evaluateDynamicNumber';
4
+ class ColorBySpeed extends Module {
5
+ constructor(options) {
6
+ super((particle) => {
7
+ const t = this.getSpeedTime(particle.velocity.length());
8
+ if (this.options.color !== undefined) {
9
+ particle.color = particle.start.color.clone().multiply(evaluateDynamicColor(this.options.color, t, particle.id));
10
+ }
11
+ if (this.options.alpha !== undefined) {
12
+ particle.alpha = particle.start.alpha * evaluateDynamicNumber(this.options.alpha, t, particle.id);
13
+ }
14
+ }, options);
15
+ this.options = options;
16
+ }
17
+ getSpeedTime(speed) {
18
+ var _a, _b, _c, _d;
19
+ const min = Array.isArray(this.options.speedRange) ? this.options.speedRange[0] : (_b = (_a = this.options.speedRange) === null || _a === void 0 ? void 0 : _a.min) !== null && _b !== void 0 ? _b : 0;
20
+ const max = Array.isArray(this.options.speedRange) ? this.options.speedRange[1] : (_d = (_c = this.options.speedRange) === null || _c === void 0 ? void 0 : _c.max) !== null && _d !== void 0 ? _d : 1;
21
+ if (max === min)
22
+ return speed >= max ? 1 : 0;
23
+ return Math.min(Math.max((speed - min) / (max - min), 0), 1);
24
+ }
25
+ }
26
+ export default ColorBySpeed;
@@ -0,0 +1,12 @@
1
+ import * as THREE from 'three';
2
+ import Module, { ModuleOptions } from '../Module';
3
+ import { DynamicValue } from '../types/DynamicValue';
4
+ export interface ColorOverLifetimeOptions extends Partial<ModuleOptions> {
5
+ color?: DynamicValue<THREE.Color>;
6
+ alpha?: DynamicValue<number>;
7
+ }
8
+ declare class ColorOverLifetime extends Module {
9
+ options: ColorOverLifetimeOptions;
10
+ constructor(options?: ColorOverLifetimeOptions);
11
+ }
12
+ export default ColorOverLifetime;
@@ -0,0 +1,17 @@
1
+ import Module from '../Module';
2
+ import evaluateDynamicColor from '../helpers/evaluateDynamicColor';
3
+ import evaluateDynamicNumber from '../helpers/evaluateDynamicNumber';
4
+ class ColorOverLifetime extends Module {
5
+ constructor(options = {}) {
6
+ super((particle) => {
7
+ if (this.options.color !== undefined) {
8
+ particle.color = particle.start.color.clone().multiply(evaluateDynamicColor(this.options.color, particle.time, particle.id));
9
+ }
10
+ if (this.options.alpha !== undefined) {
11
+ particle.alpha = particle.start.alpha * evaluateDynamicNumber(this.options.alpha, particle.time, particle.id);
12
+ }
13
+ }, options);
14
+ this.options = options;
15
+ }
16
+ }
17
+ export default ColorOverLifetime;
@@ -0,0 +1,21 @@
1
+ import Module, { ModuleOptions } from '../Module';
2
+ import { DynamicValue } from '../types/DynamicValue';
3
+ import { IParticleForceField } from '../interfaces/IParticleForceField';
4
+ import ParticleForceField from '../ParticleForceField';
5
+ import ParticleSystem from '../ParticleSystem';
6
+ export interface ExternalForcesOptions extends Partial<ModuleOptions> {
7
+ multiplier?: DynamicValue<number>;
8
+ forceFieldFilter?: (forceField: ParticleForceField) => boolean;
9
+ forceFields?: IParticleForceField[];
10
+ }
11
+ declare class ExternalForces extends Module {
12
+ multiplier: DynamicValue<number>;
13
+ explicitForceFields?: IParticleForceField[];
14
+ forceFieldFilter?: (forceField: ParticleForceField) => boolean;
15
+ private forceFields;
16
+ private particleSystem?;
17
+ constructor(options: ExternalForcesOptions);
18
+ prepare(particleSystem: ParticleSystem, deltaTime: number): void;
19
+ }
20
+ export default ExternalForces;
21
+ export { IParticleForceField };
@@ -0,0 +1,61 @@
1
+ import * as THREE from 'three';
2
+ import Module from '../Module';
3
+ import evaluateDynamicNumber from '../helpers/evaluateDynamicNumber';
4
+ import ParticleForceField from '../ParticleForceField';
5
+ class ExternalForces extends Module {
6
+ constructor(options) {
7
+ var _a;
8
+ super((particle, deltaTime) => {
9
+ var _a;
10
+ const multiplier = evaluateDynamicNumber((_a = this.multiplier) !== null && _a !== void 0 ? _a : 1, particle.time, particle.id);
11
+ const particleSystem = this.particleSystem;
12
+ if (!particleSystem)
13
+ return;
14
+ particleSystem.updateWorldMatrix(true, false);
15
+ const particlePosition = particleSystem.simulationSpace === 'world'
16
+ ? particle.position
17
+ : particleSystem.localToWorld(particle.position.clone());
18
+ const worldQuaternion = particleSystem.simulationSpace === 'local'
19
+ ? particleSystem.getWorldQuaternion(new THREE.Quaternion())
20
+ : undefined;
21
+ const inverseWorldQuaternion = worldQuaternion === null || worldQuaternion === void 0 ? void 0 : worldQuaternion.clone().invert();
22
+ const forceParticle = particleSystem.simulationSpace === 'world'
23
+ ? particle
24
+ : Object.assign(Object.create(Object.getPrototypeOf(particle)), particle, {
25
+ position: particlePosition,
26
+ velocity: particle.velocity
27
+ .clone()
28
+ .applyQuaternion(worldQuaternion),
29
+ });
30
+ this.forceFields.forEach((forceField) => {
31
+ const force = forceField.getForce(forceParticle, deltaTime);
32
+ if (inverseWorldQuaternion) {
33
+ force.applyQuaternion(inverseWorldQuaternion);
34
+ }
35
+ particle.acceleration.addScaledVector(force, multiplier);
36
+ });
37
+ }, options);
38
+ this.multiplier = 1;
39
+ this.forceFields = new Set();
40
+ this.explicitForceFields = options.forceFields;
41
+ this.forceFieldFilter = (_a = options.forceFieldFilter) !== null && _a !== void 0 ? _a : (() => true);
42
+ }
43
+ prepare(particleSystem, deltaTime) {
44
+ var _a;
45
+ this.particleSystem = particleSystem;
46
+ // If explicit force fields are provided, just use those
47
+ if (Array.isArray(this.explicitForceFields)) {
48
+ this.forceFields = new Set(this.explicitForceFields);
49
+ return;
50
+ }
51
+ this.forceFields.clear();
52
+ // Otherwise, scan the scene for force fields
53
+ (_a = particleSystem.scene) === null || _a === void 0 ? void 0 : _a.traverse((object) => {
54
+ var _a;
55
+ if (object instanceof ParticleForceField
56
+ && ((_a = this.forceFieldFilter) === null || _a === void 0 ? void 0 : _a.call(this, object)))
57
+ this.forceFields.add(object);
58
+ });
59
+ }
60
+ }
61
+ export default ExternalForces;
@@ -0,0 +1,11 @@
1
+ import * as THREE from 'three';
2
+ import Module, { ModuleOptions } from '../Module';
3
+ import { DynamicValue } from '../types/DynamicValue';
4
+ export interface ForceOverLifetimeOptions extends Partial<ModuleOptions> {
5
+ force: DynamicValue<THREE.Vector3>;
6
+ }
7
+ declare class ForceOverLifetime extends Module {
8
+ options: ForceOverLifetimeOptions;
9
+ constructor(options: ForceOverLifetimeOptions);
10
+ }
11
+ export default ForceOverLifetime;
@@ -0,0 +1,12 @@
1
+ import Module from '../Module';
2
+ import evaluateDynamicVector from '../helpers/evaluateDynamicVector3';
3
+ class ForceOverLifetime extends Module {
4
+ constructor(options) {
5
+ super((particle) => {
6
+ particle.acceleration = particle.start.acceleration.clone()
7
+ .add(evaluateDynamicVector(this.options.force, particle.time, particle.id));
8
+ }, options);
9
+ this.options = options;
10
+ }
11
+ }
12
+ export default ForceOverLifetime;
@@ -0,0 +1,16 @@
1
+ import * as THREE from 'three';
2
+ import Module, { ModuleOptions } from '../Module';
3
+ import { DynamicValue } from '../types/DynamicValue';
4
+ export interface LimitVelocityOverLifetimeOptions extends Partial<ModuleOptions> {
5
+ limit: DynamicValue<THREE.Vector3>;
6
+ dampen?: number;
7
+ drag?: DynamicValue<number>;
8
+ multiplyDragBySize?: boolean;
9
+ multiplyDragByVelocity?: boolean;
10
+ }
11
+ declare class LimitVelocityOverLifetime extends Module {
12
+ options: LimitVelocityOverLifetimeOptions;
13
+ constructor(options: LimitVelocityOverLifetimeOptions);
14
+ private dampenAxis;
15
+ }
16
+ export default LimitVelocityOverLifetime;
@@ -0,0 +1,34 @@
1
+ import Module from '../Module';
2
+ import evaluateDynamicNumber from '../helpers/evaluateDynamicNumber';
3
+ import evaluateDynamicVector from '../helpers/evaluateDynamicVector3';
4
+ class LimitVelocityOverLifetime extends Module {
5
+ constructor(options) {
6
+ super((particle, deltaTime) => {
7
+ var _a;
8
+ const limit = evaluateDynamicVector(this.options.limit, particle.time, particle.id);
9
+ const dampen = (_a = this.options.dampen) !== null && _a !== void 0 ? _a : 1;
10
+ this.dampenAxis(particle.velocity, 'x', Math.abs(limit.x), dampen);
11
+ this.dampenAxis(particle.velocity, 'y', Math.abs(limit.y), dampen);
12
+ this.dampenAxis(particle.velocity, 'z', Math.abs(limit.z), dampen);
13
+ if (this.options.drag !== undefined) {
14
+ let drag = evaluateDynamicNumber(this.options.drag, particle.time, particle.id);
15
+ if (this.options.multiplyDragBySize) {
16
+ drag *= (particle.scale.x + particle.scale.y + particle.scale.z) / 3;
17
+ }
18
+ if (this.options.multiplyDragByVelocity) {
19
+ drag *= particle.velocity.length();
20
+ }
21
+ particle.velocity.multiplyScalar(Math.max(0, 1 - drag * deltaTime));
22
+ }
23
+ }, options);
24
+ this.options = options;
25
+ }
26
+ // eslint-disable-next-line class-methods-use-this
27
+ dampenAxis(velocity, axis, limit, dampen) {
28
+ if (Math.abs(velocity[axis]) <= limit)
29
+ return;
30
+ const clamped = Math.sign(velocity[axis]) * limit;
31
+ velocity[axis] += (clamped - velocity[axis]) * Math.min(Math.max(dampen, 0), 1);
32
+ }
33
+ }
34
+ export default LimitVelocityOverLifetime;
@@ -0,0 +1,11 @@
1
+ import Module, { ModuleOptions } from '../Module';
2
+ import { DynamicValue } from '../types/DynamicValue';
3
+ export interface MassOverLifetimeOptions extends Partial<ModuleOptions> {
4
+ mass: DynamicValue<number>;
5
+ multiplyMassBySize: boolean;
6
+ }
7
+ declare class MassOverLifetime extends Module {
8
+ options: MassOverLifetimeOptions;
9
+ constructor(options: MassOverLifetimeOptions);
10
+ }
11
+ export default MassOverLifetime;
@@ -0,0 +1,15 @@
1
+ import Module from '../Module';
2
+ import evaluateDynamicNumber from '../helpers/evaluateDynamicNumber';
3
+ class MassOverLifetime extends Module {
4
+ constructor(options) {
5
+ super((particle) => {
6
+ var _a;
7
+ const sizeRatio = particle.scale.length() / particle.start.scale.length();
8
+ particle.mass = particle.start.mass
9
+ * evaluateDynamicNumber(this.options.mass, particle.time, particle.id)
10
+ * (((_a = options.multiplyMassBySize) !== null && _a !== void 0 ? _a : true) ? sizeRatio : 1);
11
+ }, options);
12
+ this.options = options;
13
+ }
14
+ }
15
+ export default MassOverLifetime;
@@ -0,0 +1,23 @@
1
+ import * as THREE from 'three';
2
+ import Module, { ModuleOptions } from '../Module';
3
+ export interface NoiseOptions extends Partial<ModuleOptions> {
4
+ octaves: number;
5
+ frequency: number;
6
+ lacunarity: number;
7
+ persistence: number;
8
+ time: number;
9
+ offset: THREE.Vector3;
10
+ }
11
+ declare class NoiseModule extends Module {
12
+ octaves: number;
13
+ frequency: number;
14
+ lacunarity: number;
15
+ persistence: number;
16
+ time: number;
17
+ offset: THREE.Vector3;
18
+ key: string;
19
+ private noiseGenerator;
20
+ constructor(key: string, options?: Partial<NoiseOptions>);
21
+ private generateNoise;
22
+ }
23
+ export default NoiseModule;
@@ -0,0 +1,45 @@
1
+ import { makeNoise4D } from 'fast-simplex-noise';
2
+ import * as THREE from 'three';
3
+ import Module from '../Module';
4
+ class NoiseModule extends Module {
5
+ constructor(key, options = {}) {
6
+ var _a, _b, _c, _d, _e, _f;
7
+ super((particle) => {
8
+ particle.noise[key] = {
9
+ noise: this.generateNoise(particle),
10
+ noise4d: this.generateNoise(particle, true),
11
+ };
12
+ }, options);
13
+ this.octaves = 1;
14
+ this.frequency = 1;
15
+ this.lacunarity = 2.0;
16
+ this.persistence = 0.5;
17
+ this.time = 0;
18
+ this.offset = new THREE.Vector3();
19
+ this.noiseGenerator = makeNoise4D();
20
+ this.key = key;
21
+ this.octaves = (_a = options.octaves) !== null && _a !== void 0 ? _a : this.octaves;
22
+ this.frequency = (_b = options.frequency) !== null && _b !== void 0 ? _b : this.frequency;
23
+ this.lacunarity = (_c = options.lacunarity) !== null && _c !== void 0 ? _c : this.lacunarity;
24
+ this.persistence = (_d = options.persistence) !== null && _d !== void 0 ? _d : this.persistence;
25
+ this.time = (_e = options.time) !== null && _e !== void 0 ? _e : this.time;
26
+ this.offset = (_f = options.offset) !== null && _f !== void 0 ? _f : this.offset;
27
+ }
28
+ generateNoise(particle, w = false) {
29
+ const layers = [];
30
+ for (let i = 0; i < this.octaves; i += 1) {
31
+ const frequency = this.frequency * (Math.pow(this.lacunarity, i));
32
+ const amplitude = Math.pow(this.persistence, i);
33
+ // Clamp because float math is nuts
34
+ const rawNoise = Math.min(Math.max((this.noiseGenerator((particle.position.x + this.offset.x) * frequency, (particle.position.y + this.offset.y) * frequency, (particle.position.z + this.offset.z) * frequency, w ? this.time : 0) + 1) / 2, 0), 1);
35
+ layers.push({
36
+ value: rawNoise * amplitude,
37
+ weight: amplitude,
38
+ });
39
+ }
40
+ // Use weighted average to maintain 0 - 1 range
41
+ return layers.map((layer) => layer.value).reduce((a, b) => a + b)
42
+ / layers.map((layer) => layer.weight).reduce((a, b) => a + b);
43
+ }
44
+ }
45
+ export default NoiseModule;
@@ -0,0 +1,14 @@
1
+ import * as THREE from 'three';
2
+ import Module, { ModuleOptions } from '../Module';
3
+ import { DynamicValue } from '../types/DynamicValue';
4
+ import { SpeedRange } from './ColorBySpeed';
5
+ export interface RotationBySpeedOptions extends Partial<ModuleOptions> {
6
+ angularVelocity: DynamicValue<THREE.Vector3>;
7
+ speedRange?: SpeedRange;
8
+ }
9
+ declare class RotationBySpeed extends Module {
10
+ options: RotationBySpeedOptions;
11
+ constructor(options: RotationBySpeedOptions);
12
+ private getSpeedTime;
13
+ }
14
+ export default RotationBySpeed;
@@ -0,0 +1,19 @@
1
+ import Module from '../Module';
2
+ import evaluateDynamicVector from '../helpers/evaluateDynamicVector3';
3
+ class RotationBySpeed extends Module {
4
+ constructor(options) {
5
+ super((particle) => {
6
+ particle.angularVelocity = particle.start.angularVelocity.clone().add(evaluateDynamicVector(this.options.angularVelocity, this.getSpeedTime(particle.velocity.length()), particle.id));
7
+ }, options);
8
+ this.options = options;
9
+ }
10
+ getSpeedTime(speed) {
11
+ var _a, _b, _c, _d;
12
+ const min = Array.isArray(this.options.speedRange) ? this.options.speedRange[0] : (_b = (_a = this.options.speedRange) === null || _a === void 0 ? void 0 : _a.min) !== null && _b !== void 0 ? _b : 0;
13
+ const max = Array.isArray(this.options.speedRange) ? this.options.speedRange[1] : (_d = (_c = this.options.speedRange) === null || _c === void 0 ? void 0 : _c.max) !== null && _d !== void 0 ? _d : 1;
14
+ if (max === min)
15
+ return speed >= max ? 1 : 0;
16
+ return Math.min(Math.max((speed - min) / (max - min), 0), 1);
17
+ }
18
+ }
19
+ export default RotationBySpeed;
@@ -0,0 +1,11 @@
1
+ import * as THREE from 'three';
2
+ import Module, { ModuleOptions } from '../Module';
3
+ import { DynamicValue } from '../types/DynamicValue';
4
+ export interface RotationOverLifetimeOptions extends Partial<ModuleOptions> {
5
+ angularVelocity: DynamicValue<THREE.Vector3>;
6
+ }
7
+ declare class RotationOverLifetime extends Module {
8
+ options: RotationOverLifetimeOptions;
9
+ constructor(options: RotationOverLifetimeOptions);
10
+ }
11
+ export default RotationOverLifetime;
@@ -0,0 +1,12 @@
1
+ import Module from '../Module';
2
+ import evaluateDynamicVector from '../helpers/evaluateDynamicVector3';
3
+ class RotationOverLifetime extends Module {
4
+ constructor(options) {
5
+ super((particle) => {
6
+ particle.angularVelocity = particle.start.angularVelocity.clone()
7
+ .add(evaluateDynamicVector(this.options.angularVelocity, particle.time, particle.id));
8
+ }, options);
9
+ this.options = options;
10
+ }
11
+ }
12
+ export default RotationOverLifetime;
@@ -0,0 +1,14 @@
1
+ import * as THREE from 'three';
2
+ import Module, { ModuleOptions } from '../Module';
3
+ import { DynamicValue } from '../types/DynamicValue';
4
+ import { SpeedRange } from './ColorBySpeed';
5
+ export interface ScaleBySpeedOptions extends Partial<ModuleOptions> {
6
+ scale: DynamicValue<THREE.Vector3>;
7
+ speedRange?: SpeedRange;
8
+ }
9
+ declare class ScaleBySpeed extends Module {
10
+ options: ScaleBySpeedOptions;
11
+ constructor(options: ScaleBySpeedOptions);
12
+ private getSpeedTime;
13
+ }
14
+ export default ScaleBySpeed;
@@ -0,0 +1,19 @@
1
+ import Module from '../Module';
2
+ import evaluateDynamicVector from '../helpers/evaluateDynamicVector3';
3
+ class ScaleBySpeed extends Module {
4
+ constructor(options) {
5
+ super((particle) => {
6
+ particle.scale = particle.start.scale.clone().multiply(evaluateDynamicVector(this.options.scale, this.getSpeedTime(particle.velocity.length()), particle.id));
7
+ }, options);
8
+ this.options = options;
9
+ }
10
+ getSpeedTime(speed) {
11
+ var _a, _b, _c, _d;
12
+ const min = Array.isArray(this.options.speedRange) ? this.options.speedRange[0] : (_b = (_a = this.options.speedRange) === null || _a === void 0 ? void 0 : _a.min) !== null && _b !== void 0 ? _b : 0;
13
+ const max = Array.isArray(this.options.speedRange) ? this.options.speedRange[1] : (_d = (_c = this.options.speedRange) === null || _c === void 0 ? void 0 : _c.max) !== null && _d !== void 0 ? _d : 1;
14
+ if (max === min)
15
+ return speed >= max ? 1 : 0;
16
+ return Math.min(Math.max((speed - min) / (max - min), 0), 1);
17
+ }
18
+ }
19
+ export default ScaleBySpeed;
@@ -0,0 +1,11 @@
1
+ import * as THREE from 'three';
2
+ import Module, { ModuleOptions } from '../Module';
3
+ import { DynamicValue } from '../types/DynamicValue';
4
+ export interface ScaleOverLifetimeOptions extends Partial<ModuleOptions> {
5
+ scale: DynamicValue<THREE.Vector3>;
6
+ }
7
+ declare class ScaleOverLifetime extends Module {
8
+ options: ScaleOverLifetimeOptions;
9
+ constructor(options: ScaleOverLifetimeOptions);
10
+ }
11
+ export default ScaleOverLifetime;
@@ -0,0 +1,11 @@
1
+ import Module from '../Module';
2
+ import evaluateDynamicVector from '../helpers/evaluateDynamicVector3';
3
+ class ScaleOverLifetime extends Module {
4
+ constructor(options) {
5
+ super((particle) => {
6
+ particle.scale = particle.start.scale.clone().multiply(evaluateDynamicVector(this.options.scale, particle.time, particle.id));
7
+ }, options);
8
+ this.options = options;
9
+ }
10
+ }
11
+ export default ScaleOverLifetime;
@@ -0,0 +1,17 @@
1
+ import * as THREE from 'three';
2
+ import Module, { ModuleOptions } from '../Module';
3
+ import { DynamicValue } from '../types/DynamicValue';
4
+ import { NoiseOptions } from './NoiseModule';
5
+ export interface TransformByNoiseOptions extends Partial<ModuleOptions>, NoiseOptions {
6
+ strength: DynamicValue<THREE.Vector3>;
7
+ scrollSpeed: DynamicValue<number>;
8
+ damping: boolean;
9
+ }
10
+ declare class TransformByNoise extends Module {
11
+ options: Partial<TransformByNoiseOptions>;
12
+ private noiseX;
13
+ private noiseY;
14
+ private noiseZ;
15
+ constructor(options: Partial<TransformByNoiseOptions>);
16
+ }
17
+ export default TransformByNoise;