@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
|
File without changes
|
|
@@ -1,16 +1,38 @@
|
|
|
1
1
|
import { init } from "@dimforge/rapier3d-compat";
|
|
2
2
|
import * as THREE from "three";
|
|
3
|
-
import { Color, Matrix4, Object3D, Vector3 } from "three";
|
|
3
|
+
import { Color, Matrix4, Object3D, PointLightShadow, Quaternion, Vector3 } from "three";
|
|
4
4
|
import { Mathf } from "../engine/engine_math";
|
|
5
5
|
import { serializeable } from "../engine/engine_serialization";
|
|
6
6
|
import { RGBAColor } from "./js-extensions/RGBAColor";
|
|
7
7
|
import { AnimationCurve } from "./AnimationCurve";
|
|
8
8
|
import { Vec3 } from "../engine/engine_types";
|
|
9
|
+
import { EmitterShape, FrameOverLife, Particle, ShapeJSON } from "three.quarks";
|
|
9
10
|
|
|
10
11
|
declare type Color4 = { r: number, g: number, b: number, a: number };
|
|
11
12
|
declare type ColorKey = { time: number, color: Color4 };
|
|
12
13
|
declare type AlphaKey = { time: number, alpha: number };
|
|
13
14
|
|
|
15
|
+
export interface IParticleSystem {
|
|
16
|
+
get currentParticles(): number;
|
|
17
|
+
get maxParticles(): number;
|
|
18
|
+
get time(): number;
|
|
19
|
+
get duration(): number;
|
|
20
|
+
readonly main: MainModule;
|
|
21
|
+
get container(): Object3D;
|
|
22
|
+
get worldQuaternion(): Quaternion;
|
|
23
|
+
get worldQuaternionInverted(): Quaternion;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export enum ParticleSystemRenderMode {
|
|
27
|
+
Billboard = 0,
|
|
28
|
+
// Stretch = 1,
|
|
29
|
+
// HorizontalBillboard = 2,
|
|
30
|
+
// VerticalBillboard = 3,
|
|
31
|
+
Mesh = 4,
|
|
32
|
+
// None = 5,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
14
36
|
export class Gradient {
|
|
15
37
|
@serializeable()
|
|
16
38
|
alphaKeys!: Array<AlphaKey>;
|
|
@@ -147,14 +169,14 @@ export class MinMaxCurve {
|
|
|
147
169
|
case ParticleSystemCurveMode.Constant:
|
|
148
170
|
return this.constant;
|
|
149
171
|
case ParticleSystemCurveMode.Curve:
|
|
150
|
-
t01
|
|
151
|
-
return this.curve!.evaluate(t01)
|
|
172
|
+
t01 = Mathf.clamp01(t01);
|
|
173
|
+
return this.curve!.evaluate(t01) * this.curveMultiplier!;
|
|
152
174
|
case ParticleSystemCurveMode.TwoCurves:
|
|
153
175
|
const t1 = t01 * this.curveMin!.duration;
|
|
154
176
|
const t2 = t01 * this.curveMax!.duration;
|
|
155
|
-
return Mathf.lerp(this.curveMin!.evaluate(t1), this.curveMax!.evaluate(t2), t % 1)
|
|
177
|
+
return Mathf.lerp(this.curveMin!.evaluate(t1), this.curveMax!.evaluate(t2), t % 1) * this.curveMultiplier!;
|
|
156
178
|
case ParticleSystemCurveMode.TwoConstants:
|
|
157
|
-
return Mathf.lerp(this.constantMin, this.constantMax, t % 1)
|
|
179
|
+
return Mathf.lerp(this.constantMin, this.constantMax, t % 1)
|
|
158
180
|
default:
|
|
159
181
|
this.curveMax!.evaluate(t01) * this.curveMultiplier!;
|
|
160
182
|
break;
|
|
@@ -178,7 +200,8 @@ export class MinMaxGradient {
|
|
|
178
200
|
@serializeable(Gradient)
|
|
179
201
|
gradientMax!: Gradient;
|
|
180
202
|
|
|
181
|
-
private _temp: RGBAColor = new RGBAColor(0, 0, 0, 1);
|
|
203
|
+
private static _temp: RGBAColor = new RGBAColor(0, 0, 0, 1);
|
|
204
|
+
private static _temp2: RGBAColor = new RGBAColor(0, 0, 0, 1);
|
|
182
205
|
|
|
183
206
|
evaluate(t01: number, lerpFactor?: number): RGBAColor {
|
|
184
207
|
const t = lerpFactor === undefined ? Math.random() : lerpFactor;
|
|
@@ -186,15 +209,22 @@ export class MinMaxGradient {
|
|
|
186
209
|
case ParticleSystemGradientMode.Color:
|
|
187
210
|
return this.color;
|
|
188
211
|
case ParticleSystemGradientMode.Gradient:
|
|
189
|
-
this.gradient.evaluate(t01,
|
|
190
|
-
return
|
|
212
|
+
this.gradient.evaluate(t01, MinMaxGradient._temp);
|
|
213
|
+
return MinMaxGradient._temp
|
|
191
214
|
case ParticleSystemGradientMode.TwoColors:
|
|
192
|
-
|
|
215
|
+
const col1 = MinMaxGradient._temp.lerpColors(this.colorMin, this.colorMax, t);
|
|
216
|
+
return col1;
|
|
217
|
+
case ParticleSystemGradientMode.TwoGradients:
|
|
218
|
+
const t2 = Math.random();
|
|
219
|
+
this.gradientMin.evaluate(t2, MinMaxGradient._temp);
|
|
220
|
+
this.gradientMax.evaluate(t2, MinMaxGradient._temp2);
|
|
221
|
+
return MinMaxGradient._temp.lerp(MinMaxGradient._temp2, t);
|
|
222
|
+
|
|
193
223
|
}
|
|
194
224
|
// console.warn("Not implemented", ParticleSystemGradientMode[this.mode]);
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
return
|
|
225
|
+
MinMaxGradient._temp.set(0xff00ff)
|
|
226
|
+
MinMaxGradient._temp.alpha = 1;
|
|
227
|
+
return MinMaxGradient._temp;
|
|
198
228
|
}
|
|
199
229
|
}
|
|
200
230
|
|
|
@@ -262,44 +292,106 @@ export class MainModule {
|
|
|
262
292
|
useUnscaledTime!: boolean;
|
|
263
293
|
}
|
|
264
294
|
|
|
295
|
+
|
|
296
|
+
export class ParticleBurst {
|
|
297
|
+
cycleCount!: number;
|
|
298
|
+
maxCount!: number;
|
|
299
|
+
minCount!: number;
|
|
300
|
+
probability!: number;
|
|
301
|
+
repeatInterval!: number;
|
|
302
|
+
time!: number;
|
|
303
|
+
count!: {
|
|
304
|
+
constant: number;
|
|
305
|
+
constantMax: number;
|
|
306
|
+
constantMin: number;
|
|
307
|
+
curve?: AnimationCurve;
|
|
308
|
+
curveMax?: AnimationCurve;
|
|
309
|
+
curveMin?: AnimationCurve;
|
|
310
|
+
curveMultiplier?: number;
|
|
311
|
+
mode: ParticleSystemCurveMode;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
private _performed: number = 0;
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
reset() {
|
|
319
|
+
this._performed = 0;
|
|
320
|
+
}
|
|
321
|
+
run(time: number): number {
|
|
322
|
+
if (time <= this.time) {
|
|
323
|
+
this.reset();
|
|
324
|
+
return 0;
|
|
325
|
+
}
|
|
326
|
+
let amount = 0;
|
|
327
|
+
if (this.cycleCount === 0 || this._performed < this.cycleCount) {
|
|
328
|
+
const nextTime = this.time + this.repeatInterval * this._performed;
|
|
329
|
+
if (time >= nextTime) {
|
|
330
|
+
this._performed += 1;
|
|
331
|
+
if (Math.random() < this.probability) {
|
|
332
|
+
switch (this.count.mode) {
|
|
333
|
+
case ParticleSystemCurveMode.Constant:
|
|
334
|
+
amount = this.count.constant;
|
|
335
|
+
break;
|
|
336
|
+
case ParticleSystemCurveMode.TwoConstants:
|
|
337
|
+
amount = Mathf.lerp(this.count.constantMin, this.count.constantMax, Math.random());
|
|
338
|
+
break;
|
|
339
|
+
case ParticleSystemCurveMode.Curve:
|
|
340
|
+
amount = this.count.curve!.evaluate(Math.random());
|
|
341
|
+
break;
|
|
342
|
+
case ParticleSystemCurveMode.TwoCurves:
|
|
343
|
+
const t = Math.random();
|
|
344
|
+
amount = Mathf.lerp(this.count.curveMin!.evaluate(t), this.count.curveMax!.evaluate(t), Math.random());
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return amount;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
265
354
|
export class EmissionModule {
|
|
266
|
-
|
|
355
|
+
|
|
356
|
+
@serializeable()
|
|
267
357
|
enabled!: boolean;
|
|
268
358
|
|
|
359
|
+
|
|
360
|
+
get burstCount() {
|
|
361
|
+
return this.bursts?.length ?? 0;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
@serializeable()
|
|
365
|
+
bursts!: ParticleBurst[];
|
|
366
|
+
|
|
269
367
|
@serializeable(MinMaxCurve)
|
|
270
368
|
rateOverTime!: MinMaxCurve;
|
|
369
|
+
@serializeable()
|
|
271
370
|
rateOverTimeMultiplier!: number;
|
|
272
371
|
|
|
273
372
|
@serializeable(MinMaxCurve)
|
|
274
373
|
rateOverDistance!: MinMaxCurve;
|
|
374
|
+
@serializeable()
|
|
275
375
|
rateOverDistanceMultiplier!: number;
|
|
276
376
|
|
|
277
377
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
private _time: number = 0;
|
|
282
|
-
private _summed: number = 0;
|
|
283
|
-
// private _didEmit: boolean = false;
|
|
378
|
+
/** set from system */
|
|
379
|
+
system!: IParticleSystem;
|
|
380
|
+
get time() { return this.system.time; }
|
|
284
381
|
|
|
285
|
-
/** called by nebula */
|
|
286
|
-
init() {
|
|
287
|
-
}
|
|
288
382
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
if (this.
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
const amount = Math.floor(this._summed);
|
|
302
|
-
this._summed -= amount;
|
|
383
|
+
getBurst() {
|
|
384
|
+
let amount = 0;
|
|
385
|
+
if (this.burstCount > 0) {
|
|
386
|
+
for (let i = 0; i < this.burstCount; i++) {
|
|
387
|
+
const burst = this.bursts[i];
|
|
388
|
+
if (burst.time >= this.time) {
|
|
389
|
+
burst.reset();
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
amount += Math.round(burst.run(this.time));
|
|
393
|
+
}
|
|
394
|
+
}
|
|
303
395
|
return amount;
|
|
304
396
|
}
|
|
305
397
|
}
|
|
@@ -317,18 +409,26 @@ export class SizeOverLifetimeModule {
|
|
|
317
409
|
size!: MinMaxCurve;
|
|
318
410
|
sizeMultiplier!: number;
|
|
319
411
|
@serializeable(MinMaxCurve)
|
|
320
|
-
|
|
321
|
-
|
|
412
|
+
x!: MinMaxCurve;
|
|
413
|
+
xMultiplier!: number;
|
|
322
414
|
@serializeable(MinMaxCurve)
|
|
323
|
-
|
|
324
|
-
|
|
415
|
+
y!: MinMaxCurve;
|
|
416
|
+
yMultiplier!: number;
|
|
325
417
|
@serializeable(MinMaxCurve)
|
|
326
|
-
|
|
327
|
-
|
|
418
|
+
z!: MinMaxCurve;
|
|
419
|
+
zMultiplier!: number;
|
|
328
420
|
|
|
329
421
|
private _time: number = 0;
|
|
422
|
+
private _temp = new Vector3();
|
|
423
|
+
|
|
424
|
+
evaluate(t01: number, target?: Vec3) {
|
|
425
|
+
if (!target) target = this._temp;
|
|
426
|
+
|
|
427
|
+
if (!this.enabled) {
|
|
428
|
+
target.x = target.y = target.z = 1;
|
|
429
|
+
return target;
|
|
430
|
+
}
|
|
330
431
|
|
|
331
|
-
evaluate(t01: number, target: Vec3) {
|
|
332
432
|
if (!this.separateAxes) {
|
|
333
433
|
const scale = this.size.evaluate(t01) * this.sizeMultiplier;
|
|
334
434
|
target.x = scale;
|
|
@@ -336,15 +436,31 @@ export class SizeOverLifetimeModule {
|
|
|
336
436
|
// target.z = scale;
|
|
337
437
|
}
|
|
338
438
|
else {
|
|
339
|
-
target.x = this.
|
|
340
|
-
|
|
341
|
-
|
|
439
|
+
target.x = this.x.evaluate(t01) * this.xMultiplier;
|
|
440
|
+
target.y = this.y.evaluate(t01) * this.yMultiplier;
|
|
441
|
+
target.z = this.z.evaluate(t01) * this.zMultiplier;
|
|
342
442
|
}
|
|
343
443
|
return target;
|
|
344
444
|
}
|
|
345
445
|
}
|
|
346
446
|
|
|
347
|
-
export class ShapeModule {
|
|
447
|
+
export class ShapeModule implements EmitterShape {
|
|
448
|
+
|
|
449
|
+
get type(): string {
|
|
450
|
+
return ParticleSystemShapeType[this.shapeType];
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
initialize(particle: Particle): void {
|
|
454
|
+
this.getPosition();
|
|
455
|
+
particle.position.copy(this._vector);
|
|
456
|
+
}
|
|
457
|
+
toJSON(): ShapeJSON {
|
|
458
|
+
return this;
|
|
459
|
+
}
|
|
460
|
+
clone(): EmitterShape {
|
|
461
|
+
return new ShapeModule();
|
|
462
|
+
}
|
|
463
|
+
|
|
348
464
|
@serializeable()
|
|
349
465
|
shapeType: ParticleSystemShapeType = ParticleSystemShapeType.Box;
|
|
350
466
|
@serializeable()
|
|
@@ -399,7 +515,6 @@ export class ShapeModule {
|
|
|
399
515
|
get vector() {
|
|
400
516
|
return this._vector;
|
|
401
517
|
}
|
|
402
|
-
/** called by nebula */
|
|
403
518
|
getPosition(): void {
|
|
404
519
|
switch (this.shapeType) {
|
|
405
520
|
case ParticleSystemShapeType.Box:
|
|
@@ -410,11 +525,14 @@ export class ShapeModule {
|
|
|
410
525
|
case ParticleSystemShapeType.Sphere:
|
|
411
526
|
randomSpherePoint(this.position.x, this.position.y, this.position.z, this.radius, this.radiusThickness, this.arc, this._vector);
|
|
412
527
|
break;
|
|
528
|
+
default:
|
|
529
|
+
this._vector.set(0, 0, 0);
|
|
530
|
+
break;
|
|
413
531
|
// case ParticleSystemShapeType.Hemisphere:
|
|
414
532
|
// randomSpherePoint(this.position.x, this.position.y, this.position.z, this.radius, this.radiusThickness, 180, this._vector);
|
|
415
533
|
// break;
|
|
416
534
|
}
|
|
417
|
-
if(this._space === ParticleSystemSimulationSpace.World) {
|
|
535
|
+
if (this._space === ParticleSystemSimulationSpace.World) {
|
|
418
536
|
this._vector.applyMatrix4(this._worldSpacePosition);
|
|
419
537
|
}
|
|
420
538
|
}
|
|
@@ -422,7 +540,7 @@ export class ShapeModule {
|
|
|
422
540
|
|
|
423
541
|
|
|
424
542
|
private _dir: Vector3 = new Vector3();
|
|
425
|
-
getDirection(position):
|
|
543
|
+
getDirection(position): Vector3 {
|
|
426
544
|
switch (this.shapeType) {
|
|
427
545
|
case ParticleSystemShapeType.Box:
|
|
428
546
|
return this._dir.set(0, 0, 1);
|
|
@@ -456,6 +574,8 @@ function randomSpherePoint(x0: number, y0: number, z0: number, radius: number, t
|
|
|
456
574
|
|
|
457
575
|
import { createNoise4D, NoiseFunction4D } from 'simplex-noise';
|
|
458
576
|
import { Context } from "../engine/engine_setup";
|
|
577
|
+
import { getWorldQuaternion } from "../engine/engine_three_utils";
|
|
578
|
+
import { Gizmos } from "../engine/engine_gizmos";
|
|
459
579
|
|
|
460
580
|
export class NoiseModule {
|
|
461
581
|
@serializeable()
|
|
@@ -523,34 +643,229 @@ export class NoiseModule {
|
|
|
523
643
|
|
|
524
644
|
/** nebula implementations: */
|
|
525
645
|
private _temp: Vector3 = new Vector3();
|
|
526
|
-
|
|
646
|
+
apply(_index: number, pos: Vec3, vel: Vec3, _deltaTime: number, age: number, life: number) {
|
|
527
647
|
if (!this.enabled) return;
|
|
528
648
|
if (!this._noise) {
|
|
529
649
|
this._noise = createNoise4D(() => 0);
|
|
530
650
|
}
|
|
531
|
-
const t = age / life;
|
|
532
|
-
const dt = Context.Current.time.deltaTime;
|
|
533
651
|
const temp = this._temp.set(pos.x, pos.y, pos.z).multiplyScalar(this.frequency);
|
|
534
652
|
const nx = this._noise(temp.x, temp.y, temp.z, this._time);
|
|
535
|
-
const ny = this._noise(temp.x, temp.y, temp.z, this._time + .
|
|
536
|
-
const nz = this._noise(temp.x, temp.y, temp.z, this._time +
|
|
537
|
-
this._temp.set(nx, ny, nz).normalize()
|
|
653
|
+
const ny = this._noise(temp.x, temp.y, temp.z, this._time + .3);
|
|
654
|
+
const nz = this._noise(temp.x, temp.y, temp.z, this._time + 1);
|
|
655
|
+
this._temp.set(nx, ny, nz).normalize()
|
|
538
656
|
|
|
657
|
+
const t = age / life;
|
|
539
658
|
let strengthFactor = this.positionAmount.evaluate(t);
|
|
540
659
|
if (!this.separateAxes) {
|
|
541
|
-
if (this.strengthX)
|
|
542
|
-
strengthFactor *= this.strengthX.evaluate(t
|
|
543
|
-
|
|
544
|
-
strengthFactor *= .
|
|
660
|
+
if (this.strengthX) {
|
|
661
|
+
strengthFactor *= this.strengthX.evaluate(t) * Math.PI;
|
|
662
|
+
}
|
|
663
|
+
// strengthFactor *= this.strengthMultiplier;
|
|
664
|
+
// strengthFactor *= deltaTime;
|
|
545
665
|
this._temp.multiplyScalar(strengthFactor);
|
|
546
666
|
}
|
|
547
|
-
|
|
548
|
-
this._temp.x *= strengthFactor *
|
|
549
|
-
this._temp.y *= strengthFactor *
|
|
550
|
-
this._temp.z *= strengthFactor *
|
|
667
|
+
else {
|
|
668
|
+
this._temp.x *= strengthFactor * this.strengthXMultiplier
|
|
669
|
+
this._temp.y *= strengthFactor * this.strengthYMultiplier;
|
|
670
|
+
this._temp.z *= strengthFactor * this.strengthZMultiplier;
|
|
551
671
|
}
|
|
672
|
+
// this._temp.setLength(strengthFactor * deltaTime);
|
|
552
673
|
vel.x += this._temp.x;
|
|
553
674
|
vel.y += this._temp.y;
|
|
554
675
|
vel.z += this._temp.z;
|
|
555
676
|
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
export class TrailModule {
|
|
680
|
+
|
|
681
|
+
@serializeable()
|
|
682
|
+
enabled!: boolean;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
export class VelocityOverLifetimeModule {
|
|
686
|
+
@serializeable()
|
|
687
|
+
enabled!: boolean;
|
|
688
|
+
|
|
689
|
+
/* orbital settings */
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
@serializeable()
|
|
693
|
+
space: ParticleSystemSimulationSpace = ParticleSystemSimulationSpace.Local;
|
|
694
|
+
|
|
695
|
+
@serializeable(MinMaxCurve)
|
|
696
|
+
speedModifier!: MinMaxCurve;
|
|
697
|
+
@serializeable()
|
|
698
|
+
speedModifierMultiplier!: number;
|
|
699
|
+
@serializeable(MinMaxCurve)
|
|
700
|
+
x!: MinMaxCurve;
|
|
701
|
+
@serializeable()
|
|
702
|
+
xMultiplier!: number;
|
|
703
|
+
@serializeable(MinMaxCurve)
|
|
704
|
+
y!: MinMaxCurve;
|
|
705
|
+
@serializeable()
|
|
706
|
+
yMultiplier!: number;
|
|
707
|
+
@serializeable(MinMaxCurve)
|
|
708
|
+
z!: MinMaxCurve;
|
|
709
|
+
@serializeable()
|
|
710
|
+
zMultiplier!: number;
|
|
711
|
+
|
|
712
|
+
private _system?: IParticleSystem;
|
|
713
|
+
// private _worldRotation: Quaternion = new Quaternion();
|
|
714
|
+
|
|
715
|
+
update(system: IParticleSystem) {
|
|
716
|
+
this._system = system;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
private _temp: Vector3 = new Vector3();
|
|
720
|
+
|
|
721
|
+
apply(_index: number, _pos: Vec3, vel: Vec3, _dt: number, age: number, life: number) {
|
|
722
|
+
if (!this.enabled) return;
|
|
723
|
+
const t = age / life;
|
|
724
|
+
|
|
725
|
+
const speed = this.speedModifier.evaluate(t) * this.speedModifierMultiplier;
|
|
726
|
+
const x = this.x.evaluate(t) * speed;
|
|
727
|
+
const y = this.y.evaluate(t) * speed;
|
|
728
|
+
const z = this.z.evaluate(t) * speed;
|
|
729
|
+
this._temp.set(-x, y, z);
|
|
730
|
+
if (this._system) {
|
|
731
|
+
if (this.space === ParticleSystemSimulationSpace.World) {
|
|
732
|
+
this._temp.applyQuaternion(this._system.worldQuaternionInverted);
|
|
733
|
+
}
|
|
734
|
+
if (this._system.main.simulationSpace === ParticleSystemSimulationSpace.World) {
|
|
735
|
+
this._temp.applyQuaternion(this._system.worldQuaternion);
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
vel.x += this._temp.x;
|
|
739
|
+
vel.y += this._temp.y;
|
|
740
|
+
vel.z += this._temp.z;
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
|
|
745
|
+
|
|
746
|
+
enum ParticleSystemAnimationTimeMode {
|
|
747
|
+
Lifetime,
|
|
748
|
+
Speed,
|
|
749
|
+
FPS,
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
enum ParticleSystemAnimationMode {
|
|
753
|
+
Grid,
|
|
754
|
+
Sprites,
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
enum ParticleSystemAnimationRowMode {
|
|
758
|
+
Custom,
|
|
759
|
+
Random,
|
|
760
|
+
MeshIndex,
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
enum ParticleSystemAnimationType {
|
|
764
|
+
WholeSheet,
|
|
765
|
+
SingleRow,
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
export class TextureSheetAnimationModule {
|
|
769
|
+
|
|
770
|
+
@serializeable()
|
|
771
|
+
animation!: ParticleSystemAnimationType;
|
|
772
|
+
|
|
773
|
+
@serializeable()
|
|
774
|
+
enabled!: boolean;
|
|
775
|
+
|
|
776
|
+
@serializeable()
|
|
777
|
+
cycleCount!: number;
|
|
778
|
+
|
|
779
|
+
@serializeable(MinMaxCurve)
|
|
780
|
+
frameOverTime!: MinMaxCurve;
|
|
781
|
+
@serializeable()
|
|
782
|
+
frameOverTimeMultiplier!: number;
|
|
783
|
+
|
|
784
|
+
@serializeable()
|
|
785
|
+
numTilesX!: number;
|
|
786
|
+
@serializeable()
|
|
787
|
+
numTilesY!: number;
|
|
788
|
+
|
|
789
|
+
@serializeable(MinMaxCurve)
|
|
790
|
+
startFrame!: MinMaxCurve;
|
|
791
|
+
@serializeable()
|
|
792
|
+
startFrameMultiplier!: number;
|
|
793
|
+
|
|
794
|
+
@serializeable()
|
|
795
|
+
rowMode!: ParticleSystemAnimationRowMode;
|
|
796
|
+
@serializeable()
|
|
797
|
+
rowIndex!: number;
|
|
798
|
+
|
|
799
|
+
@serializeable()
|
|
800
|
+
spriteCount!: number;
|
|
801
|
+
|
|
802
|
+
@serializeable()
|
|
803
|
+
timeMode!: ParticleSystemAnimationTimeMode;
|
|
804
|
+
|
|
805
|
+
private sampleOnceAtStart(): boolean {
|
|
806
|
+
if (this.timeMode === ParticleSystemAnimationTimeMode.Lifetime) {
|
|
807
|
+
switch (this.frameOverTime.mode) {
|
|
808
|
+
case ParticleSystemCurveMode.Constant:
|
|
809
|
+
case ParticleSystemCurveMode.TwoConstants:
|
|
810
|
+
return true;
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
return false;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
getStartIndex(): number {
|
|
817
|
+
if (this.sampleOnceAtStart()) {
|
|
818
|
+
return this.frameOverTime.evaluate(Math.random())
|
|
819
|
+
}
|
|
820
|
+
return 0;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
evaluate(t01: number): number | undefined {
|
|
824
|
+
if (this.sampleOnceAtStart()) {
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
return this.getIndex(t01);
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
private getIndex(t01: number): number {
|
|
831
|
+
const tiles = this.numTilesX * this.numTilesY;
|
|
832
|
+
// let pos = t01 * this.cycleCount;
|
|
833
|
+
let index = this.frameOverTime.evaluate(t01 % 1);
|
|
834
|
+
index *= this.frameOverTimeMultiplier;
|
|
835
|
+
index *= tiles;
|
|
836
|
+
index = index % tiles;
|
|
837
|
+
index = Math.floor(index);
|
|
838
|
+
// console.log(index);
|
|
839
|
+
return index;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
|
|
844
|
+
export class RotationOverLifetimeModule {
|
|
845
|
+
@serializeable()
|
|
846
|
+
enabled!: boolean;
|
|
847
|
+
|
|
848
|
+
@serializeable()
|
|
849
|
+
separateAxes!: boolean;
|
|
850
|
+
|
|
851
|
+
@serializeable(MinMaxCurve)
|
|
852
|
+
x!: MinMaxCurve;
|
|
853
|
+
@serializeable()
|
|
854
|
+
xMultiplier!: number;
|
|
855
|
+
@serializeable(MinMaxCurve)
|
|
856
|
+
y!: MinMaxCurve;
|
|
857
|
+
@serializeable()
|
|
858
|
+
yMultiplier!: number;
|
|
859
|
+
@serializeable(MinMaxCurve)
|
|
860
|
+
z!: MinMaxCurve;
|
|
861
|
+
@serializeable()
|
|
862
|
+
zMultiplier!: number;
|
|
863
|
+
|
|
864
|
+
evaluate(t01: number): number {
|
|
865
|
+
if (!this.enabled) return 0;
|
|
866
|
+
if (!this.separateAxes) {
|
|
867
|
+
return this.z.evaluate(t01) * -1;
|
|
868
|
+
}
|
|
869
|
+
return 0;
|
|
870
|
+
}
|
|
556
871
|
}
|
|
@@ -10,11 +10,14 @@ import { getParam } from "../engine/engine_utils";
|
|
|
10
10
|
export const debug = getParam("debugreflectionprobe");
|
|
11
11
|
const disable = getParam("noreflectionprobe");
|
|
12
12
|
|
|
13
|
+
const $reflectionProbeKey = Symbol("reflectionProbeKey");
|
|
14
|
+
const $originalMaterial = Symbol("original material");
|
|
15
|
+
|
|
13
16
|
export class ReflectionProbe extends Behaviour {
|
|
14
17
|
|
|
15
18
|
private static _probes: Map<Context, ReflectionProbe[]> = new Map();
|
|
16
19
|
|
|
17
|
-
public static get(object: Object3D | null | undefined, context: Context, isAnchor:boolean): ReflectionProbe | null {
|
|
20
|
+
public static get(object: Object3D | null | undefined, context: Context, isAnchor: boolean): ReflectionProbe | null {
|
|
18
21
|
if (!object || object.isObject3D !== true) return null;
|
|
19
22
|
if (disable) return null;
|
|
20
23
|
const probes = ReflectionProbe._probes.get(context);
|
|
@@ -91,7 +94,7 @@ export class ReflectionProbe extends Behaviour {
|
|
|
91
94
|
// and some need reflection probe and some don't
|
|
92
95
|
// we need to make sure we don't override the material but use a copy
|
|
93
96
|
|
|
94
|
-
private static _rendererMaterialsCache: Map<IRenderer, Array<{
|
|
97
|
+
private static _rendererMaterialsCache: Map<IRenderer, Array<{ material: Material, copy: Material }>> = new Map();
|
|
95
98
|
|
|
96
99
|
onSet(_rend: IRenderer) {
|
|
97
100
|
if (disable) return;
|
|
@@ -109,22 +112,43 @@ export class ReflectionProbe extends Behaviour {
|
|
|
109
112
|
// need to make sure materials are not shared when using reflection probes
|
|
110
113
|
// otherwise some renderers outside of the probe will be affected or vice versa
|
|
111
114
|
for (let i = 0; i < _rend.sharedMaterials.length; i++) {
|
|
112
|
-
const
|
|
113
|
-
if (!
|
|
114
|
-
if (
|
|
115
|
+
const material = _rend.sharedMaterials[i];
|
|
116
|
+
if (!material) continue;
|
|
117
|
+
if (material["envMap"] === undefined) continue;
|
|
118
|
+
if (material["envMap"] === this.texture) {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
115
121
|
let cached = rendererCache[i];
|
|
116
|
-
let copy = cached?.copy;
|
|
117
|
-
if (!cached) {
|
|
118
|
-
const clone = orig.clone();
|
|
119
|
-
copy = clone;
|
|
120
|
-
rendererCache.push({ orig, copy });
|
|
121
122
|
|
|
122
|
-
|
|
123
|
-
|
|
123
|
+
// make sure we have the currently assigned material cached (and an up to date clone of that)
|
|
124
|
+
if (!cached || cached.material !== material || cached.material.version !== material.version) {
|
|
125
|
+
const clone = material.clone();
|
|
126
|
+
|
|
127
|
+
if (cached) {
|
|
128
|
+
cached.copy = clone;
|
|
129
|
+
cached.material = material;
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
cached = {
|
|
133
|
+
material: material,
|
|
134
|
+
copy: clone
|
|
135
|
+
};
|
|
136
|
+
rendererCache.push(cached);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
clone[$reflectionProbeKey] = this;
|
|
140
|
+
clone[$originalMaterial] = material;
|
|
141
|
+
|
|
142
|
+
// make sure the reflection probe is assigned
|
|
143
|
+
clone["envMap"] = this.texture;
|
|
124
144
|
|
|
125
145
|
if (debug)
|
|
126
146
|
console.log("Set reflection", _rend.name, _rend.guid);
|
|
127
147
|
}
|
|
148
|
+
|
|
149
|
+
/** this is the material that we copied and that has the reflection probe */
|
|
150
|
+
const copy = cached?.copy;
|
|
151
|
+
|
|
128
152
|
_rend.sharedMaterials[i] = copy;
|
|
129
153
|
}
|
|
130
154
|
}
|
|
@@ -134,7 +158,7 @@ export class ReflectionProbe extends Behaviour {
|
|
|
134
158
|
if (rendererCache) {
|
|
135
159
|
for (let i = 0; i < rendererCache.length; i++) {
|
|
136
160
|
const cached = rendererCache[i];
|
|
137
|
-
_rend.sharedMaterials[i] = cached.
|
|
161
|
+
_rend.sharedMaterials[i] = cached.material;
|
|
138
162
|
}
|
|
139
163
|
}
|
|
140
164
|
}
|
|
@@ -219,6 +219,8 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
219
219
|
return lm !== null && lm !== undefined;
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
+
allowProgressiveLoading : boolean = true;
|
|
223
|
+
|
|
222
224
|
awake() {
|
|
223
225
|
this.clearInstancingState();
|
|
224
226
|
|
|
@@ -457,7 +459,7 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
457
459
|
onBeforeRenderThree(_renderer, _scene, _camera, _geometry, material, _group) {
|
|
458
460
|
|
|
459
461
|
// progressive load before rendering so we only load textures for visible materials
|
|
460
|
-
if (!suppressProgressiveLoading && material._didRequestTextureLOD === undefined) {
|
|
462
|
+
if (!suppressProgressiveLoading && material._didRequestTextureLOD === undefined && this.allowProgressiveLoading) {
|
|
461
463
|
material._didRequestTextureLOD = 0;
|
|
462
464
|
if (debugProgressiveLoading) {
|
|
463
465
|
console.log("Load material LOD (with delay)", material.name);
|
|
@@ -542,7 +544,7 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
542
544
|
// handle reflection probe
|
|
543
545
|
this._reflectionProbe = null;
|
|
544
546
|
if (this.reflectionProbeUsage !== ReflectionProbeUsage.Off) {
|
|
545
|
-
|
|
547
|
+
if(!this.probeAnchor) return;
|
|
546
548
|
const obj = this.probeAnchor || this.gameObject;
|
|
547
549
|
const isAnchor = this.probeAnchor ? true : false;
|
|
548
550
|
this._reflectionProbe = ReflectionProbe.get(obj, this.context, isAnchor);
|