@needle-tools/engine 2.40.0-pre → 2.42.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 +18 -0
- package/dist/needle-engine.d.ts +332 -126
- package/dist/needle-engine.js +401 -401
- package/dist/needle-engine.js.map +4 -4
- package/dist/needle-engine.min.js +53 -53
- 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 +6 -1
- package/lib/engine/engine_element_loading.js.map +1 -1
- package/lib/engine/engine_gizmos.d.ts +8 -21
- package/lib/engine/engine_gizmos.js +51 -5
- package/lib/engine/engine_gizmos.js.map +1 -1
- package/lib/engine/engine_math.d.ts +9 -6
- package/lib/engine/engine_math.js +9 -0
- package/lib/engine/engine_math.js.map +1 -1
- package/lib/engine/engine_physics.js +14 -6
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_serialization_core.js +2 -0
- package/lib/engine/engine_serialization_core.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 +16 -1
- package/lib/engine/engine_three_utils.js +94 -54
- package/lib/engine/engine_three_utils.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/engine_utils.d.ts +1 -0
- package/lib/engine/engine_utils.js +3 -0
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine-components/AnimationCurve.js +20 -5
- package/lib/engine-components/AnimationCurve.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/Light.d.ts +2 -0
- package/lib/engine-components/Light.js +33 -9
- package/lib/engine-components/Light.js.map +1 -1
- package/lib/engine-components/ParticleSystem.d.ts +29 -26
- package/lib/engine-components/ParticleSystem.js +349 -187
- package/lib/engine-components/ParticleSystem.js.map +1 -1
- package/lib/engine-components/ParticleSystemModules.d.ts +243 -64
- package/lib/engine-components/ParticleSystemModules.js +722 -153
- 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/WebXR.js +8 -3
- package/lib/engine-components/WebXR.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +7 -0
- package/lib/engine-components/codegen/components.js +7 -0
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/package.json +4 -2
- package/src/engine/codegen/register_types.js +28 -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 +5 -1
- package/src/engine/engine_gizmos.ts +58 -6
- package/src/engine/engine_math.ts +19 -6
- package/src/engine/engine_physics.ts +17 -7
- package/src/engine/engine_serialization_core.ts +1 -0
- package/src/engine/engine_setup.ts +25 -2
- package/src/engine/engine_three_utils.ts +103 -62
- package/src/engine/engine_types.ts +8 -1
- package/src/engine/engine_utils.ts +5 -0
- package/src/engine-components/AnimationCurve.ts +25 -11
- package/src/engine-components/BoxHelperComponent.ts +12 -15
- package/src/engine-components/Light.ts +39 -8
- package/src/engine-components/ParticleSystem.ts +395 -199
- package/src/engine-components/ParticleSystemModules.ts +638 -152
- package/src/engine-components/ReflectionProbe.ts +37 -13
- package/src/engine-components/Renderer.ts +4 -2
- package/src/engine-components/WebXR.ts +11 -8
- package/src/engine-components/codegen/components.ts +7 -0
- package/src/engine/dist/engine_physics.js +0 -739
- package/src/engine/dist/engine_setup.js +0 -777
- package/src/engine-components/dist/CharacterController.js +0 -123
- package/src/engine-components/dist/RigidBody.js +0 -458
|
@@ -1,248 +1,444 @@
|
|
|
1
1
|
import { Behaviour, GameObject } from "./Component";
|
|
2
2
|
import * as THREE from "three";
|
|
3
|
-
import
|
|
4
|
-
import { Mathf } from "../engine/engine_math";
|
|
3
|
+
import { MainModule, EmissionModule, ShapeModule, ParticleSystemShapeType, MinMaxCurve, MinMaxGradient, ColorOverLifetimeModule, SizeOverLifetimeModule, NoiseModule, ParticleSystemSimulationSpace, ParticleBurst, IParticleSystem, ParticleSystemRenderMode } from "./ParticleSystemModules"
|
|
5
4
|
import { getParam } from "../engine/engine_utils";
|
|
6
5
|
|
|
6
|
+
// https://github.dev/creativelifeform/three-nebula
|
|
7
|
+
import System, { Emitter, Position, Life, SpriteRenderer, Particle, Body, MeshRenderer, } from 'three-nebula';
|
|
8
|
+
|
|
9
|
+
import { serializeable } from "../engine/engine_serialization";
|
|
10
|
+
import { Time } from "../engine/engine_time";
|
|
11
|
+
import { Context } from "../engine/engine_setup";
|
|
12
|
+
import { RGBAColor } from "./js-extensions/RGBAColor";
|
|
13
|
+
import { AxesHelper, BufferGeometry, Material, Mesh, Object3D, Sprite, SpriteMaterial, Vector3 } from "three";
|
|
14
|
+
import { getWorldQuaternion, getWorldScale } from "../engine/engine_three_utils";
|
|
15
|
+
import { assign } from "../engine/engine_serialization_core";
|
|
16
|
+
|
|
7
17
|
const debug = getParam("debugparticles");
|
|
8
18
|
|
|
9
|
-
class ParticleState {
|
|
10
|
-
age: number = 0;
|
|
11
|
-
lifetime: number = 0;
|
|
12
|
-
position!: THREE.Vector3;
|
|
13
|
-
velocity!: THREE.Vector3;
|
|
14
|
-
color!: THREE.Color;
|
|
15
|
-
}
|
|
16
19
|
|
|
17
20
|
export class ParticleSystemRenderer extends Behaviour {
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const tex = this.context.assets.findTexture(this.sharedMaterial);
|
|
22
|
-
if (tex) return tex;
|
|
23
|
-
}
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
22
|
+
@serializeable()
|
|
23
|
+
renderMode?: ParticleSystemRenderMode;
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return this.context.assets.findMesh(this.mesh);
|
|
30
|
-
}
|
|
25
|
+
@serializeable(Material)
|
|
26
|
+
particleMaterial?: SpriteMaterial;
|
|
31
27
|
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
// @serializeable(Mesh)
|
|
29
|
+
particleMesh?: Mesh | string;
|
|
34
30
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
|
|
32
|
+
getMesh() {
|
|
33
|
+
let geo: BufferGeometry | null = null;
|
|
34
|
+
if (this.particleMesh instanceof Mesh) {
|
|
35
|
+
geo = this.particleMesh.geometry;
|
|
36
|
+
}
|
|
37
|
+
if (geo === null) geo = new THREE.BoxGeometry(1, 1, 1);
|
|
38
|
+
const res = new Mesh(geo, this.particleMaterial);
|
|
39
|
+
return res;
|
|
38
40
|
}
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
export class ParticleSystem extends Behaviour {
|
|
43
|
+
export class ParticleSystem extends Behaviour implements IParticleSystem {
|
|
44
|
+
|
|
45
|
+
@serializeable(ColorOverLifetimeModule)
|
|
46
|
+
readonly colorOverLifetime!: ColorOverLifetimeModule;
|
|
42
47
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
shape!: Modules.ShapeModule;
|
|
48
|
+
@serializeable(MainModule)
|
|
49
|
+
readonly main!: MainModule;
|
|
46
50
|
|
|
47
|
-
|
|
51
|
+
@serializeable(EmissionModule)
|
|
52
|
+
readonly emission!: EmissionModule;
|
|
48
53
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
private particlesMesh!: THREE.Points;
|
|
54
|
+
@serializeable(SizeOverLifetimeModule)
|
|
55
|
+
readonly sizeOverLifetime!: SizeOverLifetimeModule;
|
|
52
56
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
private particleStates: Array<ParticleState> = [];
|
|
56
|
-
private activeCount: number = 0;
|
|
57
|
+
@serializeable(ShapeModule)
|
|
58
|
+
readonly shape!: ShapeModule;
|
|
57
59
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
@serializeable(NoiseModule)
|
|
61
|
+
readonly noise!: NoiseModule;
|
|
62
|
+
|
|
63
|
+
get renderer(): ParticleSystemRenderer {
|
|
64
|
+
return this._renderer;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
get currentParticles() {
|
|
68
|
+
return this._system?.getCount() ?? 0;
|
|
69
|
+
}
|
|
70
|
+
get maxParticles() {
|
|
71
|
+
return this.main.maxParticles;
|
|
72
|
+
}
|
|
73
|
+
get time() {
|
|
74
|
+
return this._time;
|
|
75
|
+
}
|
|
76
|
+
get duration() {
|
|
77
|
+
return this.main.duration;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private _renderer!: ParticleSystemRenderer;
|
|
81
|
+
private _system!: System;
|
|
82
|
+
private _emitter: Emitter;
|
|
83
|
+
private _size!: SizeBehaviour;
|
|
84
|
+
private _container?: Object3D;
|
|
85
|
+
private _time: number = 0;
|
|
86
|
+
|
|
87
|
+
/** called from deserialization */
|
|
88
|
+
private set bursts(arr: ParticleBurst[]) {
|
|
89
|
+
for (let i = 0; i < arr.length; i++) {
|
|
90
|
+
const burst = arr[i];
|
|
91
|
+
if ((burst instanceof ParticleBurst) === false) {
|
|
92
|
+
const instance = new ParticleBurst();
|
|
93
|
+
assign(instance, burst);
|
|
94
|
+
arr[i] = instance;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
this._bursts = arr;
|
|
98
|
+
}
|
|
99
|
+
private _bursts?: ParticleBurst[];
|
|
61
100
|
|
|
62
101
|
awake(): void {
|
|
63
|
-
this.
|
|
64
|
-
|
|
102
|
+
this._renderer = this.gameObject.getComponent(ParticleSystemRenderer) as ParticleSystemRenderer;
|
|
103
|
+
this._system = new System();
|
|
104
|
+
|
|
105
|
+
if (this.main.simulationSpace == ParticleSystemSimulationSpace.Local) {
|
|
106
|
+
this._container = new Object3D();
|
|
107
|
+
this._container.matrixAutoUpdate = false;
|
|
108
|
+
this.gameObject.add(this._container);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const container = this.main.simulationSpace == ParticleSystemSimulationSpace.Local ? this._container : this.context.scene;
|
|
112
|
+
|
|
113
|
+
if (debug) {
|
|
65
114
|
console.log(this);
|
|
66
|
-
|
|
115
|
+
this.gameObject.add(new AxesHelper(1))
|
|
116
|
+
}
|
|
117
|
+
const renderMode = this._renderer.renderMode;
|
|
118
|
+
let renderer: any = undefined;
|
|
119
|
+
|
|
120
|
+
switch (renderMode) {
|
|
121
|
+
case ParticleSystemRenderMode.Mesh:
|
|
122
|
+
// https://three-nebula-docs.netlify.app/class/src/renderer/meshrenderer.js~meshrenderer
|
|
123
|
+
// mesh renderer example: https://github.com/creativelifeform/three-nebula/blob/master/website/components/Examples/MeshRenderer/init.js
|
|
124
|
+
renderer = new MeshRenderer(container, THREE);
|
|
125
|
+
break;
|
|
126
|
+
case ParticleSystemRenderMode.Billboard:
|
|
127
|
+
renderer = new SpriteRenderer(container, THREE);
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
67
130
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (this.geometry) {
|
|
131
|
+
if (!renderer) {
|
|
132
|
+
console.error("No renderer for particle system");
|
|
71
133
|
return;
|
|
72
134
|
}
|
|
73
|
-
// console.log(this);
|
|
74
|
-
|
|
75
|
-
this.particleStates = [];
|
|
76
|
-
this.shapeRotation.setFromEuler(new THREE.Euler(this.shape.rotation.x, this.shape.rotation.y, this.shape.rotation.z));
|
|
77
|
-
|
|
78
|
-
// TODO: how to render particle mesh
|
|
79
|
-
// const assignedMesh = this.renderer?.getMesh(0);
|
|
80
|
-
// console.log(assignedMesh);
|
|
81
|
-
|
|
82
|
-
this.geometry = new THREE.BufferGeometry();
|
|
83
|
-
|
|
84
|
-
this.positionsArray = new Float32Array(this.main.maxParticles * 3);
|
|
85
|
-
this.positions = new THREE.Float32BufferAttribute(this.positionsArray, 3);
|
|
86
|
-
this.geometry.setAttribute('position', this.positions);
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
// const color = new THREE.Color();
|
|
90
|
-
const colorsArray = new Float32Array(this.main.maxParticles * 3);
|
|
91
|
-
for (let i = 0; i < colorsArray.length; i++) {
|
|
92
|
-
colorsArray[i * 3] = 1;
|
|
93
|
-
colorsArray[i * 3 + 1] = 1;
|
|
94
|
-
colorsArray[i * 3 + 2] = 1;
|
|
95
|
-
}
|
|
96
|
-
const colors = new THREE.Float32BufferAttribute(colorsArray, 3);
|
|
97
|
-
this.geometry.setAttribute('color', colors);
|
|
98
|
-
this.material = new THREE.PointsMaterial({ size: this.main.startSize, color: 0xffffff, vertexColors: true });
|
|
99
|
-
this.material.map = this.renderer.mainTexture;
|
|
100
|
-
// this.material.onBeforeCompile = (shader) => {
|
|
101
|
-
// shader.
|
|
102
|
-
// });
|
|
103
|
-
|
|
104
|
-
this.particlesMesh = new THREE.Points(this.geometry, this.material);
|
|
105
|
-
this.particlesMesh.layers.enable(2);
|
|
106
|
-
this.gameObject.add(this.particlesMesh);
|
|
107
|
-
|
|
108
|
-
this.activeCount = this.main.prewarm ? this.main.maxParticles : 0;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// update() {
|
|
112
|
-
// if (!this.geometry) return;
|
|
113
|
-
|
|
114
|
-
// const t = this.context.time.deltaTime;
|
|
115
|
-
// this.emit(t);
|
|
116
|
-
|
|
117
|
-
// for (let i = 0; i < this.activeCount; i += 1) {
|
|
118
|
-
// const ps = this.particleStates[i];
|
|
119
|
-
// if (!ps) continue;
|
|
120
|
-
// const vx = ps.velocity.x * t;
|
|
121
|
-
// const vy = ps.velocity.y * t;
|
|
122
|
-
// const vz = ps.velocity.z * t;
|
|
123
|
-
// ps.position.x += vx;
|
|
124
|
-
// ps.position.y += vy;
|
|
125
|
-
// ps.position.z += vz;
|
|
126
|
-
// this.updateOverLifetime(i, ps);
|
|
127
|
-
// this.geometry.attributes.position.setXYZ(i, ps.position.x, ps.position.y, ps.position.z);
|
|
128
|
-
// this.geometry.attributes.color.setXYZ(i, ps.color.r, ps.color.g, ps.color.b);
|
|
129
|
-
// }
|
|
130
|
-
// if (this.geometry) {
|
|
131
|
-
// this.geometry.attributes.position.needsUpdate = true;
|
|
132
|
-
// this.geometry.setDrawRange(0, this.activeCount);
|
|
133
|
-
// }
|
|
134
|
-
// }
|
|
135
|
-
|
|
136
|
-
emit(deltaTime: number) {
|
|
137
|
-
const count = this.activeCount;
|
|
138
|
-
for (let i = 0; i < count; i += 1) {
|
|
139
|
-
|
|
140
|
-
if (i >= this.particleStates.length) {
|
|
141
|
-
const ps = new ParticleState();
|
|
142
|
-
ps.lifetime = this.main.startLifetime ?? 1;
|
|
143
|
-
ps.position = new THREE.Vector3();
|
|
144
|
-
ps.velocity = new THREE.Vector3();
|
|
145
|
-
ps.color = new THREE.Color(1, 0, 0);
|
|
146
|
-
this.particleStates.push(ps);
|
|
147
|
-
this.initializeParticle(i, ps);
|
|
148
|
-
ps.age = ps.lifetime * Math.random();
|
|
149
|
-
}
|
|
150
|
-
const ps = this.particleStates[i];
|
|
151
135
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
136
|
+
renderer.logRendererType = () => { };
|
|
137
|
+
if (renderMode === ParticleSystemRenderMode.Billboard) {
|
|
138
|
+
if (this.renderer.particleMaterial) {
|
|
139
|
+
const sprite = renderer._body as Sprite;
|
|
140
|
+
sprite.layers.disableAll();
|
|
141
|
+
sprite.layers.set(2); // ignore raycasting particles
|
|
142
|
+
sprite.renderOrder = 1;
|
|
143
|
+
sprite.material.map = this.renderer.particleMaterial.map;
|
|
144
|
+
sprite.material.transparent = true;
|
|
145
|
+
// sprite.material.sizeAttenuation = false;
|
|
146
|
+
sprite.material.blending = this.renderer.particleMaterial.blending;
|
|
147
|
+
sprite.material.blendDst = this.renderer.particleMaterial.blendDst;
|
|
148
|
+
sprite.material.blendDstAlpha = this.renderer.particleMaterial.blendDstAlpha;
|
|
149
|
+
sprite.material.blendEquation = this.renderer.particleMaterial.blendEquation;
|
|
150
|
+
sprite.material.blendEquationAlpha = this.renderer.particleMaterial.blendEquationAlpha;
|
|
151
|
+
sprite.material.blendSrc = this.renderer.particleMaterial.blendSrc;
|
|
152
|
+
sprite.material.blendSrcAlpha = this.renderer.particleMaterial.blendSrcAlpha;
|
|
153
|
+
sprite.material.premultipliedAlpha = this.renderer.particleMaterial.premultipliedAlpha;
|
|
154
|
+
sprite.material.depthWrite = false;
|
|
155
|
+
sprite.material.depthTest = true;
|
|
156
|
+
if (debug) console.log(sprite);
|
|
157
157
|
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
this._system.addRenderer(renderer);
|
|
161
|
+
|
|
162
|
+
const initializers: Array<any> = [];
|
|
163
|
+
const behaviours: Array<any> = [];
|
|
164
|
+
|
|
165
|
+
const life = new Life();
|
|
166
|
+
life.lifePan = new MinMaxCurveSpan(this.main.startLifetime, 1);
|
|
167
|
+
initializers.push(life);
|
|
168
|
+
|
|
169
|
+
const shape = new Position(this.shape);
|
|
170
|
+
initializers.push(shape);
|
|
158
171
|
|
|
159
|
-
|
|
160
|
-
|
|
172
|
+
const size = this._size = new SizeBehaviour(this.main.startSize, this.main.startSizeMultiplier);
|
|
173
|
+
size.sizeOverLifetimeModule = this.sizeOverLifetime;
|
|
174
|
+
behaviours.push(size);
|
|
175
|
+
|
|
176
|
+
const color = new GradientBehaviour(this.main.startColor, this.colorOverLifetime?.enabled ? this.colorOverLifetime.color : undefined);
|
|
177
|
+
behaviours.push(color);
|
|
178
|
+
|
|
179
|
+
const velocity = new VelocityBehaviour(renderer.container, this.shape, this.noise, this.main.startSpeed, 1);
|
|
180
|
+
velocity.gravity = this.main.gravityModifier;
|
|
181
|
+
velocity.gravityModifierMultiplier = this.main.gravityModifierMultiplier;
|
|
182
|
+
behaviours.push(velocity);
|
|
183
|
+
|
|
184
|
+
if (renderMode === ParticleSystemRenderMode.Mesh) {
|
|
185
|
+
initializers.push(new Body(this._renderer.getMesh()))
|
|
161
186
|
}
|
|
162
|
-
|
|
163
|
-
this.
|
|
187
|
+
|
|
188
|
+
const emitter = this._emitter = new Emitter({});
|
|
189
|
+
emitter.setInitializers(initializers);
|
|
190
|
+
emitter.setBehaviours(behaviours);
|
|
191
|
+
emitter.setRate(this.emission);
|
|
192
|
+
emitter.damping = 0;
|
|
164
193
|
}
|
|
165
194
|
|
|
166
|
-
|
|
195
|
+
onEnable() {
|
|
196
|
+
this._emitter.emit();
|
|
197
|
+
this._system.addEmitter(this._emitter);
|
|
198
|
+
this._system.emit({ onStart: () => { }, onUpdate: () => { }, onEnd: () => { }, });
|
|
199
|
+
this._time = 0;
|
|
200
|
+
}
|
|
167
201
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
202
|
+
onDisable() {
|
|
203
|
+
this._system.removeEmitter(this._emitter);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
onBeforeRender() {
|
|
207
|
+
if (this._bursts) {
|
|
208
|
+
this.emission.bursts = this._bursts;
|
|
173
209
|
}
|
|
174
|
-
this.geometry.attributes.color.needsUpdate = true;
|
|
175
210
|
|
|
176
|
-
|
|
177
|
-
this.
|
|
211
|
+
// sprite materials must be scaled in AR
|
|
212
|
+
const cam = this.context.mainCamera;
|
|
213
|
+
if (cam) {
|
|
214
|
+
const scale = getWorldScale(cam);
|
|
215
|
+
this._size.cameraScale = scale.x;
|
|
216
|
+
}
|
|
178
217
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
218
|
+
if (this._container && this.gameObject?.parent) {
|
|
219
|
+
// this._container.matrix.copy(this.gameObject.matrixWorld);
|
|
220
|
+
// this._container.matrixWorld.copy(this.gameObject.matrixWorld);
|
|
221
|
+
|
|
222
|
+
const scale = getWorldScale(this.gameObject.parent);
|
|
223
|
+
scale.x = 1 / scale.x;
|
|
224
|
+
scale.y = 1 / scale.y;
|
|
225
|
+
scale.z = 1 / scale.z;
|
|
226
|
+
// console.log(scale);
|
|
227
|
+
// this._container.scale.copy(scale);
|
|
228
|
+
// // this._container.updateMatrix();
|
|
229
|
+
// // this._container.updateMatrixWorld();
|
|
230
|
+
// // // set scale to 1
|
|
231
|
+
this._container.matrix.identity();
|
|
232
|
+
this._container.matrix.scale(scale);
|
|
233
|
+
// this._container.matrixWorld.copy(this._container.matrix);
|
|
234
|
+
}
|
|
235
|
+
// this._system.time
|
|
236
|
+
// this._system.duration = this.main.duration;
|
|
237
|
+
this.emission.system = this;
|
|
238
|
+
this.shape.update(this.context, this.main.simulationSpace, this.gameObject);
|
|
239
|
+
this.noise.update(this.context);
|
|
240
|
+
this._system.update(this.context.time.deltaTime * this.main.simulationSpeed);
|
|
241
|
+
this._time += this.context.time.deltaTime;
|
|
242
|
+
if (this._time > this.duration) this._time = 0;
|
|
186
243
|
}
|
|
187
244
|
|
|
188
|
-
|
|
189
|
-
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
class MinMaxCurveSpan {
|
|
249
|
+
|
|
250
|
+
readonly time: Time;
|
|
251
|
+
readonly curve: MinMaxCurve;
|
|
252
|
+
multiplier: number = 1;
|
|
253
|
+
|
|
254
|
+
constructor(minMaxCurve: MinMaxCurve, multiplier: number = 1) {
|
|
255
|
+
this.time = Context.Current.time;
|
|
256
|
+
this.curve = minMaxCurve;
|
|
257
|
+
this.multiplier = multiplier;
|
|
190
258
|
}
|
|
191
259
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
260
|
+
/** called by nebula */
|
|
261
|
+
getValue(lerp?: number) {
|
|
262
|
+
const res = this.curve.evaluate(this.time.time, lerp) * this.multiplier;
|
|
263
|
+
return res;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
abstract class CustomBehaviour extends Behaviour {
|
|
268
|
+
abstract applyBehaviour(target: Particle | Emitter, time: number, index: number);
|
|
269
|
+
abstract initialize(particle: Particle);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
abstract class MinMaxCurveBehaviour extends CustomBehaviour {
|
|
273
|
+
|
|
274
|
+
readonly startCurve: MinMaxCurve;
|
|
275
|
+
startMultiplier: number = 1;
|
|
276
|
+
|
|
277
|
+
constructor(startCurve: MinMaxCurve, startMultiplier: number = 1) {
|
|
278
|
+
super();
|
|
279
|
+
this.startCurve = startCurve;
|
|
280
|
+
this.startMultiplier = startMultiplier;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
declare type ParticleWithScale = Particle & { target: Object3D, start_scale: number };
|
|
285
|
+
|
|
286
|
+
class SizeBehaviour extends MinMaxCurveBehaviour {
|
|
287
|
+
|
|
288
|
+
sizeOverLifetimeModule!: SizeOverLifetimeModule;
|
|
289
|
+
|
|
290
|
+
cameraScale: number = 1;
|
|
291
|
+
|
|
292
|
+
applyBehaviour(particle: ParticleWithScale, _deltaTime: number, _index: number) {
|
|
293
|
+
if (particle.target.type === "Sprite") {
|
|
294
|
+
particle.radius = 1 / this.cameraScale;
|
|
295
|
+
}
|
|
296
|
+
else particle.radius = 1;
|
|
297
|
+
|
|
298
|
+
// particle.target.scale.set(1,1,1);
|
|
299
|
+
if (this.sizeOverLifetimeModule?.enabled) {
|
|
300
|
+
const time = particle.age / particle.life;
|
|
301
|
+
const scaleVector = particle.target.scale;
|
|
302
|
+
this.sizeOverLifetimeModule.evaluate?.call(this.sizeOverLifetimeModule, time, scaleVector);
|
|
303
|
+
// scaleVector.set(.1, .1, .1)
|
|
304
|
+
particle.scale = particle.start_scale * scaleVector.x;
|
|
305
|
+
// console.log(time, particle.scale);
|
|
203
306
|
}
|
|
204
307
|
}
|
|
308
|
+
initialize(particle: ParticleWithScale) {
|
|
309
|
+
particle.scale = this.startCurve.evaluate(0, Math.random());// * this.startMultiplier;
|
|
310
|
+
particle.start_scale = particle.scale;
|
|
205
311
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
break;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
declare type ParticleWithColor = Particle & { color_start: { r: number, g: number, b: number }, alpha_start: number };
|
|
316
|
+
|
|
317
|
+
class GradientBehaviour extends CustomBehaviour {
|
|
318
|
+
|
|
319
|
+
private startGradient: MinMaxGradient;
|
|
320
|
+
private gradient?: MinMaxGradient;
|
|
321
|
+
|
|
322
|
+
constructor(startGradient: MinMaxGradient, gradient?: MinMaxGradient) {
|
|
323
|
+
super();
|
|
324
|
+
this.startGradient = startGradient;
|
|
325
|
+
this.gradient = gradient;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/** called from nebula */
|
|
329
|
+
applyBehaviour(target: ParticleWithColor | Emitter, _deltaTime: number, _index: number) {
|
|
330
|
+
// console.log(target, time, index)
|
|
331
|
+
if (target instanceof Particle) {
|
|
332
|
+
if (this.gradient) {
|
|
333
|
+
const t = target.age / target.life;
|
|
334
|
+
const ev = this.gradient.evaluate(t) as RGBAColor;
|
|
335
|
+
const startColor = target.color_start;
|
|
336
|
+
target.color.r = startColor.r * ev.r;
|
|
337
|
+
target.color.g = startColor.g * ev.g;
|
|
338
|
+
target.color.b = startColor.b * ev.b;
|
|
339
|
+
target.alpha = ev.alpha * target.alpha_start;
|
|
340
|
+
}
|
|
236
341
|
}
|
|
237
|
-
|
|
342
|
+
}
|
|
238
343
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
344
|
+
private id = Symbol('gradientId');
|
|
345
|
+
private _internalId: number = 0;
|
|
346
|
+
|
|
347
|
+
/** called from nebula */
|
|
348
|
+
initialize(particle: ParticleWithColor) {
|
|
349
|
+
|
|
350
|
+
// console.log(particle);
|
|
351
|
+
// const context = Context.Current;
|
|
352
|
+
// const time = context.time.time;
|
|
353
|
+
const ev = this.startGradient.evaluate(Math.random()) as RGBAColor;
|
|
354
|
+
particle.color.r = ev.r;
|
|
355
|
+
particle.color.g = ev.g;
|
|
356
|
+
particle.color.b = ev.b;
|
|
357
|
+
particle.alpha = ev.alpha
|
|
358
|
+
|
|
359
|
+
particle.age = 0;
|
|
360
|
+
|
|
361
|
+
particle.color_start = { r: ev.r, g: ev.g, b: ev.b };
|
|
362
|
+
particle.alpha_start = ev.alpha;
|
|
363
|
+
|
|
364
|
+
particle.useColor = true;
|
|
365
|
+
particle.useAlpha = true;
|
|
366
|
+
|
|
367
|
+
if (particle[this.id] === undefined)
|
|
368
|
+
particle[this.id] = this._internalId++;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
declare type ParticleWithVelocity = Particle & { velocity_start: { x: number, y: number, u: number }, gravity: number };
|
|
374
|
+
|
|
375
|
+
class VelocityBehaviour extends CustomBehaviour {
|
|
376
|
+
|
|
377
|
+
container: Object3D;
|
|
378
|
+
|
|
379
|
+
shape: ShapeModule;
|
|
380
|
+
noise: NoiseModule;
|
|
381
|
+
|
|
382
|
+
startSpeed: MinMaxCurve;
|
|
383
|
+
startMultiplier: number = 1;
|
|
384
|
+
|
|
385
|
+
gravity?: MinMaxCurve;
|
|
386
|
+
gravityModifierMultiplier: number = 1;
|
|
387
|
+
|
|
388
|
+
downDirection = new Vector3();
|
|
389
|
+
private _temp: Vector3 = new Vector3();
|
|
390
|
+
|
|
391
|
+
constructor(container: Object3D, shape: ShapeModule, noise: NoiseModule, startCurve: MinMaxCurve, startMultiplier: number) {
|
|
392
|
+
super();
|
|
393
|
+
this.container = container;
|
|
394
|
+
this.shape = shape;
|
|
395
|
+
this.noise = noise;
|
|
396
|
+
this.startSpeed = startCurve;
|
|
397
|
+
this.startMultiplier = startMultiplier;
|
|
398
|
+
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
applyBehaviour(target: ParticleWithVelocity | Emitter, deltaTime: number, index: number) {
|
|
402
|
+
|
|
403
|
+
if (target instanceof Particle) {
|
|
404
|
+
// target.velocity.x = target.velocity_start.x;
|
|
405
|
+
// target.velocity.y = target.velocity_start.y;
|
|
406
|
+
// target.velocity.z = target.velocity_start.z;
|
|
407
|
+
if (target.gravity !== 0 && this.gravity) {
|
|
408
|
+
// get world down vector
|
|
409
|
+
this._temp.copy(this.downDirection);
|
|
410
|
+
this._temp.multiplyScalar(target.gravity * deltaTime);
|
|
411
|
+
target.velocity.add(this._temp);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (this.noise) {
|
|
415
|
+
this.noise.applyNoise(index, target.position, target.velocity, deltaTime, target.age, target.life);
|
|
416
|
+
}
|
|
244
417
|
}
|
|
418
|
+
}
|
|
245
419
|
|
|
246
|
-
|
|
420
|
+
initialize(particle: ParticleWithVelocity) {
|
|
421
|
+
const dir = this.shape.getDirection(particle.position);
|
|
422
|
+
// dir.applyQuaternion(quat);
|
|
423
|
+
const speed = this.startSpeed.evaluate(0, Math.random()) * this.startMultiplier;
|
|
424
|
+
particle.velocity.x = dir.x * speed;
|
|
425
|
+
particle.velocity.y = dir.y * speed;
|
|
426
|
+
particle.velocity.z = dir.z * speed;
|
|
427
|
+
if (!particle.velocity_start)
|
|
428
|
+
particle.velocity_start = {};
|
|
429
|
+
particle.velocity_start.x = particle.velocity.x;
|
|
430
|
+
particle.velocity_start.y = particle.velocity.y;
|
|
431
|
+
particle.velocity_start.z = particle.velocity.z;
|
|
432
|
+
|
|
433
|
+
if (this.gravity) {
|
|
434
|
+
particle.gravity = this.gravity.evaluate(Math.random(), Math.random()) * 9.81;
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
particle.gravity = 0;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const quat = getWorldQuaternion(this.container);
|
|
441
|
+
this.downDirection.set(0, -1, 0).applyQuaternion(quat);
|
|
247
442
|
}
|
|
443
|
+
|
|
248
444
|
}
|