babylon.quarks 0.17.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/LICENSE +21 -0
- package/dist/babylon.quarks.cjs +2 -0
- package/dist/babylon.quarks.cjs.map +1 -0
- package/dist/babylon.quarks.esm.js +2 -0
- package/dist/babylon.quarks.esm.js.map +1 -0
- package/dist/types/BatchedParticleRenderer.d.ts +2 -0
- package/dist/types/BatchedRenderer.d.ts +40 -0
- package/dist/types/MeshSurfaceEmitter.d.ts +19 -0
- package/dist/types/ParticleEmitter.d.ts +16 -0
- package/dist/types/ParticleSystem.d.ts +226 -0
- package/dist/types/QuarksLoader.d.ts +28 -0
- package/dist/types/QuarksPrefab.d.ts +48 -0
- package/dist/types/QuarksUtil.d.ts +14 -0
- package/dist/types/SpriteBatch.d.ts +32 -0
- package/dist/types/TrailBatch.d.ts +27 -0
- package/dist/types/VFXBatch.d.ts +51 -0
- package/dist/types/index.d.ts +19 -0
- package/dist/types/materials/ParticleMaterials.d.ts +12 -0
- package/dist/types/materials/index.d.ts +1 -0
- package/dist/types/shaders/chunks/index.d.ts +1 -0
- package/dist/types/shaders/chunks/register-shader-chunks.d.ts +3 -0
- package/dist/types/shaders/chunks/soft_fragment.glsl.d.ts +2 -0
- package/dist/types/shaders/chunks/soft_pars_fragment.glsl.d.ts +2 -0
- package/dist/types/shaders/chunks/soft_pars_vertex.glsl.d.ts +2 -0
- package/dist/types/shaders/chunks/soft_vertex.glsl.d.ts +2 -0
- package/dist/types/shaders/chunks/tile_fragment.glsl.d.ts +2 -0
- package/dist/types/shaders/chunks/tile_pars_fragment.glsl.d.ts +2 -0
- package/dist/types/shaders/chunks/tile_pars_vertex.glsl.d.ts +2 -0
- package/dist/types/shaders/chunks/tile_vertex.glsl.d.ts +2 -0
- package/dist/types/shaders/index.d.ts +9 -0
- package/dist/types/shaders/local_particle_physics_vert.glsl.d.ts +2 -0
- package/dist/types/shaders/local_particle_vert.glsl.d.ts +2 -0
- package/dist/types/shaders/particle_frag.glsl.d.ts +2 -0
- package/dist/types/shaders/particle_physics_frag.glsl.d.ts +2 -0
- package/dist/types/shaders/particle_vert.glsl.d.ts +2 -0
- package/dist/types/shaders/stretched_bb_particle_vert.glsl.d.ts +2 -0
- package/dist/types/shaders/trail_frag.glsl.d.ts +2 -0
- package/dist/types/shaders/trail_vert.glsl.d.ts +2 -0
- package/package.json +58 -0
- package/src/BatchedParticleRenderer.ts +3 -0
- package/src/BatchedRenderer.ts +135 -0
- package/src/MeshSurfaceEmitter.ts +137 -0
- package/src/ParticleEmitter.ts +86 -0
- package/src/ParticleSystem.ts +1162 -0
- package/src/QuarksLoader.ts +503 -0
- package/src/QuarksPrefab.ts +307 -0
- package/src/QuarksUtil.ts +66 -0
- package/src/SpriteBatch.ts +391 -0
- package/src/TrailBatch.ts +345 -0
- package/src/VFXBatch.ts +102 -0
- package/src/index.ts +54 -0
- package/src/materials/ParticleMaterials.ts +23 -0
- package/src/materials/index.ts +1 -0
- package/src/shaders/chunks/index.ts +1 -0
- package/src/shaders/chunks/register-shader-chunks.ts +32 -0
- package/src/shaders/chunks/soft_fragment.glsl.ts +13 -0
- package/src/shaders/chunks/soft_pars_fragment.glsl.ts +20 -0
- package/src/shaders/chunks/soft_pars_vertex.glsl.ts +6 -0
- package/src/shaders/chunks/soft_vertex.glsl.ts +6 -0
- package/src/shaders/chunks/tile_fragment.glsl.ts +9 -0
- package/src/shaders/chunks/tile_pars_fragment.glsl.ts +9 -0
- package/src/shaders/chunks/tile_pars_vertex.glsl.ts +28 -0
- package/src/shaders/chunks/tile_vertex.glsl.ts +18 -0
- package/src/shaders/index.ts +9 -0
- package/src/shaders/local_particle_physics_vert.glsl.ts +66 -0
- package/src/shaders/local_particle_vert.glsl.ts +50 -0
- package/src/shaders/particle_frag.glsl.ts +61 -0
- package/src/shaders/particle_physics_frag.glsl.ts +67 -0
- package/src/shaders/particle_vert.glsl.ts +85 -0
- package/src/shaders/stretched_bb_particle_vert.glsl.ts +74 -0
- package/src/shaders/trail_frag.glsl.ts +21 -0
- package/src/shaders/trail_vert.glsl.ts +58 -0
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const _default: "\nattribute vec3 position;\nattribute vec3 previous;\nattribute vec3 next;\nattribute float side;\nattribute float width;\nattribute vec2 uv;\nattribute vec4 color;\n\nuniform mat4 view;\nuniform mat4 projection;\nuniform float lineWidth;\nuniform vec2 resolution;\nuniform float sizeAttenuation;\n\nvarying vec2 vUV;\nvarying vec4 vColor;\n\nvec2 fix(vec4 i, float aspect) {\n vec2 res = i.xy / i.w;\n res.x *= aspect;\n return res;\n}\n\nvoid main() {\n float aspect = resolution.x / resolution.y;\n vec4 finalPosition = projection * view * vec4(position, 1.0);\n vec4 prevPos = projection * view * vec4(previous, 1.0);\n vec4 nextPos = projection * view * vec4(next, 1.0);\n\n vec2 currentP = fix(finalPosition, aspect);\n vec2 prevP = fix(prevPos, aspect);\n vec2 nextP = fix(nextPos, aspect);\n\n float w = lineWidth * width;\n vec2 dir;\n if (distance(nextP, currentP) < 0.0001) {\n dir = normalize(currentP - prevP);\n } else if (distance(prevP, currentP) < 0.0001) {\n dir = normalize(nextP - currentP);\n } else {\n vec2 dir1 = normalize(currentP - prevP);\n vec2 dir2 = normalize(nextP - currentP);\n dir = normalize(dir1 + dir2);\n }\n vec4 normal = vec4(-dir.y, dir.x, 0.0, 1.0);\n normal.xy *= 0.5 * w;\n normal *= projection;\n if (sizeAttenuation == 0.0) {\n normal.xy *= finalPosition.w;\n normal.xy /= (vec4(resolution, 0.0, 1.0) * projection).xy;\n }\n finalPosition.xy += normal.xy * side;\n gl_Position = finalPosition;\n vUV = uv;\n vColor = color;\n}\n";
|
|
2
|
+
export default _default;
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "babylon.quarks",
|
|
3
|
+
"version": "0.17.0",
|
|
4
|
+
"description": "A High-Performance Particle System for Babylon.js",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"types": "./dist/types/index.d.ts",
|
|
7
|
+
"main": "./dist/babylon.quarks.cjs",
|
|
8
|
+
"module": "./dist/babylon.quarks.esm.js",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/babylon.quarks.esm.js",
|
|
12
|
+
"require": "./dist/babylon.quarks.cjs",
|
|
13
|
+
"types": "./dist/types/index.d.ts"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"src",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"clean": "rimraf dist",
|
|
23
|
+
"build:types": "tsc --emitDeclarationOnly",
|
|
24
|
+
"build:js": "cross-env NODE_ENV=production rollup -c",
|
|
25
|
+
"build": "npm run clean && npm run build:types && npm run build:js",
|
|
26
|
+
"test": "jest",
|
|
27
|
+
"prettier": "prettier --write --ignore-unknown **/*.ts"
|
|
28
|
+
},
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://github.com/Soullnik/babylon.quarks-standalone.git"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"particle",
|
|
35
|
+
"library",
|
|
36
|
+
"3d",
|
|
37
|
+
"game",
|
|
38
|
+
"performance",
|
|
39
|
+
"babylonjs",
|
|
40
|
+
"vfx"
|
|
41
|
+
],
|
|
42
|
+
"author": "soullnik <soullnik96@gmail.com>",
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/Soullnik/babylon.quarks-standalone/issues"
|
|
46
|
+
},
|
|
47
|
+
"homepage": "https://github.com/Soullnik/babylon.quarks-standalone#readme",
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"@babylonjs/core": ">=9.0.0"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"quarks.core": "^0.17.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@babylonjs/core": "^9.0.0",
|
|
56
|
+
"@types/jest": "^30.0.0"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import {TransformNode} from '@babylonjs/core/Meshes/transformNode';
|
|
2
|
+
import {Scene} from '@babylonjs/core/scene';
|
|
3
|
+
import {Texture} from '@babylonjs/core/Materials/Textures/texture';
|
|
4
|
+
import {BaseTexture} from '@babylonjs/core/Materials/Textures/baseTexture';
|
|
5
|
+
import {IParticleSystem} from 'quarks.core';
|
|
6
|
+
import {VFXBatch, RenderMode, StoredBatchSettings} from './VFXBatch';
|
|
7
|
+
import {SpriteBatch} from './SpriteBatch';
|
|
8
|
+
import {TrailBatch} from './TrailBatch';
|
|
9
|
+
import {ParticleSystem} from './ParticleSystem';
|
|
10
|
+
|
|
11
|
+
export interface VFXBatchSettings {
|
|
12
|
+
instancingGeometry: Float32Array;
|
|
13
|
+
instancingIndices: Uint32Array | Uint16Array;
|
|
14
|
+
instancingUVs?: Float32Array;
|
|
15
|
+
instancingNormals?: Float32Array;
|
|
16
|
+
renderMode: RenderMode;
|
|
17
|
+
renderOrder: number;
|
|
18
|
+
uTileCount: number;
|
|
19
|
+
vTileCount: number;
|
|
20
|
+
blendTiles: boolean;
|
|
21
|
+
softParticles: boolean;
|
|
22
|
+
softNearFade: number;
|
|
23
|
+
softFarFade: number;
|
|
24
|
+
materialBlendMode: number;
|
|
25
|
+
materialTransparent: boolean;
|
|
26
|
+
materialDepthTest: boolean;
|
|
27
|
+
materialDepthWrite: boolean;
|
|
28
|
+
materialAlphaTest: number;
|
|
29
|
+
texture: Texture | null;
|
|
30
|
+
layerMask: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class BatchedRenderer extends TransformNode {
|
|
34
|
+
batches: Array<VFXBatch> = [];
|
|
35
|
+
systemToBatchIndex: Map<IParticleSystem, number> = new Map<IParticleSystem, number>();
|
|
36
|
+
depthTexture: BaseTexture | null = null;
|
|
37
|
+
|
|
38
|
+
constructor(name: string, scene: Scene) {
|
|
39
|
+
super(name, scene);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private static equals(a: StoredBatchSettings, b: VFXBatchSettings): boolean {
|
|
43
|
+
return (
|
|
44
|
+
a.materialBlendMode === b.materialBlendMode &&
|
|
45
|
+
a.materialTransparent === b.materialTransparent &&
|
|
46
|
+
a.materialDepthTest === b.materialDepthTest &&
|
|
47
|
+
a.materialDepthWrite === b.materialDepthWrite &&
|
|
48
|
+
a.materialAlphaTest === b.materialAlphaTest &&
|
|
49
|
+
a.texture === b.texture &&
|
|
50
|
+
a.renderMode === b.renderMode &&
|
|
51
|
+
a.blendTiles === b.blendTiles &&
|
|
52
|
+
a.softParticles === b.softParticles &&
|
|
53
|
+
a.softFarFade === b.softFarFade &&
|
|
54
|
+
a.softNearFade === b.softNearFade &&
|
|
55
|
+
a.uTileCount === b.uTileCount &&
|
|
56
|
+
a.vTileCount === b.vTileCount &&
|
|
57
|
+
a.instancingGeometry === b.instancingGeometry &&
|
|
58
|
+
a.renderOrder === b.renderOrder &&
|
|
59
|
+
a.layerMask === b.layerMask
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
addSystem(system: IParticleSystem) {
|
|
64
|
+
(system as unknown as ParticleSystem)._renderer = this;
|
|
65
|
+
const settings = (system as unknown as ParticleSystem).getRendererSettings();
|
|
66
|
+
for (let i = 0; i < this.batches.length; i++) {
|
|
67
|
+
if (BatchedRenderer.equals(this.batches[i].settings, settings)) {
|
|
68
|
+
this.batches[i].addSystem(system);
|
|
69
|
+
this.systemToBatchIndex.set(system, i);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
let batch: VFXBatch;
|
|
74
|
+
const scene = this.getScene();
|
|
75
|
+
switch (settings.renderMode) {
|
|
76
|
+
case RenderMode.Trail:
|
|
77
|
+
batch = new TrailBatch(settings, scene);
|
|
78
|
+
break;
|
|
79
|
+
case RenderMode.Mesh:
|
|
80
|
+
case RenderMode.BillBoard:
|
|
81
|
+
case RenderMode.VerticalBillBoard:
|
|
82
|
+
case RenderMode.HorizontalBillBoard:
|
|
83
|
+
case RenderMode.StretchedBillBoard:
|
|
84
|
+
batch = new SpriteBatch(settings, scene);
|
|
85
|
+
break;
|
|
86
|
+
default:
|
|
87
|
+
throw new Error(`Unsupported render mode: ${settings.renderMode}`);
|
|
88
|
+
}
|
|
89
|
+
batch.mesh.parent = this;
|
|
90
|
+
if (this.depthTexture) {
|
|
91
|
+
batch.applyDepthTexture(this.depthTexture);
|
|
92
|
+
}
|
|
93
|
+
batch.addSystem(system);
|
|
94
|
+
this.batches.push(batch);
|
|
95
|
+
this.systemToBatchIndex.set(system, this.batches.length - 1);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
deleteSystem(system: IParticleSystem) {
|
|
99
|
+
const batchIndex = this.systemToBatchIndex.get(system);
|
|
100
|
+
if (batchIndex !== undefined) {
|
|
101
|
+
this.batches[batchIndex].removeSystem(system);
|
|
102
|
+
this.systemToBatchIndex.delete(system);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
updateSystem(system: IParticleSystem) {
|
|
107
|
+
this.deleteSystem(system);
|
|
108
|
+
this.addSystem(system);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
setDepthTexture(depthTexture: BaseTexture | null) {
|
|
112
|
+
this.depthTexture = depthTexture;
|
|
113
|
+
for (const batch of this.batches) {
|
|
114
|
+
batch.applyDepthTexture(depthTexture);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
update(delta: number) {
|
|
119
|
+
this.systemToBatchIndex.forEach((_value, ps) => {
|
|
120
|
+
(ps as any).update(delta);
|
|
121
|
+
});
|
|
122
|
+
for (let i = 0; i < this.batches.length; i++) {
|
|
123
|
+
this.batches[i].update();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
dispose(): void {
|
|
128
|
+
for (const batch of this.batches) {
|
|
129
|
+
batch.dispose();
|
|
130
|
+
}
|
|
131
|
+
this.batches = [];
|
|
132
|
+
this.systemToBatchIndex.clear();
|
|
133
|
+
super.dispose();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import {Mesh} from '@babylonjs/core/Meshes/mesh';
|
|
2
|
+
import {VertexBuffer} from '@babylonjs/core/Buffers/buffer';
|
|
3
|
+
import {
|
|
4
|
+
Particle,
|
|
5
|
+
EmitterShape,
|
|
6
|
+
ShapeJSON,
|
|
7
|
+
IParticleSystem,
|
|
8
|
+
Vector3,
|
|
9
|
+
Plugin,
|
|
10
|
+
} from 'quarks.core';
|
|
11
|
+
|
|
12
|
+
export class MeshSurfaceEmitter implements EmitterShape {
|
|
13
|
+
type = 'mesh_surface';
|
|
14
|
+
|
|
15
|
+
private _triangleIndexToArea: number[] = [];
|
|
16
|
+
private _mesh?: Mesh;
|
|
17
|
+
private _positions?: Float32Array;
|
|
18
|
+
private _indices?: Uint32Array | Int32Array;
|
|
19
|
+
private _meshReferenceId?: string;
|
|
20
|
+
|
|
21
|
+
get mesh() {
|
|
22
|
+
return this._mesh;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
set mesh(mesh: Mesh | undefined) {
|
|
26
|
+
this._mesh = mesh;
|
|
27
|
+
if (!mesh) return;
|
|
28
|
+
|
|
29
|
+
const positions = mesh.getVerticesData(VertexBuffer.PositionKind);
|
|
30
|
+
const indices = mesh.getIndices();
|
|
31
|
+
if (!positions || !indices) return;
|
|
32
|
+
|
|
33
|
+
this._positions = new Float32Array(positions);
|
|
34
|
+
this._indices = new Int32Array(indices);
|
|
35
|
+
|
|
36
|
+
this._triangleIndexToArea.length = 0;
|
|
37
|
+
let area = 0;
|
|
38
|
+
const triCount = indices.length / 3;
|
|
39
|
+
this._triangleIndexToArea.push(0);
|
|
40
|
+
|
|
41
|
+
const a = new Vector3();
|
|
42
|
+
const b = new Vector3();
|
|
43
|
+
const c = new Vector3();
|
|
44
|
+
|
|
45
|
+
for (let i = 0; i < triCount; i++) {
|
|
46
|
+
const i0 = indices[i * 3];
|
|
47
|
+
const i1 = indices[i * 3 + 1];
|
|
48
|
+
const i2 = indices[i * 3 + 2];
|
|
49
|
+
|
|
50
|
+
a.set(positions[i0 * 3], positions[i0 * 3 + 1], positions[i0 * 3 + 2]);
|
|
51
|
+
b.set(positions[i1 * 3], positions[i1 * 3 + 1], positions[i1 * 3 + 2]);
|
|
52
|
+
c.set(positions[i2 * 3], positions[i2 * 3 + 1], positions[i2 * 3 + 2]);
|
|
53
|
+
|
|
54
|
+
b.sub(a);
|
|
55
|
+
c.sub(a);
|
|
56
|
+
const cross = new Vector3();
|
|
57
|
+
cross.crossVectors(b, c);
|
|
58
|
+
area += cross.length() * 0.5;
|
|
59
|
+
this._triangleIndexToArea.push(area);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
constructor(mesh?: Mesh, meshReferenceId?: string) {
|
|
64
|
+
this._meshReferenceId = meshReferenceId;
|
|
65
|
+
if (mesh) this.mesh = mesh;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
initialize(p: Particle) {
|
|
69
|
+
if (!this._positions || !this._indices) {
|
|
70
|
+
p.position.set(0, 0, 0);
|
|
71
|
+
p.velocity.set(0, 0, 1).multiplyScalar(p.startSpeed);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const triCount = this._triangleIndexToArea.length - 1;
|
|
76
|
+
let left = 0, right = triCount;
|
|
77
|
+
const target = Math.random() * this._triangleIndexToArea[triCount];
|
|
78
|
+
|
|
79
|
+
while (left + 1 < right) {
|
|
80
|
+
const mid = Math.floor((left + right) / 2);
|
|
81
|
+
if (target < this._triangleIndexToArea[mid]) {
|
|
82
|
+
right = mid;
|
|
83
|
+
} else {
|
|
84
|
+
left = mid;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let u1 = Math.random();
|
|
89
|
+
let u2 = Math.random();
|
|
90
|
+
if (u1 + u2 > 1) {
|
|
91
|
+
u1 = 1 - u1;
|
|
92
|
+
u2 = 1 - u2;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const idx0 = this._indices[left * 3];
|
|
96
|
+
const idx1 = this._indices[left * 3 + 1];
|
|
97
|
+
const idx2 = this._indices[left * 3 + 2];
|
|
98
|
+
|
|
99
|
+
const ax = this._positions[idx0 * 3], ay = this._positions[idx0 * 3 + 1], az = this._positions[idx0 * 3 + 2];
|
|
100
|
+
const bx = this._positions[idx1 * 3] - ax, by = this._positions[idx1 * 3 + 1] - ay, bz = this._positions[idx1 * 3 + 2] - az;
|
|
101
|
+
const cx = this._positions[idx2 * 3] - ax, cy = this._positions[idx2 * 3 + 1] - ay, cz = this._positions[idx2 * 3 + 2] - az;
|
|
102
|
+
|
|
103
|
+
p.position.set(ax + bx * u1 + cx * u2, ay + by * u1 + cy * u2, az + bz * u1 + cz * u2);
|
|
104
|
+
|
|
105
|
+
const nx = by * cz - bz * cy;
|
|
106
|
+
const ny = bz * cx - bx * cz;
|
|
107
|
+
const nz = bx * cy - by * cx;
|
|
108
|
+
const len = Math.sqrt(nx * nx + ny * ny + nz * nz) || 1;
|
|
109
|
+
p.velocity.set(nx / len, ny / len, nz / len).multiplyScalar(p.startSpeed);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
toJSON(): ShapeJSON {
|
|
113
|
+
return {type: 'mesh_surface', mesh: this._mesh ? (this._mesh as any).uniqueId?.toString() : this._meshReferenceId ?? ''};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
static fromJSON(json: any): MeshSurfaceEmitter {
|
|
117
|
+
return new MeshSurfaceEmitter(undefined, json?.mesh);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
clone(): EmitterShape {
|
|
121
|
+
return new MeshSurfaceEmitter(this._mesh, this._meshReferenceId);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
update(_system: IParticleSystem, _delta: number): void {}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export const MeshSurfaceEmitterPlugin: Plugin = {
|
|
128
|
+
id: 'babylon.quarks',
|
|
129
|
+
initialize: () => {},
|
|
130
|
+
emitterShapes: [{
|
|
131
|
+
type: 'mesh_surface',
|
|
132
|
+
params: [['mesh', ['mesh']]],
|
|
133
|
+
constructor: MeshSurfaceEmitter,
|
|
134
|
+
loadJSON: (json: any) => MeshSurfaceEmitter.fromJSON(json),
|
|
135
|
+
}],
|
|
136
|
+
behaviors: [],
|
|
137
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import {TransformNode} from '@babylonjs/core/Meshes/transformNode';
|
|
2
|
+
import {Scene} from '@babylonjs/core/scene';
|
|
3
|
+
import {Matrix4, IParticleSystem, SerializationOptions} from 'quarks.core';
|
|
4
|
+
|
|
5
|
+
export class ParticleEmitter extends TransformNode {
|
|
6
|
+
system: IParticleSystem;
|
|
7
|
+
private _matrixWorld: Matrix4 = new Matrix4();
|
|
8
|
+
|
|
9
|
+
get matrixWorld(): Matrix4 {
|
|
10
|
+
const m = this.getWorldMatrix();
|
|
11
|
+
const e = this._matrixWorld.elements;
|
|
12
|
+
e[0] = m.m[0]; e[1] = m.m[1]; e[2] = m.m[2]; e[3] = m.m[3];
|
|
13
|
+
e[4] = m.m[4]; e[5] = m.m[5]; e[6] = m.m[6]; e[7] = m.m[7];
|
|
14
|
+
e[8] = m.m[8]; e[9] = m.m[9]; e[10] = m.m[10]; e[11] = m.m[11];
|
|
15
|
+
e[12] = m.m[12]; e[13] = m.m[13]; e[14] = m.m[14]; e[15] = m.m[15];
|
|
16
|
+
return this._matrixWorld;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
get visible(): boolean {
|
|
20
|
+
return this.isEnabled();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
set visible(value: boolean) {
|
|
24
|
+
this.setEnabled(value);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get uuid(): string {
|
|
28
|
+
return this.uniqueId.toString();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
constructor(system: IParticleSystem, scene?: Scene) {
|
|
32
|
+
super('particleEmitter', scene || undefined);
|
|
33
|
+
this.system = system;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
dispose(): void {
|
|
37
|
+
super.dispose();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
extractFromCache(cache: any): any[] {
|
|
41
|
+
const values: any[] = [];
|
|
42
|
+
for (const key in cache) {
|
|
43
|
+
const data = cache[key];
|
|
44
|
+
if (data && typeof data === 'object') {
|
|
45
|
+
delete data.metadata;
|
|
46
|
+
}
|
|
47
|
+
values.push(data);
|
|
48
|
+
}
|
|
49
|
+
return values;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
clone(name?: string): ParticleEmitter {
|
|
53
|
+
const clonedSystem = this.system.clone();
|
|
54
|
+
const clonedEmitter = clonedSystem.emitter as ParticleEmitter;
|
|
55
|
+
clonedEmitter.name = name ?? this.name;
|
|
56
|
+
clonedEmitter.position.copyFrom(this.position);
|
|
57
|
+
clonedEmitter.rotation.copyFrom(this.rotation);
|
|
58
|
+
clonedEmitter.scaling.copyFrom(this.scaling);
|
|
59
|
+
if (this.rotationQuaternion) {
|
|
60
|
+
clonedEmitter.rotationQuaternion = this.rotationQuaternion.clone();
|
|
61
|
+
}
|
|
62
|
+
clonedEmitter.setEnabled(this.isEnabled());
|
|
63
|
+
return clonedEmitter;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
toJSON(meta?: any, options: SerializationOptions = {}): any {
|
|
67
|
+
return {
|
|
68
|
+
uuid: (this as any)._quarksUUID ?? this.uniqueId.toString(),
|
|
69
|
+
type: 'ParticleEmitter',
|
|
70
|
+
name: this.name,
|
|
71
|
+
position: [this.position.x, this.position.y, this.position.z],
|
|
72
|
+
rotation: [this.rotation.x, this.rotation.y, this.rotation.z],
|
|
73
|
+
quaternion: this.rotationQuaternion
|
|
74
|
+
? [
|
|
75
|
+
this.rotationQuaternion.x,
|
|
76
|
+
this.rotationQuaternion.y,
|
|
77
|
+
this.rotationQuaternion.z,
|
|
78
|
+
this.rotationQuaternion.w,
|
|
79
|
+
]
|
|
80
|
+
: undefined,
|
|
81
|
+
scale: [this.scaling.x, this.scaling.y, this.scaling.z],
|
|
82
|
+
visible: this.isEnabled(),
|
|
83
|
+
ps: this.system.toJSON(meta, options),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|