@needle-tools/engine 2.41.0-pre → 2.43.0-pre

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 (79) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/needle-engine.d.ts +226 -76
  3. package/dist/needle-engine.js +3847 -433
  4. package/dist/needle-engine.js.map +4 -4
  5. package/dist/needle-engine.min.js +51 -51
  6. package/dist/needle-engine.min.js.map +4 -4
  7. package/lib/engine/engine_element.js +1 -1
  8. package/lib/engine/engine_element.js.map +1 -1
  9. package/lib/engine/engine_element_loading.js +24 -3
  10. package/lib/engine/engine_element_loading.js.map +1 -1
  11. package/lib/engine/engine_gizmos.d.ts +8 -22
  12. package/lib/engine/engine_gizmos.js +37 -3
  13. package/lib/engine/engine_gizmos.js.map +1 -1
  14. package/lib/engine/engine_setup.d.ts +3 -0
  15. package/lib/engine/engine_setup.js +15 -0
  16. package/lib/engine/engine_setup.js.map +1 -1
  17. package/lib/engine/engine_three_utils.d.ts +17 -1
  18. package/lib/engine/engine_three_utils.js +104 -54
  19. package/lib/engine/engine_three_utils.js.map +1 -1
  20. package/lib/engine/engine_time.js +2 -0
  21. package/lib/engine/engine_time.js.map +1 -1
  22. package/lib/engine/engine_types.d.ts +6 -0
  23. package/lib/engine/engine_types.js.map +1 -1
  24. package/lib/engine/extensions/NEEDLE_techniques_webgl.js +42 -0
  25. package/lib/engine/extensions/NEEDLE_techniques_webgl.js.map +1 -1
  26. package/lib/engine-components/Animation.js +9 -1
  27. package/lib/engine-components/Animation.js.map +1 -1
  28. package/lib/engine-components/AnimationCurve.js +2 -2
  29. package/lib/engine-components/AnimationCurve.js.map +1 -1
  30. package/lib/engine-components/AnimatorController.js +4 -1
  31. package/lib/engine-components/AnimatorController.js.map +1 -1
  32. package/lib/engine-components/BoxHelperComponent.js +9 -10
  33. package/lib/engine-components/BoxHelperComponent.js.map +1 -1
  34. package/lib/engine-components/Camera.d.ts +3 -0
  35. package/lib/engine-components/Camera.js +17 -9
  36. package/lib/engine-components/Camera.js.map +1 -1
  37. package/lib/engine-components/ParticleSystem.d.ts +41 -13
  38. package/lib/engine-components/ParticleSystem.js +587 -219
  39. package/lib/engine-components/ParticleSystem.js.map +1 -1
  40. package/lib/engine-components/ParticleSystemBehaviours.d.ts +0 -0
  41. package/lib/engine-components/ParticleSystemBehaviours.js +2 -0
  42. package/lib/engine-components/ParticleSystemBehaviours.js.map +1 -0
  43. package/lib/engine-components/ParticleSystemModules.d.ts +123 -22
  44. package/lib/engine-components/ParticleSystemModules.js +377 -60
  45. package/lib/engine-components/ParticleSystemModules.js.map +1 -1
  46. package/lib/engine-components/ReflectionProbe.js +29 -11
  47. package/lib/engine-components/ReflectionProbe.js.map +1 -1
  48. package/lib/engine-components/Renderer.d.ts +1 -0
  49. package/lib/engine-components/Renderer.js +4 -2
  50. package/lib/engine-components/Renderer.js.map +1 -1
  51. package/lib/engine-components/codegen/components.d.ts +5 -0
  52. package/lib/engine-components/codegen/components.js +5 -0
  53. package/lib/engine-components/codegen/components.js.map +1 -1
  54. package/lib/engine-components/js-extensions/RGBAColor.d.ts +1 -0
  55. package/lib/engine-components/js-extensions/RGBAColor.js +7 -0
  56. package/lib/engine-components/js-extensions/RGBAColor.js.map +1 -1
  57. package/package.json +3 -2
  58. package/src/engine/codegen/register_types.js +20 -0
  59. package/src/engine/dist/engine_three_utils.js +279 -0
  60. package/src/engine/engine_element.ts +1 -1
  61. package/src/engine/engine_element_loading.ts +23 -2
  62. package/src/engine/engine_gizmos.ts +45 -8
  63. package/src/engine/engine_setup.ts +25 -2
  64. package/src/engine/engine_three_utils.ts +113 -63
  65. package/src/engine/engine_time.ts +1 -0
  66. package/src/engine/engine_types.ts +8 -1
  67. package/src/engine/extensions/NEEDLE_techniques_webgl.ts +43 -1
  68. package/src/engine-components/Animation.ts +7 -1
  69. package/src/engine-components/AnimationCurve.ts +2 -2
  70. package/src/engine-components/AnimatorController.ts +5 -1
  71. package/src/engine-components/BoxHelperComponent.ts +12 -15
  72. package/src/engine-components/Camera.ts +17 -10
  73. package/src/engine-components/ParticleSystem.ts +660 -258
  74. package/src/engine-components/ParticleSystemBehaviours.ts +0 -0
  75. package/src/engine-components/ParticleSystemModules.ts +379 -64
  76. package/src/engine-components/ReflectionProbe.ts +37 -13
  77. package/src/engine-components/Renderer.ts +4 -2
  78. package/src/engine-components/codegen/components.ts +5 -0
  79. package/src/engine-components/js-extensions/RGBAColor.ts +7 -0
@@ -1,368 +1,770 @@
1
1
  import { Behaviour, GameObject } from "./Component";
2
2
  import * as THREE from "three";
3
- import { MainModule, EmissionModule, ShapeModule, ParticleSystemShapeType, MinMaxCurve, MinMaxGradient, ColorOverLifetimeModule, SizeOverLifetimeModule, NoiseModule, ParticleSystemSimulationSpace } from "./ParticleSystemModules"
3
+ import { MainModule, EmissionModule, ShapeModule, ParticleSystemShapeType, MinMaxCurve, MinMaxGradient, ColorOverLifetimeModule, SizeOverLifetimeModule, NoiseModule, ParticleSystemSimulationSpace, ParticleBurst, IParticleSystem, ParticleSystemRenderMode, TrailModule, VelocityOverLifetimeModule, TextureSheetAnimationModule, RotationOverLifetimeModule } from "./ParticleSystemModules"
4
4
  import { getParam } from "../engine/engine_utils";
