@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.
- package/CHANGELOG.md +24 -0
- package/dist/needle-engine.d.ts +226 -76
- package/dist/needle-engine.js +3847 -433
- package/dist/needle-engine.js.map +4 -4
- package/dist/needle-engine.min.js +51 -51
- package/dist/needle-engine.min.js.map +4 -4
- package/lib/engine/engine_element.js +1 -1
- package/lib/engine/engine_element.js.map +1 -1
- package/lib/engine/engine_element_loading.js +24 -3
- package/lib/engine/engine_element_loading.js.map +1 -1
- package/lib/engine/engine_gizmos.d.ts +8 -22
- package/lib/engine/engine_gizmos.js +37 -3
- package/lib/engine/engine_gizmos.js.map +1 -1
- package/lib/engine/engine_setup.d.ts +3 -0
- package/lib/engine/engine_setup.js +15 -0
- package/lib/engine/engine_setup.js.map +1 -1
- package/lib/engine/engine_three_utils.d.ts +17 -1
- package/lib/engine/engine_three_utils.js +104 -54
- package/lib/engine/engine_three_utils.js.map +1 -1
- package/lib/engine/engine_time.js +2 -0
- package/lib/engine/engine_time.js.map +1 -1
- package/lib/engine/engine_types.d.ts +6 -0
- package/lib/engine/engine_types.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js +42 -0
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js.map +1 -1
- package/lib/engine-components/Animation.js +9 -1
- package/lib/engine-components/Animation.js.map +1 -1
- package/lib/engine-components/AnimationCurve.js +2 -2
- package/lib/engine-components/AnimationCurve.js.map +1 -1
- package/lib/engine-components/AnimatorController.js +4 -1
- package/lib/engine-components/AnimatorController.js.map +1 -1
- package/lib/engine-components/BoxHelperComponent.js +9 -10
- package/lib/engine-components/BoxHelperComponent.js.map +1 -1
- package/lib/engine-components/Camera.d.ts +3 -0
- package/lib/engine-components/Camera.js +17 -9
- package/lib/engine-components/Camera.js.map +1 -1
- package/lib/engine-components/ParticleSystem.d.ts +41 -13
- package/lib/engine-components/ParticleSystem.js +587 -219
- package/lib/engine-components/ParticleSystem.js.map +1 -1
- package/lib/engine-components/ParticleSystemBehaviours.d.ts +0 -0
- package/lib/engine-components/ParticleSystemBehaviours.js +2 -0
- package/lib/engine-components/ParticleSystemBehaviours.js.map +1 -0
- package/lib/engine-components/ParticleSystemModules.d.ts +123 -22
- package/lib/engine-components/ParticleSystemModules.js +377 -60
- package/lib/engine-components/ParticleSystemModules.js.map +1 -1
- package/lib/engine-components/ReflectionProbe.js +29 -11
- package/lib/engine-components/ReflectionProbe.js.map +1 -1
- package/lib/engine-components/Renderer.d.ts +1 -0
- package/lib/engine-components/Renderer.js +4 -2
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +5 -0
- package/lib/engine-components/codegen/components.js +5 -0
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/js-extensions/RGBAColor.d.ts +1 -0
- package/lib/engine-components/js-extensions/RGBAColor.js +7 -0
- package/lib/engine-components/js-extensions/RGBAColor.js.map +1 -1
- package/package.json +3 -2
- package/src/engine/codegen/register_types.js +20 -0
- package/src/engine/dist/engine_three_utils.js +279 -0
- package/src/engine/engine_element.ts +1 -1
- package/src/engine/engine_element_loading.ts +23 -2
- package/src/engine/engine_gizmos.ts +45 -8
- package/src/engine/engine_setup.ts +25 -2
- package/src/engine/engine_three_utils.ts +113 -63
- package/src/engine/engine_time.ts +1 -0
- package/src/engine/engine_types.ts +8 -1
- package/src/engine/extensions/NEEDLE_techniques_webgl.ts +43 -1
- package/src/engine-components/Animation.ts +7 -1
- package/src/engine-components/AnimationCurve.ts +2 -2
- package/src/engine-components/AnimatorController.ts +5 -1
- package/src/engine-components/BoxHelperComponent.ts +12 -15
- package/src/engine-components/Camera.ts +17 -10
- package/src/engine-components/ParticleSystem.ts +660 -258
- package/src/engine-components/ParticleSystemBehaviours.ts +0 -0
- package/src/engine-components/ParticleSystemModules.ts +379 -64
- package/src/engine-components/ReflectionProbe.ts +37 -13
- package/src/engine-components/Renderer.ts +4 -2
- package/src/engine-components/codegen/components.ts +5 -0
- 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
|
-
|
|
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
|
-
|
|
29
|
+
// @serializeable(Mesh)
|
|
30
|
+
particleMesh?: Mesh | string;
|
|
48
31
|
|
|
49
|
-
|
|
50
|
-
|
|
32
|
+
get transparent(): boolean {
|
|
33
|
+
const res = this.particleMaterial?.transparent ?? false;
|
|
34
|
+
// console.log(res, this.particleMaterial);
|
|
35
|
+
return res;
|
|
36
|
+
}
|
|
51
37
|
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
56
|
-
emission!: EmissionModule;
|
|
49
|
+
class MinMaxCurveFunction implements FunctionValueGenerator {
|
|
57
50
|
|
|
58
|
-
|
|
59
|
-
sizeOverLifetime!: SizeOverLifetimeModule;
|
|
51
|
+
private _curve: MinMaxCurve;
|
|
60
52
|
|
|
61
|
-
|
|
62
|
-
shape!: ShapeModule;
|
|
53
|
+
constructor(curve: MinMaxCurve) { this._curve = curve; }
|
|
63
54
|
|
|
64
|
-
|
|
65
|
-
noise!: NoiseModule;
|
|
55
|
+
type: "function" = "function";
|
|
66
56
|
|
|
67
|
-
|
|
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
|
-
|
|
70
|
-
private _emitter: Emitter;
|
|
71
|
-
private _size!: SizeBehaviour;
|
|
68
|
+
class MinMaxGradientFunction implements FunctionColorGenerator {
|
|
72
69
|
|
|
73
|
-
|
|
74
|
-
if (debug) {
|
|
75
|
-
console.log(this);
|
|
76
|
-
this.gameObject.add(new AxesHelper(1))
|
|
77
|
-
}
|
|
70
|
+
private _curve: MinMaxGradient;
|
|
78
71
|
|
|
79
|
-
|
|
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
|
-
|
|
74
|
+
type: "function" = "function";
|
|
108
75
|
|
|
109
|
-
|
|
110
|
-
const
|
|
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
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
-
|
|
119
|
-
initializers.push(shape);
|
|
101
|
+
abstract genValue(): number;
|
|
120
102
|
|
|
121
|
-
|
|
122
|
-
size.sizeOverLifetimeModule = this.sizeOverLifetime;
|
|
123
|
-
behaviours.push(size);
|
|
103
|
+
readonly system: ParticleSystem;
|
|
124
104
|
|
|
125
|
-
|
|
126
|
-
|
|
105
|
+
constructor(system: ParticleSystem) {
|
|
106
|
+
this.system = system;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
127
109
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
110
|
+
class TextureSheetStartFrameGenerator extends BaseValueGenerator {
|
|
111
|
+
genValue(): number {
|
|
112
|
+
return this.system.textureSheetAnimation.getStartIndex();
|
|
113
|
+
}
|
|
132
114
|
|
|
115
|
+
}
|
|
133
116
|
|
|
134
|
-
|
|
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
|
-
|
|
142
|
-
|
|
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
|
-
|
|
148
|
-
this.
|
|
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
|
-
|
|
152
|
-
this.
|
|
153
|
-
|
|
154
|
-
this.
|
|
155
|
-
this.
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
const
|
|
162
|
-
|
|
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
|
-
|
|
167
|
+
constructor(ps: ParticleSystem) {
|
|
168
|
+
this.system = ps;
|
|
169
|
+
}
|
|
172
170
|
|
|
173
|
-
|
|
174
|
-
readonly curve: MinMaxCurve;
|
|
175
|
-
multiplier: number = 1;
|
|
171
|
+
abstract type: string;
|
|
176
172
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
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
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
|
|
216
|
+
class SizeBehaviour extends ParticleSystemBaseBehaviour {
|
|
196
217
|
|
|
197
|
-
|
|
198
|
-
startMultiplier: number = 1;
|
|
218
|
+
type: string = "NeedleSize";
|
|
199
219
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
this.
|
|
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
|
-
|
|
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
|
-
|
|
239
|
+
private _gravityDirection = new Vector3();
|
|
210
240
|
|
|
211
|
-
|
|
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
|
-
|
|
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
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
if (
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
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
|
-
|
|
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
|
-
|
|
303
|
+
class ParticleSystemInterface implements ParticleSystemParameters {
|
|
239
304
|
|
|
240
|
-
|
|
305
|
+
private readonly system: ParticleSystem;
|
|
306
|
+
private readonly emission: ParticleSystemEmissionOverTime;
|
|
307
|
+
private get anim(): TextureSheetAnimationModule {
|
|
308
|
+
return this.system.textureSheetAnimation;
|
|
309
|
+
}
|
|
241
310
|
|
|
242
|
-
|
|
243
|
-
|
|
311
|
+
constructor(system: ParticleSystem) {
|
|
312
|
+
this.system = system;
|
|
313
|
+
this.emission = new ParticleSystemEmissionOverTime(this.system);
|
|
314
|
+
}
|
|
244
315
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
this.startGradient = startGradient;
|
|
248
|
-
this.gradient = gradient;
|
|
316
|
+
update() {
|
|
317
|
+
this.emission.update();
|
|
249
318
|
}
|
|
250
319
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
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
|
-
|
|
268
|
-
private _internalId: number = 0;
|
|
376
|
+
}
|
|
269
377
|
|
|
270
|
-
|
|
271
|
-
initialize(particle: ParticleWithColor) {
|
|
378
|
+
export class ParticleSystem extends Behaviour implements IParticleSystem {
|
|
272
379
|
|
|
273
|
-
|
|
274
|
-
|
|
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
|
-
|
|
383
|
+
@serializeable(MainModule)
|
|
384
|
+
readonly main!: MainModule;
|
|
283
385
|
|
|
284
|
-
|
|
285
|
-
|
|
386
|
+
@serializeable(EmissionModule)
|
|
387
|
+
readonly emission!: EmissionModule;
|
|
286
388
|
|
|
287
|
-
|
|
288
|
-
|
|
389
|
+
@serializeable(SizeOverLifetimeModule)
|
|
390
|
+
readonly sizeOverLifetime!: SizeOverLifetimeModule;
|
|
289
391
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
}
|
|
293
|
-
}
|
|
392
|
+
@serializeable(ShapeModule)
|
|
393
|
+
readonly shape!: ShapeModule;
|
|
294
394
|
|
|
395
|
+
@serializeable(NoiseModule)
|
|
396
|
+
readonly noise!: NoiseModule;
|
|
295
397
|
|
|
296
|
-
|
|
398
|
+
// @serializeable(TrailModule)
|
|
399
|
+
readonly trails!: TrailModule;
|
|
297
400
|
|
|
298
|
-
|
|
401
|
+
@serializeable(VelocityOverLifetimeModule)
|
|
402
|
+
readonly velocityOverLifetime!: VelocityOverLifetimeModule;
|
|
299
403
|
|
|
300
|
-
|
|
404
|
+
@serializeable(TextureSheetAnimationModule)
|
|
405
|
+
readonly textureSheetAnimation!: TextureSheetAnimationModule;
|
|
301
406
|
|
|
302
|
-
|
|
303
|
-
|
|
407
|
+
@serializeable(RotationOverLifetimeModule)
|
|
408
|
+
readonly rotationOverLifetime!: RotationOverLifetimeModule;
|
|
304
409
|
|
|
305
|
-
|
|
306
|
-
|
|
410
|
+
get renderer(): ParticleSystemRenderer {
|
|
411
|
+
return this._renderer;
|
|
412
|
+
}
|
|
307
413
|
|
|
308
|
-
|
|
309
|
-
|
|
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
|
-
|
|
312
|
-
|
|
437
|
+
get container(): Object3D {
|
|
438
|
+
return this._container!;
|
|
439
|
+
}
|
|
313
440
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
this.
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
this.
|
|
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
|
-
|
|
323
|
-
|
|
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
|
-
|
|
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
|
-
|
|
340
|
-
|
|
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
|
-
|
|
346
|
-
|
|
347
|
-
|
|
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
|
-
|
|
361
|
-
|
|
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
|
-
|
|
365
|
-
|
|
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
|
+
// }
|