babylon.quarks 0.26.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1194 -8
- package/README.md +13 -9
- package/dist/babylon.quarks.cjs +1 -1
- package/dist/babylon.quarks.cjs.map +1 -1
- package/dist/babylon.quarks.esm.js +1 -1
- package/dist/babylon.quarks.esm.js.map +1 -1
- package/dist/babylon.quarks.umd.min.js +1 -1
- package/dist/babylon.quarks.umd.min.js.map +1 -1
- package/dist/types/index.d.cts +10108 -0
- package/dist/types/index.d.ts +5794 -998
- package/package.json +18 -7
- package/src/BatchedRenderer.ts +274 -156
- package/src/EffectPool.ts +94 -12
- package/src/MeshSurfaceEmitter.ts +50 -14
- package/src/ParticleEmitter.ts +75 -17
- package/src/ParticleSystem.ts +981 -2066
- package/src/QuarksLoader.ts +666 -194
- package/src/QuarksPrefab.ts +367 -73
- package/src/QuarksSerializer.ts +512 -0
- package/src/QuarksUtil.ts +77 -7
- package/src/SpriteBatch.ts +127 -252
- package/src/TrailBatch.ts +545 -348
- package/src/VFXBatch.ts +238 -596
- package/src/batchKey.ts +239 -0
- package/src/batchSettings.ts +546 -0
- package/src/effectDocumentJSON.ts +261 -0
- package/src/effectResources.ts +76 -0
- package/src/envAtlas.ts +126 -18
- package/src/geometryUtil.ts +1 -1
- package/src/index.ts +69 -35
- package/src/nodeId.ts +36 -0
- package/src/shaderProgram.ts +419 -0
- package/src/shaderVariants.ts +245 -0
- package/src/shaders/chunks/blend.ts +31 -0
- package/src/shaders/chunks/fog.ts +12 -5
- package/src/shaders/chunks/sheet.ts +111 -0
- package/src/shaders/chunks/soft.ts +85 -0
- package/src/shaders/chunks/surface.ts +12 -2
- package/src/shaders/local_particle_physics_vert.glsl.ts +14 -28
- package/src/shaders/local_particle_physics_vert.wgsl.ts +16 -29
- package/src/shaders/particle_frag.glsl.ts +5 -22
- package/src/shaders/particle_frag.wgsl.ts +5 -23
- package/src/shaders/particle_physics_frag.glsl.ts +16 -26
- package/src/shaders/particle_physics_frag.wgsl.ts +14 -26
- package/src/shaders/particle_vert.glsl.ts +5 -27
- package/src/shaders/particle_vert.wgsl.ts +5 -26
- package/src/shaders/stretched_bb_particle_vert.glsl.ts +7 -33
- package/src/shaders/stretched_bb_particle_vert.wgsl.ts +7 -33
- package/src/shaders/trail_frag.glsl.ts +13 -0
- package/src/shaders/trail_frag.wgsl.ts +13 -0
- package/src/shaders/trail_vert.glsl.ts +45 -36
- package/src/shaders/trail_vert.wgsl.ts +46 -40
- package/src/softDepth.ts +136 -0
- package/src/system/BehaviorPlan.ts +85 -0
- package/src/system/BoundsTracker.ts +181 -0
- package/src/system/EmissionController.ts +358 -0
- package/src/system/EventDispatcher.ts +60 -0
- package/src/system/ParticleSpawner.ts +274 -0
- package/src/system/SimulationClock.ts +130 -0
- package/src/system/geometry.ts +104 -0
- package/src/system/integrate.ts +428 -0
- package/src/system/materialResolve.ts +165 -0
- package/src/system/normalize.ts +100 -0
- package/src/system/serialization.ts +422 -0
- package/src/system/settingsSchema.ts +339 -0
- package/src/system/types.ts +449 -0
- package/src/textureSource.ts +30 -0
- package/src/trailSettings.ts +54 -0
- package/src/BatchedParticleRenderer.ts +0 -3
- package/src/materials/ParticleMaterials.ts +0 -23
- package/src/materials/index.ts +0 -1
- package/src/shaders/chunks/index.ts +0 -1
- package/src/shaders/chunks/register-shader-chunks.ts +0 -32
- package/src/shaders/chunks/soft_fragment.glsl.ts +0 -13
- package/src/shaders/chunks/soft_pars_fragment.glsl.ts +0 -20
- package/src/shaders/chunks/soft_pars_vertex.glsl.ts +0 -6
- package/src/shaders/chunks/soft_vertex.glsl.ts +0 -6
- package/src/shaders/chunks/tile_fragment.glsl.ts +0 -9
- package/src/shaders/chunks/tile_pars_fragment.glsl.ts +0 -9
- package/src/shaders/chunks/tile_pars_vertex.glsl.ts +0 -28
- package/src/shaders/chunks/tile_vertex.glsl.ts +0 -18
- package/src/shaders/index.ts +0 -9
- package/src/shaders/local_particle_vert.glsl.ts +0 -50
package/src/QuarksUtil.ts
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
|
+
import {InstancedMesh} from '@babylonjs/core/Meshes/instancedMesh';
|
|
2
|
+
import {Mesh} from '@babylonjs/core/Meshes/mesh';
|
|
1
3
|
import {TransformNode} from '@babylonjs/core/Meshes/transformNode';
|
|
2
4
|
import {Node} from '@babylonjs/core/node';
|
|
3
5
|
import {ConstantValue, EmitSubParticleSystem, FunctionValueGenerator, IntervalValue, ValueGenerator} from 'quarks.core';
|
|
4
6
|
import {BatchedRenderer} from './BatchedRenderer';
|
|
7
|
+
import {shareEffectResources} from './effectResources';
|
|
8
|
+
import {MeshSurfaceEmitter} from './MeshSurfaceEmitter';
|
|
5
9
|
import {ParticleEmitter} from './ParticleEmitter';
|
|
6
10
|
import {ParticleSystem} from './ParticleSystem';
|
|
7
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Helpers that act on a whole effect: every particle system under a root node, as a loaded effect
|
|
14
|
+
* or a hand-built tree has them.
|
|
15
|
+
*/
|
|
8
16
|
export class QuarksUtil {
|
|
17
|
+
/** Calls `callback` on `root` and every node under it that is a {@link ParticleEmitter}. */
|
|
9
18
|
static runOnAllParticleEmitters(root: Node, callback: (emitter: ParticleEmitter) => void): void {
|
|
10
19
|
QuarksUtil.traverseNode(root, (node) => {
|
|
11
20
|
if (node instanceof ParticleEmitter) {
|
|
@@ -14,42 +23,62 @@ export class QuarksUtil {
|
|
|
14
23
|
});
|
|
15
24
|
}
|
|
16
25
|
|
|
26
|
+
/** Adds every system under `root` to `batchRenderer`. */
|
|
17
27
|
static addToBatchRenderer(root: Node, batchRenderer: BatchedRenderer): void {
|
|
18
28
|
QuarksUtil.runOnAllParticleEmitters(root, (emitter) => {
|
|
19
29
|
batchRenderer.addSystem(emitter.system);
|
|
20
30
|
});
|
|
21
31
|
}
|
|
22
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Plays every system under `root`, see {@link ParticleSystem.play}: paused ones resume and
|
|
35
|
+
* finished ones, a short burst inside a longer effect included, start over.
|
|
36
|
+
*/
|
|
23
37
|
static play(root: Node): void {
|
|
24
38
|
QuarksUtil.runOnAllParticleEmitters(root, (emitter) => {
|
|
25
39
|
(emitter.system as unknown as ParticleSystem).play();
|
|
26
40
|
});
|
|
27
41
|
}
|
|
28
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Undoes {@link pause} on every system under `root`, see {@link ParticleSystem.resume}: the
|
|
45
|
+
* finished ones stay finished.
|
|
46
|
+
*/
|
|
47
|
+
static resume(root: Node): void {
|
|
48
|
+
QuarksUtil.runOnAllParticleEmitters(root, (emitter) => {
|
|
49
|
+
(emitter.system as unknown as ParticleSystem).resume();
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Clears, rewinds and pauses every system under `root`, see {@link ParticleSystem.stop}. */
|
|
29
54
|
static stop(root: Node): void {
|
|
30
55
|
QuarksUtil.runOnAllParticleEmitters(root, (emitter) => {
|
|
31
56
|
(emitter.system as unknown as ParticleSystem).stop();
|
|
32
57
|
});
|
|
33
58
|
}
|
|
34
59
|
|
|
60
|
+
/** Pauses every system under `root`, see {@link ParticleSystem.pause}. */
|
|
35
61
|
static pause(root: Node): void {
|
|
36
62
|
QuarksUtil.runOnAllParticleEmitters(root, (emitter) => {
|
|
37
63
|
(emitter.system as unknown as ParticleSystem).pause();
|
|
38
64
|
});
|
|
39
65
|
}
|
|
40
66
|
|
|
67
|
+
/** Restarts every system under `root` from the beginning, see {@link ParticleSystem.restart}. */
|
|
41
68
|
static restart(root: Node): void {
|
|
42
69
|
QuarksUtil.runOnAllParticleEmitters(root, (emitter) => {
|
|
43
70
|
(emitter.system as unknown as ParticleSystem).restart();
|
|
44
71
|
});
|
|
45
72
|
}
|
|
46
73
|
|
|
74
|
+
/** Sets {@link ParticleSystem.autoDestroy} on every system under `root`. */
|
|
47
75
|
static setAutoDestroy(root: Node, autoDestroy: boolean): void {
|
|
48
76
|
QuarksUtil.runOnAllParticleEmitters(root, (emitter) => {
|
|
49
77
|
(emitter.system as unknown as ParticleSystem).autoDestroy = autoDestroy;
|
|
50
78
|
});
|
|
51
79
|
}
|
|
52
80
|
|
|
81
|
+
/** Ends emission on every system under `root` and lets the particles die out, see {@link ParticleSystem.endEmit}. */
|
|
53
82
|
static endEmit(root: Node): void {
|
|
54
83
|
QuarksUtil.runOnAllParticleEmitters(root, (emitter) => {
|
|
55
84
|
(emitter.system as unknown as ParticleSystem).endEmit();
|
|
@@ -77,16 +106,46 @@ export class QuarksUtil {
|
|
|
77
106
|
/**
|
|
78
107
|
* A deep copy of an effect: the node tree under `root` with every particle
|
|
79
108
|
* system cloned, sub emitter links pointing at the copies, and the same
|
|
80
|
-
* transforms and enabled state.
|
|
81
|
-
*
|
|
109
|
+
* transforms and enabled state. Meshes are cloned as meshes that share
|
|
110
|
+
* the source's geometry and material, instances of a mesh in the tree as
|
|
111
|
+
* instances of its copy, and a mesh surface shape that emits from a mesh
|
|
112
|
+
* in the tree emits from its copy. An instance of a mesh outside the tree
|
|
113
|
+
* stays an instance of that mesh, and goes when it is disposed. The copy holds the
|
|
114
|
+
* source's textures and materials, so disposing the source leaves the copy
|
|
115
|
+
* whole. It is not added to any renderer. Nodes that are neither transform
|
|
116
|
+
* nodes nor emitters, such as lights and cameras, are skipped.
|
|
82
117
|
*/
|
|
83
118
|
static instantiate(root: TransformNode, name?: string): TransformNode {
|
|
84
119
|
const copies = new Map<ParticleEmitter, ParticleEmitter>();
|
|
120
|
+
const meshCopies = new Map<Node, Mesh>();
|
|
121
|
+
const inTree = new Set<Node>([root, ...root.getDescendants(false)]);
|
|
122
|
+
// A mesh is copied when first needed: where it sits in the tree, or earlier, as the source
|
|
123
|
+
// of an instance copied before it. Its children are copied as every node's are.
|
|
124
|
+
const meshCopyOf = (mesh: Mesh): Mesh => {
|
|
125
|
+
let copy = meshCopies.get(mesh);
|
|
126
|
+
if (copy === undefined) {
|
|
127
|
+
copy = mesh.clone(mesh.name, null, true);
|
|
128
|
+
copy.setEnabled(mesh.isEnabled(false));
|
|
129
|
+
meshCopies.set(mesh, copy);
|
|
130
|
+
}
|
|
131
|
+
return copy;
|
|
132
|
+
};
|
|
85
133
|
const copyNode = (node: Node, parent: TransformNode | null, copyName?: string): TransformNode | null => {
|
|
86
134
|
let copy: TransformNode;
|
|
87
135
|
if (node instanceof ParticleEmitter) {
|
|
88
136
|
copy = node.clone(copyName);
|
|
89
137
|
copies.set(node, copy as ParticleEmitter);
|
|
138
|
+
} else if (node instanceof Mesh) {
|
|
139
|
+
copy = meshCopyOf(node);
|
|
140
|
+
if (copyName !== undefined) {
|
|
141
|
+
copy.name = copyName;
|
|
142
|
+
}
|
|
143
|
+
} else if (node instanceof InstancedMesh) {
|
|
144
|
+
// An instance of a mesh in the tree becomes an instance of its copy, so the copy
|
|
145
|
+
// does not go when the source effect is disposed (a mesh disposes its instances).
|
|
146
|
+
const source = inTree.has(node.sourceMesh) ? meshCopyOf(node.sourceMesh) : undefined;
|
|
147
|
+
copy = node.clone(copyName ?? node.name, null, true, source)!;
|
|
148
|
+
copy.setEnabled(node.isEnabled(false));
|
|
90
149
|
} else if (node instanceof TransformNode) {
|
|
91
150
|
copy = new TransformNode(copyName ?? node.name, node.getScene());
|
|
92
151
|
copy.position.copyFrom(node.position);
|
|
@@ -106,9 +165,12 @@ export class QuarksUtil {
|
|
|
106
165
|
return copy;
|
|
107
166
|
};
|
|
108
167
|
const copy = copyNode(root, null, name) as TransformNode;
|
|
109
|
-
//
|
|
168
|
+
// The copy draws with the source's textures and materials, so disposeEffect(source) keeps them.
|
|
169
|
+
shareEffectResources(root, copy);
|
|
110
170
|
for (const emitter of copies.values()) {
|
|
111
|
-
|
|
171
|
+
const system = emitter.system as unknown as ParticleSystem;
|
|
172
|
+
// Sub emitter behaviors on the copies still target the original emitters.
|
|
173
|
+
for (const behavior of system.behaviors) {
|
|
112
174
|
if (behavior instanceof EmitSubParticleSystem) {
|
|
113
175
|
const target = copies.get(behavior.subParticleSystem as unknown as ParticleEmitter);
|
|
114
176
|
if (target !== undefined) {
|
|
@@ -116,6 +178,14 @@ export class QuarksUtil {
|
|
|
116
178
|
}
|
|
117
179
|
}
|
|
118
180
|
}
|
|
181
|
+
// So does a mesh surface shape: it emits from the copy of its mesh when the tree has one.
|
|
182
|
+
const shape = system.emitterShape;
|
|
183
|
+
if (shape instanceof MeshSurfaceEmitter && shape.mesh !== undefined) {
|
|
184
|
+
const meshCopy = meshCopies.get(shape.mesh);
|
|
185
|
+
if (meshCopy !== undefined) {
|
|
186
|
+
shape.mesh = meshCopy;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
119
189
|
}
|
|
120
190
|
return copy;
|
|
121
191
|
}
|
|
@@ -130,7 +200,8 @@ export class QuarksUtil {
|
|
|
130
200
|
* {@link endEmit}, or when one is frozen at playback speed 0.
|
|
131
201
|
*
|
|
132
202
|
* Random values count at their maximum, so this is an upper bound; curves
|
|
133
|
-
* are sampled.
|
|
203
|
+
* are sampled. A runtime {@link ParticleSystem.timeDilation} is not counted:
|
|
204
|
+
* this is the effect's own length. Particles cut short by collisions or culling only make the
|
|
134
205
|
* real effect shorter.
|
|
135
206
|
*/
|
|
136
207
|
static getDuration(root: Node): number {
|
|
@@ -147,8 +218,7 @@ export class QuarksUtil {
|
|
|
147
218
|
continue;
|
|
148
219
|
}
|
|
149
220
|
const target = (behavior.subParticleSystem as unknown as ParticleEmitter | undefined)?.system as
|
|
150
|
-
|
|
|
151
|
-
| undefined;
|
|
221
|
+
ParticleSystem | undefined;
|
|
152
222
|
if (target !== undefined && typeof target === 'object') {
|
|
153
223
|
if (!systems.includes(target)) {
|
|
154
224
|
systems.push(target);
|