5
- import System, {
6
- Emitter,
7
- Rate,
8
- Span,
9
- Position,
10
- Mass,
11
- Radius,
12
- Life,
13
- PointZone,
14
- Vector3D,
15
- Alpha,
16
- Scale,
17
- Color,
18
- SpriteRenderer,
19
- RadialVelocity,
20
- BoxZone,
21
- Particle,
22
- Gravity,
23
- SphereZone,
24
- } from 'three-nebula';
5
+
25
6
  // https://github.dev/creativelifeform/three-nebula
7
+ // import System, { Emitter, Position, Life, SpriteRenderer, Particle, Body, MeshRenderer, } from 'three-nebula';
26
8
 
27
9
  import { serializeable } from "../engine/engine_serialization";
28
- import { Time } from "../engine/engine_time";
29
- import { Context } from "../engine/engine_setup";
30
10
  import { RGBAColor } from "./js-extensions/RGBAColor";
11
+ import { AxesHelper, BufferGeometry, Color, Material, Mesh, MeshStandardMaterial, Object3D, OneMinusDstAlphaFactor, Quaternion, Sprite, SpriteMaterial, Vector3, Vector4 } from "three";
12
+ import { getWorldPosition, getWorldQuaternion, getWorldScale } from "../engine/engine_three_utils";
13
+ import { assign } from "../engine/engine_serialization_core";
14
+ import { BatchedParticleRenderer, Behavior, BillBoardSettings, BurstParameters, ColorGenerator, ConstantColor, ConstantValue, EmitterShape, FunctionColorGenerator, FunctionJSON, FunctionValueGenerator, MeshSettings, Particle, ParticleEmitter, ParticleSystem as _ParticleSystem, ParticleSystemParameters, PointEmitter, RenderMode, RotationGenerator, SizeOverLife, TrailBatch, TrailSettings, ValueGenerator } from "three.quarks";
15
+ import { createFlatTexture } from "../engine/engine_shaders";
31
16
  import { Mathf } from "../engine/engine_math";
32
- import { Vec3 } from "../engine/engine_types";
33
- import { AxesHelper, Material, Object3D, Sprite, SpriteMaterial, Vector3 } from "three";
34
- import { Renderer } from "./Renderer";
35
- import { getWorldQuaternion, getWorldScale } from "../engine/engine_three_utils";
36
17
 
37
18
  const debug = getParam("debugparticles");
38
19
 
39
20
 
40
-
41
21
  export class ParticleSystemRenderer extends Behaviour {
42
22
 
23
+ @serializeable()
24
+ renderMode?: ParticleSystemRenderMode;
25
+
43
26
  @serializeable(Material)
44
27
  particleMaterial?: SpriteMaterial;
45
- }
46
28
 
47
- export class ParticleSystem extends Behaviour {
29
+ // @serializeable(Mesh)
30
+ particleMesh?: Mesh | string;
48
31
 
49
- @serializeable(ColorOverLifetimeModule)
50
- colorOverLifetime!: ColorOverLifetimeModule;
32
+ get transparent(): boolean {
33
+ const res = this.particleMaterial?.transparent ?? false;
34
+ // console.log(res, this.particleMaterial);
35
+ return res;
36
+ }
51
37
 
52
- @serializeable(MainModule)
53
- main!: MainModule;
38
+ getMesh() {
39
+ let geo: BufferGeometry | null = null;
40
+ if (this.particleMesh instanceof Mesh) {
41
+ geo = this.particleMesh.geometry;
42
+ }
43
+ if (geo === null) geo = new THREE.BoxGeometry(1, 1, 1);
44
+ const res = new Mesh(geo, this.particleMaterial);
45
+ return res;
46
+ }
47
+ }
54
48
 
55
- @serializeable(EmissionModule)
56
- emission!: EmissionModule;
49
+ class MinMaxCurveFunction implements FunctionValueGenerator {
57
50
 
58
- @serializeable(SizeOverLifetimeModule)
59
- sizeOverLifetime!: SizeOverLifetimeModule;
51
+ private _curve: MinMaxCurve;
60
52
 
61
- @serializeable(ShapeModule)
62
- shape!: ShapeModule;
53
+ constructor(curve: MinMaxCurve) { this._curve = curve; }
63
54
 
64
- @serializeable(NoiseModule)
65
- noise!: NoiseModule;
55
+ type: "function" = "function";
66
56
 
67
- renderer!: ParticleSystemRenderer;
57
+ genValue(t: number): number {
58
+ return this._curve.evaluate(t, Math.random());
59
+ }
60
+ toJSON(): FunctionJSON {
61
+ throw new Error("Method not implemented.");
62
+ }
63
+ clone(): FunctionValueGenerator {
64
+ throw new Error("Method not implemented.");
65
+ }
66
+ }
68
67
 
69
- private _system!: System;
70
- private _emitter: Emitter;
71
- private _size!: SizeBehaviour;
68
+ class MinMaxGradientFunction implements FunctionColorGenerator {
72
69
 
73
- awake(): void {
74
- if (debug) {
75
- console.log(this);
76
- this.gameObject.add(new AxesHelper(1))
77
- }
70
+ private _curve: MinMaxGradient;
78
71
 
79
- this.renderer = this.gameObject.getComponent(ParticleSystemRenderer) as ParticleSystemRenderer;
80
- this._system = new System();
81
- const container = this.main.simulationSpace == ParticleSystemSimulationSpace.Local ? this.gameObject : this.context.scene;
82
-
83
-
84
- const renderer = new SpriteRenderer(container, THREE);
85
- renderer.logRendererType = () => { };
86
- if (this.renderer.particleMaterial) {
87
- const sprite = renderer._body as Sprite;
88
- sprite.layers.disableAll();
89
- sprite.layers.set(2); // ignore raycasting particles
90
- sprite.renderOrder = 1;
91
- sprite.material.map = this.renderer.particleMaterial.map;
92
- sprite.material.transparent = true;
93
- // sprite.material.sizeAttenuation = false;
94
- sprite.material.blending = this.renderer.particleMaterial.blending;
95
- sprite.material.blendDst = this.renderer.particleMaterial.blendDst;
96
- sprite.material.blendDstAlpha = this.renderer.particleMaterial.blendDstAlpha;
97
- sprite.material.blendEquation = this.renderer.particleMaterial.blendEquation;
98
- sprite.material.blendEquationAlpha = this.renderer.particleMaterial.blendEquationAlpha;
99
- sprite.material.blendSrc = this.renderer.particleMaterial.blendSrc;
100
- sprite.material.blendSrcAlpha = this.renderer.particleMaterial.blendSrcAlpha;
101
- sprite.material.premultipliedAlpha = this.renderer.particleMaterial.premultipliedAlpha;
102
- sprite.material.depthWrite = false;
103
- sprite.material.depthTest = true;
104
- if (debug) console.log(sprite);
105
- }
72
+ constructor(curve: MinMaxGradient) { this._curve = curve; }
106
73
 
107
- this._system.addRenderer(renderer);
74
+ type: "function" = "function";
108
75
 
109
- const initializers: Array<any> = [];
110
- const behaviours: Array<any> = [];
76
+ genColor(color: THREE.Vector4, t: number): THREE.Vector4 {
77
+ const col = this._curve.evaluate(t, Math.random());
78
+ // TODO: incoming color should probably be blended?
79
+ color.set(col.r, col.g, col.b, col.alpha);
80
+ return color;
81
+ }
82
+ toJSON(): FunctionJSON {
83
+ throw new Error("Method not implemented.");
84
+ }
85
+ clone(): FunctionColorGenerator {
86
+ throw new Error("Method not implemented.");
87
+ }
111
88
 
89
+ }
112
90
 
91
+ abstract class BaseValueGenerator implements ValueGenerator {
113
92
 
114
- const life = new Life();
115
- life.lifePan = new MinMaxCurveSpan(this.main.startLifetime, 1);
116
- initializers.push(life);
93
+ type: "value" = "value";
94
+ toJSON(): FunctionJSON {
95
+ throw new Error("Method not implemented.");
96
+ }
97
+ clone(): ValueGenerator {
98
+ throw new Error("Method not implemented.");
99
+ }
117
100
 
118
- const shape = new Position(this.shape);
119
- initializers.push(shape);
101
+ abstract genValue(): number;
120
102
 
121
- const size = this._size = new SizeBehaviour(this.main.startSize, this.main.startSizeMultiplier);
122
- size.sizeOverLifetimeModule = this.sizeOverLifetime;
123
- behaviours.push(size);
103
+ readonly system: ParticleSystem;
124
104
 
125
- const color = new GradientBehaviour(this.main.startColor, this.colorOverLifetime?.enabled ? this.colorOverLifetime.color : undefined);
126
- behaviours.push(color);
105
+ constructor(system: ParticleSystem) {
106
+ this.system = system;
107
+ }
108
+ }
127
109
 
128
- const velocity = new VelocityBehaviour(renderer.container, this.shape, this.noise, this.main.startSpeed, 1);
129
- velocity.gravity = this.main.gravityModifier;
130
- velocity.gravityModifierMultiplier = this.main.gravityModifierMultiplier;
131
- behaviours.push(velocity);
110
+ class TextureSheetStartFrameGenerator extends BaseValueGenerator {
111
+ genValue(): number {
112
+ return this.system.textureSheetAnimation.getStartIndex();
113
+ }
132
114
 
115
+ }
133
116
 
134
- const emitter = this._emitter = new Emitter({});
135
- emitter.setInitializers(initializers);
136
- emitter.setBehaviours(behaviours);
137
- emitter.setRate(this.emission);
138
- emitter.damping = 0;
139
- }
117
+ class ParticleSystemEmissionOverTime extends BaseValueGenerator {
140
118
 
141
- onEnable() {
142
- this._emitter.emit();
143
- this._system.addEmitter(this._emitter);
144
- this._system.emit({ onStart: () => { }, onUpdate: () => { }, onEnd: () => { }, });
145
- }
119
+ private _lastPosition: Vector3 = new Vector3();
120
+ private _lastDistance: number = 0;
146
121
 
147
- onDisable() {
148
- this._system.removeEmitter(this._emitter);
122
+ update() {
123
+ const currentPosition = getWorldPosition(this.system.gameObject);
124
+ this._lastDistance = this._lastPosition.distanceTo(currentPosition)
125
+ this._lastPosition.copy(currentPosition);
149
126
  }
150
127
 
151
- onBeforeRender() {
152
- this.emission.currentParticles = this._system.getCount();
153
- this.emission.maxParticles = this.main.maxParticles;
154
- this.shape.update(this.context, this.main.simulationSpace, this.gameObject);
155
- this.noise.update(this.context);
156
- this._system.update(this.context.time.deltaTime * this.main.simulationSpeed);
157
-
158
- // sprite materials must be scaled in AR
159
- const cam = this.context.mainCamera;
160
- if (cam) {
161
- const scale = getWorldScale(cam);
162
- this._size.cameraScale = scale.x;
128
+ genValue(): number {
129
+ if (this.system.currentParticles >= this.system.maxParticles) return 0;
130
+ // emission over time
131
+ let emission = this.system.emission.rateOverTime.evaluate(this.system.time / this.system.duration, Math.random());
132
+ // if(this.system.currentParticles + emission > this.system.maxParticles)
133
+ // emission = (this.system.maxParticles - this.system.currentParticles);
134
+ // const res = Mathf.clamp(emission, 0, this.system.maxParticles - this.system.currentParticles);
135
+
136
+ if (this.system.deltaTime > 0) {
137
+ const distanceEmission = this.system.emission.rateOverDistance.evaluate(this.system.time / this.system.duration, Math.random());
138
+ const meterPerSecond = this._lastDistance / this.system.deltaTime;
139
+ let distanceEmissionValue = meterPerSecond * distanceEmission;
140
+ if (!Number.isFinite(distanceEmissionValue)) distanceEmissionValue = 0;
141
+ emission += distanceEmissionValue;
163
142
  }
164
- }
165
143
 
144
+ const burst = this.system.emission.getBurst();
145
+ if (burst > 0)
146
+ emission += burst / this.system.deltaTime;
147
+
148
+ const maxEmission = (this.system.maxParticles - this.system.currentParticles);
149
+ return Mathf.clamp(emission, 0, maxEmission / this.system.deltaTime);
150
+ }
166
151
  }
167
152
 
153
+ class ParticleSystemEmissionOverDistance extends BaseValueGenerator {
168
154
 
155
+ genValue(): number {
156
+ // this seems not be called yet
157
+ return 0;
158
+ // if (this.system.currentParticles >= this.system.maxParticles) return 0;
159
+ // const emission = this.system.emission.rateOverDistance.evaluate(this.system.time / this.system.duration, Math.random());
160
+ // return emission;
161
+ }
162
+ }
169
163
 
164
+ abstract class ParticleSystemBaseBehaviour implements Behavior {
165
+ readonly system: ParticleSystem;
170
166
 
171
- class MinMaxCurveSpan {
167
+ constructor(ps: ParticleSystem) {
168
+ this.system = ps;
169
+ }
172
170
 
173
- readonly time: Time;
174
- readonly curve: MinMaxCurve;
175
- multiplier: number = 1;
171
+ abstract type: string;
176
172
 
177
- constructor(minMaxCurve: MinMaxCurve, multiplier: number = 1) {
178
- this.time = Context.Current.time;
179
- this.curve = minMaxCurve;
180
- this.multiplier = multiplier;
173
+ initialize(_particle: Particle): void {
174
+ }
175
+ update(_particle: Particle, _delta: number): void {
181
176
  }
177
+ frameUpdate(_delta: number): void {
178
+ }
179
+ toJSON() { throw new Error("Method not implemented."); }
180
+ clone(): Behavior { throw new Error("Method not implemented."); }
181
+ }
182
182
 
183
- /** called by nebula */
184
- getValue(lerp?: number) {
185
- const res = this.curve.evaluate(this.time.time, lerp) * this.multiplier;
186
- return res;
183
+ class TextureSheetAnimationBehaviour extends ParticleSystemBaseBehaviour {
184
+ type: string = "NeedleTextureSheet"
185
+
186
+ update(particle: Particle, _delta: number) {
187
+ const sheet = this.system.textureSheetAnimation;
188
+ if (sheet.enabled) {
189
+ const t01 = particle.age / particle.life;
190
+ const index = sheet.evaluate(t01);;
191
+ if (index !== undefined)
192
+ particle.uvTile = index;
193
+ }
187
194
  }
195
+
188
196
  }
189
197
 
190
- abstract class CustomBehaviour extends Behaviour {
191
- abstract applyBehaviour(target: Particle | Emitter, time: number, index: number);
192
- abstract initialize(particle: Particle);
198
+ class RotationBehaviour extends ParticleSystemBaseBehaviour {
199
+ type: string = "NeedleRotation"
200
+
201
+ update(particle: Particle, delta: number) {
202
+ if (particle.rotation === undefined) return;
203
+ if (particle.rotation instanceof Quaternion) {
204
+
205
+ }
206
+ else {
207
+ if (this.system.rotationOverLifetime.enabled) {
208
+ particle.rotation += this.system.rotationOverLifetime.evaluate(particle.age / particle.life) * delta;
209
+ }
210
+ // HACK flip y
211
+ else particle.rotation = Math.PI;
212
+ }
213
+ }
193
214
  }
194
215
 
195
- abstract class MinMaxCurveBehaviour extends CustomBehaviour {
216
+ class SizeBehaviour extends ParticleSystemBaseBehaviour {
196
217
 
197
- readonly startCurve: MinMaxCurve;
198
- startMultiplier: number = 1;
218
+ type: string = "NeedleSize";
199
219
 
200
- constructor(startCurve: MinMaxCurve, startMultiplier: number = 1) {
201
- super();
202
- this.startCurve = startCurve;
203
- this.startMultiplier = startMultiplier;
220
+ update(particle: Particle, _delta: number): void {
221
+ const t = particle.age / particle.life;
222
+ let size = 1;
223
+ if (this.system.sizeOverLifetime.enabled)
224
+ size *= this.system.sizeOverLifetime.evaluate(t).x;
225
+ const scaleFactor = this.system.scale / this.system.cameraScale;
226
+ particle.size = particle.startSize * size * scaleFactor;
227
+ // console.log(particle.startSize, size, this.system.scale, this.system.cameraScale);
204
228
  }
205
229
  }
206
230
 
207
- declare type ParticleWithScale = Particle & { target: Object3D, start_scale: number };
231
+ const $startVelocity = Symbol("startVelocity");
232
+ const $gravityFactor = Symbol("gravityModifier");
233
+ const temp3 = new Vector3();
234
+ const temp4 = new Quaternion();
235
+
236
+ class VelocityBehaviour extends ParticleSystemBaseBehaviour {
237
+ type: string = "NeedleVelocity";
208
238
 
209
- class SizeBehaviour extends MinMaxCurveBehaviour {
239
+ private _gravityDirection = new Vector3();
210
240
 
211
- sizeOverLifetimeModule!: SizeOverLifetimeModule;
241
+ initialize(particle: Particle): void {
242
+ const scale = this.system.scale;
243
+ particle.startSpeed = this.system.main.startSpeed.evaluate(Math.random(), Math.random());
244
+ particle.velocity.copy(this.system.shape.getDirection(particle.position)).multiplyScalar(particle.startSpeed);
245
+ if (!particle[$startVelocity]) particle[$startVelocity] = particle.velocity.clone();
246
+ else particle[$startVelocity].copy(particle.velocity);
212
247
 
213
- cameraScale: number = 1;
248
+ let gravityFactor = Math.PI / scale;
249
+ gravityFactor = this.system.main.gravityModifier.evaluate(Math.random(), Math.random()) * gravityFactor;
250
+ particle[$gravityFactor] = gravityFactor;
251
+
252
+
253
+ this._gravityDirection.set(0, -1, 0).applyQuaternion(this.system.worldQuaternionInverted);
254
+ }
214
255
 
215
- applyBehaviour(particle: ParticleWithScale, _deltaTime: number, _index: number) {
216
- if (particle.target.type === "Sprite") {
217
- particle.radius = 1 / this.cameraScale;
256
+ update(particle: Particle, delta: number): void {
257
+ // const t = particle.age / particle.life;
258
+ // console.log(this.system.deltaTime, delta);
259
+
260
+ const baseVelocity = particle[$startVelocity];
261
+ let gravityFactor = particle[$gravityFactor];
262
+ if (gravityFactor !== 0) {
263
+ // gravityFactor *= -1;
264
+ temp3.copy(this._gravityDirection).multiplyScalar(gravityFactor * delta * Math.PI);
265
+ // Gizmos.DrawDirection(particle.position, temp3, 0xff0000, 0, false, 10);
266
+ baseVelocity.add(temp3);
218
267
  }
219
- else particle.radius = 1;
220
-
221
- // particle.target.scale.set(1,1,1);
222
- if (this.sizeOverLifetimeModule?.enabled) {
223
- const time = particle.age / particle.life;
224
- const scaleVector = particle.target.scale;
225
- this.sizeOverLifetimeModule.evaluate?.call(this.sizeOverLifetimeModule, time, scaleVector);
226
- // scaleVector.set(.1, .1, .1)
227
- particle.scale = particle.start_scale * scaleVector.x;
228
- // console.log(time, particle.scale);
268
+ particle.velocity.copy(baseVelocity);
269
+
270
+ const noise = this.system.noise;
271
+ if (noise.enabled) {
272
+ noise.apply(0, particle.position, particle.velocity, delta, particle.age, particle.life);
273
+ }
274
+
275
+ const velocity = this.system.velocityOverLifetime;
276
+ if (velocity.enabled) {
277
+ velocity.apply(0, particle.position, particle.velocity, delta, particle.age, particle.life);
229
278
  }
279
+ // particle.velocity.multiplyScalar(1-delta);
280
+
281
+ // const vel = this.system.velocityOverLifetime.evaluate(particle.age / particle.life);
230
282
  }
231
- initialize(particle: ParticleWithScale) {
232
- particle.scale = this.startCurve.evaluate(0, Math.random());// * this.startMultiplier;
233
- particle.start_scale = particle.scale;
283
+ }
234
284
 
285
+ class ColorBehaviour extends ParticleSystemBaseBehaviour {
286
+ type: string = "NeedleColor";
287
+
288
+ initialize(particle: Particle): void {
289
+ const col = this.system.main.startColor.evaluate(particle.age / particle.life, Math.random());
290
+ particle.startColor.set(col.r, col.g, col.b, col.alpha);
291
+ particle.color.copy(particle.startColor);
292
+ }
293
+
294
+ update(particle: Particle, _delta: number): void {
295
+ if (this.system.colorOverLifetime.enabled) {
296
+ const t = particle.age / particle.life;
297
+ const col = this.system.colorOverLifetime.color.evaluate(t);
298
+ particle.color.set(col.r, col.g, col.b, col.alpha).multiply(particle.startColor);
299
+ }
235
300
  }
236
301
  }
237
302
 
238
- declare type ParticleWithColor = Particle & { color_start: { r: number, g: number, b: number }, alpha_start: number };
303
+ class ParticleSystemInterface implements ParticleSystemParameters {
239
304
 
240
- class GradientBehaviour extends CustomBehaviour {
305
+ private readonly system: ParticleSystem;
306
+ private readonly emission: ParticleSystemEmissionOverTime;
307
+ private get anim(): TextureSheetAnimationModule {
308
+ return this.system.textureSheetAnimation;
309
+ }
241
310
 
242
- private startGradient: MinMaxGradient;
243
- private gradient?: MinMaxGradient;
311
+ constructor(system: ParticleSystem) {
312
+ this.system = system;
313
+ this.emission = new ParticleSystemEmissionOverTime(this.system);
314
+ }
244
315
 
245
- constructor(startGradient: MinMaxGradient, gradient?: MinMaxGradient) {
246
- super();
247
- this.startGradient = startGradient;
248
- this.gradient = gradient;
316
+ update() {
317
+ this.emission.update();
249
318
  }
250
319
 
251
- /** called from nebula */
252
- applyBehaviour(target: ParticleWithColor | Emitter, _deltaTime: number, _index: number) {
253
- // console.log(target, time, index)
254
- if (target instanceof Particle) {
255
- if (this.gradient) {
256
- const t = target.age / target.life;
257
- const ev = this.gradient.evaluate(t) as RGBAColor;
258
- const startColor = target.color_start;
259
- target.color.r = startColor.r * ev.r;
260
- target.color.g = startColor.g * ev.g;
261
- target.color.b = startColor.b * ev.b;
262
- target.alpha = ev.alpha * target.alpha_start;
263
- }
320
+ autoDestroy?: boolean | undefined;
321
+ get looping() { return this.system.main.loop; }
322
+ get duration() { return this.system.duration; }
323
+ get shape(): EmitterShape { return this.system.shape; }
324
+ get startLife() { return new MinMaxCurveFunction(this.system.main.startLifetime); }
325
+ get startSpeed() { return new MinMaxCurveFunction(this.system.main.startSpeed); }
326
+ get startRotation() { return new MinMaxCurveFunction(this.system.main.startRotation); }
327
+ get startSize() { return new MinMaxCurveFunction(this.system.main.startSize); }
328
+ startLength?: ValueGenerator | FunctionValueGenerator | undefined; /** start length is for trails */
329
+ get startColor() { return new ConstantColor(new Vector4(1, 1, 1, 1)); }
330
+ get emissionOverTime() { return this.emission; }
331
+ /** this is not supported yet */
332
+ get emissionOverDistance() { return new ParticleSystemEmissionOverDistance(this.system); }
333
+ /** not used - burst is controled via emissionOverTime */
334
+ emissionBursts?: BurstParameters[] | undefined;
335
+ onlyUsedByOther?: boolean | undefined;
336
+ readonly behaviors: Behavior[] = [];
337
+ get instancingGeometry() {
338
+ return this.system.renderer.getMesh().geometry;
339
+ }
340
+ get renderMode() {
341
+ if (this.system.trails["enabled"] === true) {
342
+ return RenderMode.Trail;
343
+ }
344
+ switch (this.system.renderer.renderMode) {
345
+ case ParticleSystemRenderMode.Billboard: return RenderMode.BillBoard;
346
+ // case ParticleSystemRenderMode.Stretch: return RenderMode.Stretch;
347
+ // case ParticleSystemRenderMode.HorizontalBillboard: return RenderMode.HorizontalBillboard;
348
+ // case ParticleSystemRenderMode.VerticalBillboard: return RenderMode.VerticalBillboard;
349
+ case ParticleSystemRenderMode.Mesh: return RenderMode.LocalSpace;
350
+ }
351
+ return RenderMode.BillBoard;
352
+ }
353
+ rendererEmitterSettings: TrailSettings = {
354
+ startLength: new ConstantValue(220),
355
+ followLocalOrigin: false,
356
+ };
357
+ get speedFactor() { return this.system.main.simulationSpeed; }
358
+ get texture(): THREE.Texture {
359
+ const mat = this.system.renderer.particleMaterial;
360
+ if (mat && mat["map"]) {
361
+ const tex = mat["map"]!;
362
+ tex.premultiplyAlpha = false;
363
+ tex.encoding = THREE.LinearEncoding;
364
+ return tex;
264
365
  }
366
+ return createFlatTexture(new RGBAColor(1, 1, 1, 1), 1)
265
367
  }
368
+ get startTileIndex() { return new TextureSheetStartFrameGenerator(this.system); }
369
+ get uTileCount() { return this.anim.enabled ? this.anim?.numTilesX : undefined }
370
+ get vTileCount() { return this.anim.enabled ? this.anim?.numTilesY : undefined }
371
+ get renderOrder() { return 1; }
372
+ get blending(): THREE.Blending { return this.system.renderer.particleMaterial?.blending ?? THREE.NormalBlending; }
373
+ get transparent() { return this.system.renderer.transparent; }
374
+ get worldSpace() { return this.system.main.simulationSpace === ParticleSystemSimulationSpace.World; }
266
375
 
267
- private id = Symbol('gradientId');
268
- private _internalId: number = 0;
376
+ }
269
377
 
270
- /** called from nebula */
271
- initialize(particle: ParticleWithColor) {
378
+ export class ParticleSystem extends Behaviour implements IParticleSystem {
272
379
 
273
- // console.log(particle);
274
- // const context = Context.Current;
275
- // const time = context.time.time;
276
- const ev = this.startGradient.evaluate(Math.random()) as RGBAColor;
277
- particle.color.r = ev.r;
278
- particle.color.g = ev.g;
279
- particle.color.b = ev.b;
280
- particle.alpha = ev.alpha
380
+ @serializeable(ColorOverLifetimeModule)
381
+ readonly colorOverLifetime!: ColorOverLifetimeModule;
281
382
 
282
- particle.age = 0;
383
+ @serializeable(MainModule)
384
+ readonly main!: MainModule;
283
385
 
284
- particle.color_start = { r: ev.r, g: ev.g, b: ev.b };
285
- particle.alpha_start = ev.alpha;
386
+ @serializeable(EmissionModule)
387
+ readonly emission!: EmissionModule;
286
388
 
287
- particle.useColor = true;
288
- particle.useAlpha = true;
389
+ @serializeable(SizeOverLifetimeModule)
390
+ readonly sizeOverLifetime!: SizeOverLifetimeModule;
289
391
 
290
- if (particle[this.id] === undefined)
291
- particle[this.id] = this._internalId++;
292
- }
293
- }
392
+ @serializeable(ShapeModule)
393
+ readonly shape!: ShapeModule;
294
394
 
395
+ @serializeable(NoiseModule)
396
+ readonly noise!: NoiseModule;
295
397
 
296
- declare type ParticleWithVelocity = Particle & { velocity_start: { x: number, y: number, u: number }, gravity: number };
398
+ // @serializeable(TrailModule)
399
+ readonly trails!: TrailModule;
297
400
 
298
- class VelocityBehaviour extends CustomBehaviour {
401
+ @serializeable(VelocityOverLifetimeModule)
402
+ readonly velocityOverLifetime!: VelocityOverLifetimeModule;
299
403
 
300
- container: Object3D;
404
+ @serializeable(TextureSheetAnimationModule)
405
+ readonly textureSheetAnimation!: TextureSheetAnimationModule;
301
406
 
302
- shape: ShapeModule;
303
- noise: NoiseModule;
407
+ @serializeable(RotationOverLifetimeModule)
408
+ readonly rotationOverLifetime!: RotationOverLifetimeModule;
304
409
 
305
- startSpeed: MinMaxCurve;
306
- startMultiplier: number = 1;
410
+ get renderer(): ParticleSystemRenderer {
411
+ return this._renderer;
412
+ }
307
413
 
308
- gravity?: MinMaxCurve;
309
- gravityModifierMultiplier: number = 1;
414
+ get currentParticles() {
415
+ return this._particleSystem?.particleNum ?? 0;
416
+ }
417
+ get maxParticles() {
418
+ return this.main.maxParticles;
419
+ }
420
+ get time() {
421
+ return this._time;
422
+ }
423
+ get duration() {
424
+ return this.main.duration;
425
+ }
426
+ get deltaTime() {
427
+ return this.context.time.deltaTime * this.main.simulationSpeed;
428
+ }
429
+ get scale() {
430
+ return this.gameObject.scale.x;
431
+ }
432
+ get cameraScale(): number {
433
+ return this._cameraScale;
434
+ }
435
+ private _cameraScale: number = 1;
310
436
 
311
- downDirection = new Vector3(0, -1, 0);
312
- private _temp: Vector3 = new Vector3();
437
+ get container(): Object3D {
438
+ return this._container!;
439
+ }
313
440
 
314
- constructor(container: Object3D, shape: ShapeModule, noise: NoiseModule, startCurve: MinMaxCurve, startMultiplier: number) {
315
- super();
316
- this.container = container;
317
- this.shape = shape;
318
- this.noise = noise;
319
- this.startSpeed = startCurve;
320
- this.startMultiplier = startMultiplier;
441
+ private __worldQuaternion = new Quaternion();
442
+ get worldQuaternion(): Quaternion {
443
+ return this.__worldQuaternion;
444
+ }
445
+ private _worldQuaternionInverted = new Quaternion();
446
+ get worldQuaternionInverted(): Quaternion {
447
+ return this._worldQuaternionInverted;
448
+ }
321
449
 
322
- const quat = getWorldQuaternion(container);
323
- this.downDirection.applyQuaternion(quat);
450
+ private _renderer!: ParticleSystemRenderer;
451
+
452
+ private _batchSystem?: BatchedParticleRenderer;
453
+ private _particleSystem?: _ParticleSystem;
454
+ private _interface!: ParticleSystemInterface;
455
+
456
+ // private _system!: System;
457
+ // private _emitter: Emitter;
458
+ // private _size!: SizeBehaviour;
459
+ private _container!: Object3D;
460
+ private _time: number = 0;
461
+
462
+ /** called from deserialization */
463
+ private set bursts(arr: ParticleBurst[]) {
464
+ for (let i = 0; i < arr.length; i++) {
465
+ const burst = arr[i];
466
+ if ((burst instanceof ParticleBurst) === false) {
467
+ const instance = new ParticleBurst();
468
+ assign(instance, burst);
469
+ arr[i] = instance;
470
+ }
471
+ }
472
+ this._bursts = arr;
324
473
  }
474
+ private _bursts?: ParticleBurst[];
325
475
 
326
- applyBehaviour(target: ParticleWithVelocity | Emitter, deltaTime: number, index: number) {
476
+ awake(): void {
477
+ this._renderer = this.gameObject.getComponent(ParticleSystemRenderer) as ParticleSystemRenderer;
327
478
 
328
- if (target instanceof Particle) {
329
- // target.velocity.x = target.velocity_start.x;
330
- // target.velocity.y = target.velocity_start.y;
331
- // target.velocity.z = target.velocity_start.z;
332
- if (target.gravity) {
333
- // get world down vector
334
- this._temp.copy(this.downDirection);
335
- this._temp.multiplyScalar(target.gravity * deltaTime);
336
- target.velocity.sub(this._temp);
337
- }
338
479
 
339
- if (this.noise) {
340
- this.noise.applyNoise(index, target.position, target.velocity, deltaTime, target.age, target.life);
341
- }
480
+ this._container = new Object3D();
481
+ this._container.matrixAutoUpdate = false;
482
+ if (this.main.simulationSpace == ParticleSystemSimulationSpace.Local) {
483
+ this.gameObject.add(this._container);
484
+ }
485
+ else {
486
+ this.context.scene.add(this._container);
342
487
  }
488
+ // else this._container = this.context.scene;
489
+
490
+ this._batchSystem = new BatchedParticleRenderer();
491
+ this._container.add(this._batchSystem);
492
+ this._interface = new ParticleSystemInterface(this);
493
+ this._particleSystem = new _ParticleSystem(this._batchSystem, this._interface);
494
+ this._particleSystem.addBehavior(new SizeBehaviour(this));
495
+ this._particleSystem.addBehavior(new VelocityBehaviour(this));
496
+ this._particleSystem.addBehavior(new ColorBehaviour(this));
497
+ this._particleSystem.addBehavior(new TextureSheetAnimationBehaviour(this));
498
+ this._particleSystem.addBehavior(new RotationBehaviour(this));
499
+ const emitter = this._particleSystem.emitter;
500
+ this.context.scene.add(emitter);
501
+
502
+ if (debug) {
503
+ console.log(this);
504
+ this.container.add(new AxesHelper(1))
505
+ }
506
+
507
+ // renderer.logRendererType = () => { };
508
+ // if (renderMode === ParticleSystemRenderMode.Billboard) {
509
+ // if (this.renderer.particleMaterial) {
510
+ // const sprite = renderer._body as Sprite;
511
+ // sprite.layers.disableAll();
512
+ // sprite.layers.set(2); // ignore raycasting particles
513
+ // sprite.renderOrder = 1;
514
+ // sprite.material.map = this.renderer.particleMaterial.map;
515
+ // sprite.material.transparent = true;
516
+ // // sprite.material.sizeAttenuation = false;
517
+ // sprite.material.blending = this.renderer.particleMaterial.blending;
518
+ // sprite.material.blendDst = this.renderer.particleMaterial.blendDst;
519
+ // sprite.material.blendDstAlpha = this.renderer.particleMaterial.blendDstAlpha;
520
+ // sprite.material.blendEquation = this.renderer.particleMaterial.blendEquation;
521
+ // sprite.material.blendEquationAlpha = this.renderer.particleMaterial.blendEquationAlpha;
522
+ // sprite.material.blendSrc = this.renderer.particleMaterial.blendSrc;
523
+ // sprite.material.blendSrcAlpha = this.renderer.particleMaterial.blendSrcAlpha;
524
+ // sprite.material.premultipliedAlpha = this.renderer.particleMaterial.premultipliedAlpha;
525
+ // sprite.material.depthWrite = false;
526
+ // sprite.material.depthTest = true;
527
+ // if (debug) console.log(sprite);
528
+ // }
529
+ // }
530
+
531
+ }
532
+
533
+ onEnable() {
534
+ this._time = 0;
535
+ }
536
+
537
+ onDisable() {
343
538
  }
344
539
 
345
- initialize(particle: ParticleWithVelocity) {
346
- const dir = this.shape.getDirection(particle.position);
347
- const speed = this.startSpeed.evaluate(0, Math.random()) * this.startMultiplier;
348
- particle.velocity.x = dir.x * speed;
349
- particle.velocity.y = dir.y * speed;
350
- particle.velocity.z = dir.z * speed;
351
- if (!particle.velocity_start)
352
- particle.velocity_start = {};
353
- particle.velocity_start.x = particle.velocity.x;
354
- particle.velocity_start.y = particle.velocity.y;
355
- particle.velocity_start.z = particle.velocity.z;
356
-
357
- if (this.gravity) {
358
- particle.gravity = this.gravity.evaluate(0, Math.random()) * this.gravityModifierMultiplier * 9.81;
540
+ onBeforeRender() {
541
+ if (this._bursts) {
542
+ this.emission.bursts = this._bursts;
359
543
  }
360
- else {
361
- particle.gravity = 0;
544
+
545
+ // sprite materials must be scaled in AR
546
+ const cam = this.context.mainCamera;
547
+ if (cam) {
548
+ const scale = getWorldScale(cam);
549
+ this._cameraScale = scale.x;
550
+ }
551
+
552
+ let rotationSource = this._container;
553
+ if (this.main.simulationSpace === ParticleSystemSimulationSpace.World)
554
+ rotationSource = this.gameObject;
555
+ getWorldQuaternion(rotationSource, this.__worldQuaternion)
556
+ this._worldQuaternionInverted.copy(this.__worldQuaternion).invert()
557
+
558
+ if (this._container && this.gameObject?.parent) {
559
+ const scale = getWorldScale(this.gameObject.parent);
560
+ scale.x = 1 / scale.x;
561
+ scale.y = 1 / scale.y;
562
+ scale.z = 1 / scale.z;
563
+ this._container.matrix.identity();
564
+ this._container.matrix.scale(scale);
362
565
  }
363
566
 
364
- // particle.acceleration.y = 1;
365
- // console.log(particle);
567
+ this.emission.system = this;
568
+ const dt = this.deltaTime;
569
+ this._interface.update();
570
+ this.shape.update(this.context, this.main.simulationSpace, this.gameObject);
571
+ this.noise.update(this.context);
572
+ this.velocityOverLifetime.update(this);
573
+ this._batchSystem?.update(dt);
574
+ this._time += dt;
575
+ if (this._time > this.duration) this._time = 0;
366
576
  }
367
577
 
368
- }
578
+ }
579
+
580
+
581
+
582
+
583
+
584
+
585
+
586
+
587
+
588
+
589
+
590
+
591
+
592
+
593
+ // abstract class CustomBehaviour extends Behaviour {
594
+ // abstract applyBehaviour(target: Particle | Emitter, time: number, index: number);
595
+ // abstract initialize(particle: Particle);
596
+ // }
597
+
598
+ // abstract class MinMaxCurveBehaviour extends CustomBehaviour {
599
+
600
+ // readonly startCurve: MinMaxCurve;
601
+ // startMultiplier: number = 1;
602
+
603
+ // constructor(startCurve: MinMaxCurve, startMultiplier: number = 1) {
604
+ // super();
605
+ // this.startCurve = startCurve;
606
+ // this.startMultiplier = startMultiplier;
607
+ // }
608
+ // }
609
+
610
+ // declare type ParticleWithScale = Particle & { target: Object3D, start_scale: number };
611
+
612
+ // class SizeBehaviour extends MinMaxCurveBehaviour {
613
+
614
+ // sizeOverLifetimeModule!: SizeOverLifetimeModule;
615
+
616
+ // cameraScale: number = 1;
617
+
618
+ // applyBehaviour(particle: ParticleWithScale, _deltaTime: number, _index: number) {
619
+ // if (particle.target.type === "Sprite") {
620
+ // particle.radius = 1 / this.cameraScale;
621
+ // }
622
+ // else particle.radius = 1;
623
+
624
+ // // particle.target.scale.set(1,1,1);
625
+ // if (this.sizeOverLifetimeModule?.enabled) {
626
+ // const time = particle.age / particle.life;
627
+ // const scaleVector = particle.target.scale;
628
+ // this.sizeOverLifetimeModule.evaluate?.call(this.sizeOverLifetimeModule, time, scaleVector);
629
+ // // scaleVector.set(.1, .1, .1)
630
+ // particle.scale = particle.start_scale * scaleVector.x;
631
+ // // console.log(time, particle.scale);
632
+ // }
633
+ // }
634
+ // initialize(particle: ParticleWithScale) {
635
+ // particle.scale = this.startCurve.evaluate(0, Math.random());// * this.startMultiplier;
636
+ // particle.start_scale = particle.scale;
637
+
638
+ // }
639
+ // }
640
+
641
+ // declare type ParticleWithColor = Particle & { color_start: { r: number, g: number, b: number }, alpha_start: number };
642
+
643
+ // class GradientBehaviour extends CustomBehaviour {
644
+
645
+ // private startGradient: MinMaxGradient;
646
+ // private gradient?: MinMaxGradient;
647
+
648
+ // constructor(startGradient: MinMaxGradient, gradient?: MinMaxGradient) {
649
+ // super();
650
+ // this.startGradient = startGradient;
651
+ // this.gradient = gradient;
652
+ // }
653
+
654
+ // /** called from nebula */
655
+ // applyBehaviour(target: ParticleWithColor | Emitter, _deltaTime: number, _index: number) {
656
+ // // console.log(target, time, index)
657
+ // if (target instanceof Particle) {
658
+ // if (this.gradient) {
659
+ // const t = target.age / target.life;
660
+ // const ev = this.gradient.evaluate(t) as RGBAColor;
661
+ // const startColor = target.color_start;
662
+ // target.color.r = startColor.r * ev.r;
663
+ // target.color.g = startColor.g * ev.g;
664
+ // target.color.b = startColor.b * ev.b;
665
+ // target.alpha = ev.alpha * target.alpha_start;
666
+ // }
667
+ // }
668
+ // }
669
+
670
+ // private id = Symbol('gradientId');
671
+ // private _internalId: number = 0;
672
+
673
+ // /** called from nebula */
674
+ // initialize(particle: ParticleWithColor) {
675
+
676
+ // // console.log(particle);
677
+ // // const context = Context.Current;
678
+ // // const time = context.time.time;
679
+ // const ev = this.startGradient.evaluate(Math.random()) as RGBAColor;
680
+ // particle.color.r = ev.r;
681
+ // particle.color.g = ev.g;
682
+ // particle.color.b = ev.b;
683
+ // particle.alpha = ev.alpha
684
+
685
+ // particle.age = 0;
686
+
687
+ // particle.color_start = { r: ev.r, g: ev.g, b: ev.b };
688
+ // particle.alpha_start = ev.alpha;
689
+
690
+ // particle.useColor = true;
691
+ // particle.useAlpha = true;
692
+
693
+ // if (particle[this.id] === undefined)
694
+ // particle[this.id] = this._internalId++;
695
+ // }
696
+ // }
697
+
698
+
699
+ // declare type ParticleWithVelocity = Particle & { velocity_start: { x: number, y: number, u: number }, gravity: number };
700
+
701
+ // class VelocityBehaviour extends CustomBehaviour {
702
+
703
+ // container: Object3D;
704
+
705
+ // shape: ShapeModule;
706
+ // noise: NoiseModule;
707
+
708
+ // startSpeed: MinMaxCurve;
709
+ // startMultiplier: number = 1;
710
+
711
+ // gravity?: MinMaxCurve;
712
+ // gravityModifierMultiplier: number = 1;
713
+
714
+ // downDirection = new Vector3();
715
+ // private _temp: Vector3 = new Vector3();
716
+
717
+ // constructor(container: Object3D, shape: ShapeModule, noise: NoiseModule, startCurve: MinMaxCurve, startMultiplier: number) {
718
+ // super();
719
+ // this.container = container;
720
+ // this.shape = shape;
721
+ // this.noise = noise;
722
+ // this.startSpeed = startCurve;
723
+ // this.startMultiplier = startMultiplier;
724
+
725
+ // }
726
+
727
+ // applyBehaviour(target: ParticleWithVelocity | Emitter, deltaTime: number, index: number) {
728
+
729
+ // if (target instanceof Particle) {
730
+ // // target.velocity.x = target.velocity_start.x;
731
+ // // target.velocity.y = target.velocity_start.y;
732
+ // // target.velocity.z = target.velocity_start.z;
733
+ // if (target.gravity !== 0 && this.gravity) {
734
+ // // get world down vector
735
+ // this._temp.copy(this.downDirection);
736
+ // this._temp.multiplyScalar(target.gravity * deltaTime);
737
+ // target.velocity.add(this._temp);
738
+ // }
739
+
740
+ // if (this.noise) {
741
+ // this.noise.applyNoise(index, target.position, target.velocity, deltaTime, target.age, target.life);
742
+ // }
743
+ // }
744
+ // }
745
+
746
+ // initialize(particle: ParticleWithVelocity) {
747
+ // const dir = this.shape.getDirection(particle.position);
748
+ // // dir.applyQuaternion(quat);
749
+ // const speed = this.startSpeed.evaluate(0, Math.random()) * this.startMultiplier;
750
+ // particle.velocity.x = dir.x * speed;
751
+ // particle.velocity.y = dir.y * speed;
752
+ // particle.velocity.z = dir.z * speed;
753
+ // if (!particle.velocity_start)
754
+ // particle.velocity_start = {};
755
+ // particle.velocity_start.x = particle.velocity.x;
756
+ // particle.velocity_start.y = particle.velocity.y;
757
+ // particle.velocity_start.z = particle.velocity.z;
758
+
759
+ // if (this.gravity) {
760
+ // particle.gravity = this.gravity.evaluate(Math.random(), Math.random()) * 9.81;
761
+ // }
762
+ // else {
763
+ // particle.gravity = 0;
764
+ // }
765
+
766
+ // const quat = getWorldQuaternion(this.container);
767
+ // this.downDirection.set(0, -1, 0).applyQuaternion(quat);
768
+ // }
769
+
770
+ // }