hz-particles 1.0.14 → 1.2.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/README.md +84 -60
- package/dist-lib/hz-particles-r3f.cjs +3 -3
- package/dist-lib/hz-particles-r3f.d.ts +22 -17
- package/dist-lib/hz-particles-r3f.mjs +206 -403
- package/dist-lib/hz-particles.cjs +126 -14
- package/dist-lib/hz-particles.d.ts +178 -10
- package/dist-lib/hz-particles.mjs +2387 -1099
- package/package.json +4 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class
|
|
1
|
+
class cs {
|
|
2
2
|
constructor(t = {}) {
|
|
3
3
|
this.config = t, this._posOut = [0, 0, 0], this._rotMatrix = null, this._invRotMatrix = null, this._cachedRotX = void 0, this._cachedRotY = void 0, this._cachedRotZ = void 0;
|
|
4
4
|
}
|
|
@@ -6,21 +6,21 @@ class Z {
|
|
|
6
6
|
* Rebuild the cached rotation matrix if config values changed.
|
|
7
7
|
*/
|
|
8
8
|
_updateRotationMatrix() {
|
|
9
|
-
const t = this.config.
|
|
9
|
+
const t = this.config.emissionRotationX || 0, e = this.config.emissionRotationY || 0, i = this.config.emissionRotationZ || 0;
|
|
10
10
|
if (t === this._cachedRotX && e === this._cachedRotY && i === this._cachedRotZ)
|
|
11
11
|
return;
|
|
12
12
|
this._cachedRotX = t, this._cachedRotY = e, this._cachedRotZ = i;
|
|
13
|
-
const
|
|
13
|
+
const s = t * Math.PI / 180, n = e * Math.PI / 180, o = i * Math.PI / 180, a = Math.cos(s), c = Math.sin(s), l = Math.cos(n), u = Math.sin(n), f = Math.cos(o), h = Math.sin(o);
|
|
14
14
|
this._rotMatrix = [
|
|
15
|
-
l * d,
|
|
16
|
-
s * u * d - o * f,
|
|
17
|
-
o * u * d + s * f,
|
|
18
15
|
l * f,
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
c * u * f - a * h,
|
|
17
|
+
a * u * f + c * h,
|
|
18
|
+
l * h,
|
|
19
|
+
c * u * h + a * f,
|
|
20
|
+
a * u * h - c * f,
|
|
21
21
|
-u,
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
c * l,
|
|
23
|
+
a * l
|
|
24
24
|
], this._invRotMatrix = [
|
|
25
25
|
this._rotMatrix[0],
|
|
26
26
|
this._rotMatrix[3],
|
|
@@ -34,90 +34,90 @@ class Z {
|
|
|
34
34
|
];
|
|
35
35
|
}
|
|
36
36
|
emitParticle(t, e, i) {
|
|
37
|
-
const
|
|
38
|
-
if (this.config.emissionShape === "cube" ? this._emitFromCube(
|
|
37
|
+
const s = this._posOut;
|
|
38
|
+
if (this.config.emissionShape === "cube" || this.config.emissionShape === "box" ? this._emitFromCube(s) : this.config.emissionShape === "sphere" ? this._emitFromSphere(s) : this.config.emissionShape === "square" ? this._emitFromSquare(s) : this.config.emissionShape === "circle" ? this._emitFromCircle(s) : this.config.emissionShape === "cylinder" ? this._emitFromCylinder(s) : this.config.emissionShape === "plain" ? this._emitFromPlain(s) : this.config.emissionShape === "cone" ? this._emitFromCone(s) : this.config.emissionShape === "torus" ? this._emitFromTorus(s) : this.config.emissionShape === "line" ? this._emitFromLine(s) : this.config.emissionShape === "hemisphere" ? this._emitFromHemisphere(s) : this.config.emissionShape === "disc" ? this._emitFromDisc(s) : this.config.emissionShape === "annulus" ? this._emitFromAnnulus(s) : this.config.emissionShape === "capsule" ? this._emitFromCapsule(s) : this.config.emissionShape === "arc" ? this._emitFromArc(s) : this.config.emissionShape === "spiral" ? this._emitFromSpiral(s) : this.config.emissionShape === "frustum" ? this._emitFromFrustum(s) : this.config.emissionShape === "cubeSurface" ? this._emitFromCubeSurface(s) : this.config.emissionShape === "sphereSurface" ? this._emitFromSphereSurface(s) : this.config.emissionShape === "boxFrame" ? this._emitFromBoxFrame(s) : this.config.emissionShape === "polygon" ? this._emitFromPolygon(s) : this.config.emissionShape === "rectangle" ? this._emitFromRectangle(s) : (s[0] = 0, s[1] = 0, s[2] = 0), this.config.emissionRotationX || this.config.emissionRotationY || this.config.emissionRotationZ) {
|
|
39
39
|
this._updateRotationMatrix();
|
|
40
|
-
const
|
|
41
|
-
|
|
40
|
+
const a = this._rotMatrix, c = s[0], l = s[1], u = s[2];
|
|
41
|
+
s[0] = a[0] * c + a[1] * l + a[2] * u, s[1] = a[3] * c + a[4] * l + a[5] * u, s[2] = a[6] * c + a[7] * l + a[8] * u;
|
|
42
42
|
}
|
|
43
|
-
(this.config.
|
|
44
|
-
const
|
|
45
|
-
t[
|
|
46
|
-
const
|
|
47
|
-
this.calculateVelocity(
|
|
43
|
+
(this.config.emissionPositionX || this.config.emissionPositionY || this.config.emissionPositionZ) && (s[0] += this.config.emissionPositionX || 0, s[1] += this.config.emissionPositionY || 0, s[2] += this.config.emissionPositionZ || 0);
|
|
44
|
+
const n = e * 8;
|
|
45
|
+
t[n] = s[0], t[n + 1] = s[1], t[n + 2] = s[2];
|
|
46
|
+
const o = e * 4;
|
|
47
|
+
this.calculateVelocity(s[0], s[1], s[2], i, o), this.setParticleColor(t, n), this.setParticleLifetime(t, n);
|
|
48
48
|
}
|
|
49
49
|
// Apply rotation using cached matrix
|
|
50
50
|
applyRotation(t, e, i) {
|
|
51
51
|
this._updateRotationMatrix();
|
|
52
|
-
const
|
|
52
|
+
const s = this._rotMatrix;
|
|
53
53
|
return [
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
s[0] * t + s[1] * e + s[2] * i,
|
|
55
|
+
s[3] * t + s[4] * e + s[5] * i,
|
|
56
|
+
s[6] * t + s[7] * e + s[8] * i
|
|
57
57
|
];
|
|
58
58
|
}
|
|
59
59
|
// Apply inverse rotation using cached matrix
|
|
60
60
|
inverseRotation(t, e, i) {
|
|
61
61
|
this._updateRotationMatrix();
|
|
62
|
-
const
|
|
62
|
+
const s = this._invRotMatrix;
|
|
63
63
|
return [
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
s[0] * t + s[1] * e + s[2] * i,
|
|
65
|
+
s[3] * t + s[4] * e + s[5] * i,
|
|
66
|
+
s[6] * t + s[7] * e + s[8] * i
|
|
67
67
|
];
|
|
68
68
|
}
|
|
69
69
|
_emitFromCube(t) {
|
|
70
70
|
let e = this.config.innerLength || 0, i = this.config.outerLength || this.config.cubeLength;
|
|
71
71
|
if (e > 0) {
|
|
72
|
-
const
|
|
73
|
-
let
|
|
74
|
-
switch (
|
|
72
|
+
const s = Math.floor(Math.random() * 6), n = Math.random() - 0.5, o = Math.random() - 0.5;
|
|
73
|
+
let a, c, l;
|
|
74
|
+
switch (s) {
|
|
75
75
|
case 0:
|
|
76
|
-
|
|
76
|
+
a = n, c = o, l = 0.5;
|
|
77
77
|
break;
|
|
78
78
|
case 1:
|
|
79
|
-
|
|
79
|
+
a = n, c = o, l = -0.5;
|
|
80
80
|
break;
|
|
81
81
|
case 2:
|
|
82
|
-
|
|
82
|
+
a = 0.5, c = n, l = o;
|
|
83
83
|
break;
|
|
84
84
|
case 3:
|
|
85
|
-
|
|
85
|
+
a = -0.5, c = n, l = o;
|
|
86
86
|
break;
|
|
87
87
|
case 4:
|
|
88
|
-
|
|
88
|
+
a = n, c = 0.5, l = o;
|
|
89
89
|
break;
|
|
90
90
|
case 5:
|
|
91
|
-
|
|
91
|
+
a = n, c = -0.5, l = o;
|
|
92
92
|
break;
|
|
93
93
|
}
|
|
94
|
-
const u = Math.random(),
|
|
95
|
-
t[0] =
|
|
94
|
+
const u = Math.random(), f = e + u * (i - e);
|
|
95
|
+
t[0] = a * f, t[1] = c * f, t[2] = l * f;
|
|
96
96
|
} else
|
|
97
97
|
t[0] = (Math.random() - 0.5) * i, t[1] = (Math.random() - 0.5) * i, t[2] = (Math.random() - 0.5) * i;
|
|
98
98
|
}
|
|
99
99
|
_emitFromSphere(t) {
|
|
100
|
-
const e = Math.random() * 2 * Math.PI, i = Math.acos(2 * Math.random() - 1),
|
|
101
|
-
let
|
|
102
|
-
this.config.innerRadius === 0 ?
|
|
100
|
+
const e = Math.random() * 2 * Math.PI, i = Math.acos(2 * Math.random() - 1), s = Math.sin(i) * Math.cos(e), n = Math.sin(i) * Math.sin(e), o = Math.cos(i);
|
|
101
|
+
let a;
|
|
102
|
+
this.config.innerRadius === 0 ? a = this.config.outerRadius * Math.cbrt(Math.random()) : a = this.config.innerRadius + (this.config.outerRadius - this.config.innerRadius) * Math.random(), t[0] = s * a, t[1] = n * a, t[2] = o * a;
|
|
103
103
|
}
|
|
104
104
|
_emitFromSquare(t) {
|
|
105
105
|
const e = this.config.squareInnerSize || 0, i = this.config.squareSize || 2;
|
|
106
106
|
if (e > 0) {
|
|
107
|
-
const
|
|
108
|
-
let
|
|
109
|
-
switch (
|
|
107
|
+
const s = Math.floor(Math.random() * 4);
|
|
108
|
+
let n = e + (i - e) * Math.random();
|
|
109
|
+
switch (s) {
|
|
110
110
|
case 0:
|
|
111
|
-
t[0] = (Math.random() * 2 - 1) *
|
|
111
|
+
t[0] = (Math.random() * 2 - 1) * n, t[1] = n;
|
|
112
112
|
break;
|
|
113
113
|
case 1:
|
|
114
|
-
t[0] =
|
|
114
|
+
t[0] = n, t[1] = (Math.random() * 2 - 1) * n;
|
|
115
115
|
break;
|
|
116
116
|
case 2:
|
|
117
|
-
t[0] = (Math.random() * 2 - 1) *
|
|
117
|
+
t[0] = (Math.random() * 2 - 1) * n, t[1] = -n;
|
|
118
118
|
break;
|
|
119
119
|
case 3:
|
|
120
|
-
t[0] = -
|
|
120
|
+
t[0] = -n, t[1] = (Math.random() * 2 - 1) * n;
|
|
121
121
|
break;
|
|
122
122
|
}
|
|
123
123
|
} else
|
|
@@ -125,153 +125,157 @@ class Z {
|
|
|
125
125
|
t[2] = 0;
|
|
126
126
|
}
|
|
127
127
|
_emitFromCircle(t) {
|
|
128
|
-
const e = this.config.circleInnerRadius || 0, i = this.config.circleOuterRadius || 2,
|
|
129
|
-
let
|
|
130
|
-
e > 0 ?
|
|
128
|
+
const e = this.config.circleInnerRadius || 0, i = this.config.circleOuterRadius || 2, s = Math.random() * Math.PI * 2;
|
|
129
|
+
let n;
|
|
130
|
+
e > 0 ? n = e + (i - e) * Math.random() : n = i * Math.sqrt(Math.random()), t[0] = Math.cos(s) * n, t[1] = Math.sin(s) * n, t[2] = 0;
|
|
131
131
|
}
|
|
132
132
|
_emitFromPlain(t) {
|
|
133
133
|
const e = this.config.planeWidth || 2, i = this.config.planeDepth || 2;
|
|
134
134
|
t[0] = (Math.random() - 0.5) * e, t[1] = 0, t[2] = (Math.random() - 0.5) * i;
|
|
135
135
|
}
|
|
136
136
|
_emitFromCone(t) {
|
|
137
|
-
const e = this.config.coneInnerRadius || 0, i = this.config.coneOuterRadius || 2,
|
|
137
|
+
const e = this.config.coneInnerRadius || 0, i = this.config.coneOuterRadius || 2, s = this.config.coneHeight || 4, n = Math.random() * Math.PI * 2, o = Math.random(), a = o * s, c = i * (1 - o);
|
|
138
138
|
let l;
|
|
139
139
|
if (e > 0) {
|
|
140
|
-
const u = e * (1 -
|
|
141
|
-
l = u + (
|
|
140
|
+
const u = e * (1 - o);
|
|
141
|
+
l = u + (c - u) * Math.random();
|
|
142
142
|
} else
|
|
143
|
-
l =
|
|
144
|
-
t[0] = Math.cos(
|
|
143
|
+
l = c * Math.sqrt(Math.random());
|
|
144
|
+
t[0] = Math.cos(n) * l, t[1] = a, t[2] = Math.sin(n) * l;
|
|
145
145
|
}
|
|
146
146
|
_emitFromTorus(t) {
|
|
147
|
-
const e = this.config.torusMajorRadius || 2, i = this.config.torusMinorRadius || 0.5,
|
|
148
|
-
t[0] = (e +
|
|
147
|
+
const e = this.config.torusMajorRadius || 2, i = this.config.torusMinorRadius || 0.5, s = Math.random() * Math.PI * 2, n = Math.random() * Math.PI * 2, o = i * Math.sqrt(Math.random());
|
|
148
|
+
t[0] = (e + o * Math.cos(n)) * Math.cos(s), t[1] = o * Math.sin(n), t[2] = (e + o * Math.cos(n)) * Math.sin(s);
|
|
149
149
|
}
|
|
150
150
|
_emitFromLine(t) {
|
|
151
151
|
const e = this.config.lineLength || 4, i = Math.random();
|
|
152
152
|
t[0] = 0, t[1] = (i - 0.5) * e, t[2] = 0;
|
|
153
153
|
}
|
|
154
154
|
_emitFromHemisphere(t) {
|
|
155
|
-
const e = this.config.hemisphereInnerRadius || 0, i = this.config.hemisphereOuterRadius || 2,
|
|
155
|
+
const e = this.config.hemisphereInnerRadius || 0, i = this.config.hemisphereOuterRadius || 2, s = Math.random() * Math.PI * 2, n = Math.acos(Math.random()), o = Math.sin(n) * Math.cos(s), a = Math.cos(n), c = Math.sin(n) * Math.sin(s);
|
|
156
156
|
let l;
|
|
157
|
-
e > 0 ? l = e + (i - e) * Math.random() : l = i * Math.cbrt(Math.random()), t[0] =
|
|
157
|
+
e > 0 ? l = e + (i - e) * Math.random() : l = i * Math.cbrt(Math.random()), t[0] = o * l, t[1] = a * l, t[2] = c * l;
|
|
158
158
|
}
|
|
159
159
|
_emitFromDisc(t) {
|
|
160
|
-
const e = this.config.discRadius || 2, i = Math.random() * Math.PI * 2,
|
|
161
|
-
t[0] = Math.cos(i) *
|
|
160
|
+
const e = this.config.discRadius || 2, i = Math.random() * Math.PI * 2, s = e * Math.sqrt(Math.random());
|
|
161
|
+
t[0] = Math.cos(i) * s, t[1] = 0, t[2] = Math.sin(i) * s;
|
|
162
162
|
}
|
|
163
163
|
_emitFromAnnulus(t) {
|
|
164
|
-
const e = this.config.annulusInnerRadius || 1, i = this.config.annulusOuterRadius || 2,
|
|
165
|
-
t[0] = Math.cos(
|
|
164
|
+
const e = this.config.annulusInnerRadius || 1, i = this.config.annulusOuterRadius || 2, s = Math.random() * Math.PI * 2, n = e + (i - e) * Math.random();
|
|
165
|
+
t[0] = Math.cos(s) * n, t[1] = 0, t[2] = Math.sin(s) * n;
|
|
166
166
|
}
|
|
167
167
|
_emitFromCapsule(t) {
|
|
168
|
-
const e = this.config.capsuleRadius || 0.5, i = this.config.capsuleHeight || 4,
|
|
169
|
-
if (Math.random() <
|
|
170
|
-
const
|
|
171
|
-
t[0] = Math.cos(
|
|
168
|
+
const e = this.config.capsuleRadius || 0.5, i = this.config.capsuleHeight || 4, s = i * 0.5, n = Math.PI * e * e * i, o = 4 / 3 * Math.PI * e * e * e, a = n / (n + o);
|
|
169
|
+
if (Math.random() < a) {
|
|
170
|
+
const c = Math.random() * Math.PI * 2, l = e * Math.sqrt(Math.random());
|
|
171
|
+
t[0] = Math.cos(c) * l, t[1] = (Math.random() - 0.5) * i, t[2] = Math.sin(c) * l;
|
|
172
172
|
} else {
|
|
173
|
-
const
|
|
174
|
-
t[0] = u * Math.sin(l) * Math.cos(
|
|
173
|
+
const c = Math.random() * Math.PI * 2, l = Math.acos(2 * Math.random() - 1), u = e * Math.cbrt(Math.random());
|
|
174
|
+
t[0] = u * Math.sin(l) * Math.cos(c), t[1] = u * Math.cos(l), t[2] = u * Math.sin(l) * Math.sin(c), t[1] += t[1] >= 0 ? s : -s;
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
177
|
_emitFromArc(t) {
|
|
178
|
-
const e = this.config.arcStartAngle || 0, i = this.config.arcEndAngle || 180,
|
|
178
|
+
const e = this.config.arcStartAngle || 0, i = this.config.arcEndAngle || 180, s = this.config.arcInnerRadius || 0, n = this.config.arcOuterRadius || 2, o = e * Math.PI / 180, a = i * Math.PI / 180, c = o + Math.random() * (a - o);
|
|
179
179
|
let l;
|
|
180
|
-
|
|
180
|
+
s > 0 ? l = s + (n - s) * Math.random() : l = n * Math.sqrt(Math.random()), t[0] = Math.cos(c) * l, t[1] = Math.sin(c) * l, t[2] = 0;
|
|
181
181
|
}
|
|
182
182
|
_emitFromSpiral(t) {
|
|
183
|
-
const e = this.config.spiralTurns || 3, i = this.config.spiralRadiusStart || 0.5,
|
|
184
|
-
t[0] = Math.cos(
|
|
183
|
+
const e = this.config.spiralTurns || 3, i = this.config.spiralRadiusStart || 0.5, s = this.config.spiralRadiusEnd || 2, n = this.config.spiralHeight || 4, o = Math.random(), a = o * e * Math.PI * 2, c = i + (s - i) * o;
|
|
184
|
+
t[0] = Math.cos(a) * c, t[1] = (o - 0.5) * n, t[2] = Math.sin(a) * c;
|
|
185
185
|
}
|
|
186
186
|
_emitFromFrustum(t) {
|
|
187
|
-
const e = this.config.frustumRadiusNear || 0.5, i = this.config.frustumRadiusFar || 2,
|
|
188
|
-
t[0] = Math.cos(
|
|
187
|
+
const e = this.config.frustumRadiusNear || 0.5, i = this.config.frustumRadiusFar || 2, s = this.config.frustumHeight || 4, n = Math.random() * Math.PI * 2, o = Math.random(), a = o * s, l = (e + (i - e) * o) * Math.sqrt(Math.random());
|
|
188
|
+
t[0] = Math.cos(n) * l, t[1] = a, t[2] = Math.sin(n) * l;
|
|
189
189
|
}
|
|
190
190
|
_emitFromCubeSurface(t) {
|
|
191
|
-
const e = this.config.cubeSurfaceSize || 2, i = e * 0.5,
|
|
192
|
-
switch (
|
|
191
|
+
const e = this.config.cubeSurfaceSize || 2, i = e * 0.5, s = Math.floor(Math.random() * 6), n = (Math.random() - 0.5) * e, o = (Math.random() - 0.5) * e;
|
|
192
|
+
switch (s) {
|
|
193
193
|
case 0:
|
|
194
|
-
t[0] =
|
|
194
|
+
t[0] = n, t[1] = o, t[2] = i;
|
|
195
195
|
break;
|
|
196
196
|
case 1:
|
|
197
|
-
t[0] =
|
|
197
|
+
t[0] = n, t[1] = o, t[2] = -i;
|
|
198
198
|
break;
|
|
199
199
|
case 2:
|
|
200
|
-
t[0] = i, t[1] =
|
|
200
|
+
t[0] = i, t[1] = n, t[2] = o;
|
|
201
201
|
break;
|
|
202
202
|
case 3:
|
|
203
|
-
t[0] = -i, t[1] =
|
|
203
|
+
t[0] = -i, t[1] = n, t[2] = o;
|
|
204
204
|
break;
|
|
205
205
|
case 4:
|
|
206
|
-
t[0] =
|
|
206
|
+
t[0] = n, t[1] = i, t[2] = o;
|
|
207
207
|
break;
|
|
208
208
|
case 5:
|
|
209
|
-
t[0] =
|
|
209
|
+
t[0] = n, t[1] = -i, t[2] = o;
|
|
210
210
|
break;
|
|
211
211
|
}
|
|
212
212
|
}
|
|
213
213
|
_emitFromSphereSurface(t) {
|
|
214
|
-
const e = this.config.sphereSurfaceRadius || 2, i = Math.random() * Math.PI * 2,
|
|
215
|
-
t[0] = e * Math.sin(
|
|
214
|
+
const e = this.config.sphereSurfaceRadius || 2, i = Math.random() * Math.PI * 2, s = Math.acos(2 * Math.random() - 1);
|
|
215
|
+
t[0] = e * Math.sin(s) * Math.cos(i), t[1] = e * Math.sin(s) * Math.sin(i), t[2] = e * Math.cos(s);
|
|
216
216
|
}
|
|
217
217
|
_emitFromBoxFrame(t) {
|
|
218
|
-
const e = this.config.boxFrameSize || 2, i = e * 0.5,
|
|
219
|
-
if (
|
|
220
|
-
const [
|
|
221
|
-
t[0] =
|
|
222
|
-
} else if (
|
|
223
|
-
const [
|
|
224
|
-
t[0] =
|
|
218
|
+
const e = this.config.boxFrameSize || 2, i = e * 0.5, s = Math.floor(Math.random() * 12), o = (Math.random() - 0.5) * e, a = [[-1, -1], [-1, 1], [1, -1], [1, 1]];
|
|
219
|
+
if (s < 4) {
|
|
220
|
+
const [c, l] = a[s];
|
|
221
|
+
t[0] = o, t[1] = c * i, t[2] = l * i;
|
|
222
|
+
} else if (s < 8) {
|
|
223
|
+
const [c, l] = a[s - 4];
|
|
224
|
+
t[0] = c * i, t[1] = o, t[2] = l * i;
|
|
225
225
|
} else {
|
|
226
|
-
const [
|
|
227
|
-
t[0] =
|
|
226
|
+
const [c, l] = a[s - 8];
|
|
227
|
+
t[0] = c * i, t[1] = l * i, t[2] = o;
|
|
228
228
|
}
|
|
229
229
|
}
|
|
230
230
|
_emitFromPolygon(t) {
|
|
231
|
-
const e = Math.max(3, Math.floor(this.config.polygonSides || 6)), i = this.config.polygonRadius || 2,
|
|
232
|
-
let
|
|
233
|
-
|
|
234
|
-
const l =
|
|
231
|
+
const e = Math.max(3, Math.floor(this.config.polygonSides || 6)), i = this.config.polygonRadius || 2, s = Math.floor(Math.random() * e), n = s / e * Math.PI * 2, o = (s + 1) / e * Math.PI * 2;
|
|
232
|
+
let a = Math.random(), c = Math.random();
|
|
233
|
+
a + c > 1 && (a = 1 - a, c = 1 - c);
|
|
234
|
+
const l = a * Math.cos(n) + c * Math.cos(o), u = a * Math.sin(n) + c * Math.sin(o);
|
|
235
235
|
t[0] = l * i, t[1] = u * i, t[2] = 0;
|
|
236
236
|
}
|
|
237
|
+
_emitFromRectangle(t) {
|
|
238
|
+
const e = this.config.rectangleWidth || 2, i = this.config.rectangleHeight || 2;
|
|
239
|
+
t[0] = (Math.random() - 0.5) * e, t[1] = (Math.random() - 0.5) * i, t[2] = 0;
|
|
240
|
+
}
|
|
237
241
|
_emitFromCylinder(t) {
|
|
238
|
-
const e = this.config.cylinderInnerRadius || 0, i = this.config.cylinderOuterRadius || 2,
|
|
239
|
-
let
|
|
240
|
-
e > 0 ?
|
|
242
|
+
const e = this.config.cylinderInnerRadius || 0, i = this.config.cylinderOuterRadius || 2, s = this.config.cylinderHeight || 4, n = Math.random() * Math.PI * 2;
|
|
243
|
+
let o;
|
|
244
|
+
e > 0 ? o = e + (i - e) * Math.random() : o = i * Math.sqrt(Math.random()), t[0] = Math.cos(n) * o, t[1] = (Math.random() - 0.5) * s, t[2] = Math.sin(n) * o;
|
|
241
245
|
}
|
|
242
|
-
calculateVelocity(t, e, i,
|
|
243
|
-
const
|
|
244
|
-
let
|
|
245
|
-
if (
|
|
246
|
-
let
|
|
246
|
+
calculateVelocity(t, e, i, s, n) {
|
|
247
|
+
const o = this.config.emissionPositionX || 0, a = this.config.emissionPositionY || 0, c = this.config.emissionPositionZ || 0, l = t - o, u = e - a, f = i - c, h = Math.sqrt(l * l + u * u + f * f);
|
|
248
|
+
let m, S, R;
|
|
249
|
+
if (h > 1e-4) {
|
|
250
|
+
let C = !1;
|
|
247
251
|
if (this.config.emissionShape === "circle" && this.config.circleVelocityDirection === "tangential") {
|
|
248
|
-
const
|
|
249
|
-
if (
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
+
const B = this.inverseRotation(l, u, f), A = Math.sqrt(B[0] * B[0] + B[1] * B[1]);
|
|
253
|
+
if (A > 1e-4) {
|
|
254
|
+
const P = -B[1] / A, _ = B[0] / A, T = this.applyRotation(P, _, 0);
|
|
255
|
+
m = T[0], S = T[1], R = T[2], C = !0;
|
|
252
256
|
}
|
|
253
257
|
} else if (this.config.emissionShape === "cylinder" && this.config.cylinderVelocityDirection === "tangential") {
|
|
254
|
-
const
|
|
255
|
-
if (
|
|
256
|
-
const
|
|
257
|
-
|
|
258
|
+
const B = this.inverseRotation(l, u, f), A = Math.sqrt(B[0] * B[0] + B[2] * B[2]);
|
|
259
|
+
if (A > 1e-4) {
|
|
260
|
+
const P = -B[2] / A, _ = B[0] / A, T = this.applyRotation(P, 0, _);
|
|
261
|
+
m = T[0], S = T[1], R = T[2], C = !0;
|
|
258
262
|
} else {
|
|
259
|
-
const
|
|
260
|
-
|
|
263
|
+
const P = Math.random() * Math.PI * 2, _ = this.applyRotation(Math.cos(P), 0, Math.sin(P));
|
|
264
|
+
m = _[0], S = _[1], R = _[2], C = !0;
|
|
261
265
|
}
|
|
262
266
|
}
|
|
263
|
-
|
|
267
|
+
C || (m = l / h, S = u / h, R = f / h);
|
|
264
268
|
} else {
|
|
265
|
-
const
|
|
266
|
-
|
|
269
|
+
const C = Math.random() * Math.PI * 2, B = Math.acos(2 * Math.random() - 1);
|
|
270
|
+
m = Math.sin(B) * Math.cos(C), S = Math.sin(B) * Math.sin(C), R = Math.cos(B);
|
|
267
271
|
}
|
|
268
|
-
let
|
|
269
|
-
this.config.randomSpeed ?
|
|
272
|
+
let D;
|
|
273
|
+
this.config.randomSpeed ? D = (this.config.minSpeed || 0) + Math.random() * ((this.config.maxSpeed || 1) - (this.config.minSpeed || 0)) : D = this.config.particleSpeed, s[n] = this.config.overrideXVelocity ? this.config.xVelocity : m * D, s[n + 1] = this.config.overrideYVelocity ? this.config.yVelocity : S * D, s[n + 2] = this.config.overrideZVelocity ? this.config.zVelocity : R * D, s[n + 3] = 0;
|
|
270
274
|
}
|
|
271
275
|
setParticleColor(t, e) {
|
|
272
276
|
if (this.config.randomColorEnabled && this.config.randomColors.length > 0) {
|
|
273
|
-
const i = this.config.randomColors,
|
|
274
|
-
t[e + 3] =
|
|
277
|
+
const i = this.config.randomColors, s = i[Math.floor(Math.random() * i.length)];
|
|
278
|
+
t[e + 3] = s[0], t[e + 4] = s[1], t[e + 5] = s[2];
|
|
275
279
|
} else this.config.colorTransitionEnabled ? (t[e + 3] = this.config.startColor[0], t[e + 4] = this.config.startColor[1], t[e + 5] = this.config.startColor[2]) : (t[e + 3] = this.config.particleColor[0], t[e + 4] = this.config.particleColor[1], t[e + 5] = this.config.particleColor[2]);
|
|
276
280
|
}
|
|
277
281
|
setParticleLifetime(t, e) {
|
|
@@ -279,7 +283,7 @@ class Z {
|
|
|
279
283
|
t[e + 6] = 0, t[e + 7] = i + (Math.random() * 0.4 - 0.2) * i;
|
|
280
284
|
}
|
|
281
285
|
}
|
|
282
|
-
class
|
|
286
|
+
class us {
|
|
283
287
|
constructor(t, e = 1e4) {
|
|
284
288
|
this.device = t, this.physicsSettings = {
|
|
285
289
|
deltaTime: 0.016,
|
|
@@ -321,17 +325,25 @@ class q {
|
|
|
321
325
|
size: e * 4 * 4,
|
|
322
326
|
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
|
|
323
327
|
label: "RenderReadback_Velocity"
|
|
324
|
-
}), this._renderStagingInUse = !1
|
|
328
|
+
}), this._renderStagingInUse = !1, this._scriptStagingParticleBuffer = t.createBuffer({
|
|
329
|
+
size: e * 8 * 4,
|
|
330
|
+
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
|
|
331
|
+
label: "ScriptReadback_ParticleData"
|
|
332
|
+
}), this._scriptStagingVelocityBuffer = t.createBuffer({
|
|
333
|
+
size: e * 4 * 4,
|
|
334
|
+
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
|
|
335
|
+
label: "ScriptReadback_Velocity"
|
|
336
|
+
}), this._scriptStagingInUse = !1;
|
|
325
337
|
}
|
|
326
338
|
async initComputePipeline(t, e, i) {
|
|
327
339
|
try {
|
|
328
340
|
return await this.createComputePipeline(t, e, i), this.computeReady = !0, !0;
|
|
329
|
-
} catch (
|
|
330
|
-
return console.error("Error initializing compute pipeline:",
|
|
341
|
+
} catch (s) {
|
|
342
|
+
return console.error("Error initializing compute pipeline:", s), !1;
|
|
331
343
|
}
|
|
332
344
|
}
|
|
333
345
|
async createComputePipeline(t, e, i) {
|
|
334
|
-
const { particlePhysicsShader:
|
|
346
|
+
const { particlePhysicsShader: s } = await Promise.resolve().then(() => _i);
|
|
335
347
|
this.computeBindGroupLayout = this.device.createBindGroupLayout({
|
|
336
348
|
entries: [
|
|
337
349
|
{
|
|
@@ -361,7 +373,7 @@ class q {
|
|
|
361
373
|
}),
|
|
362
374
|
compute: {
|
|
363
375
|
module: this.device.createShaderModule({
|
|
364
|
-
code:
|
|
376
|
+
code: s
|
|
365
377
|
}),
|
|
366
378
|
entryPoint: "main"
|
|
367
379
|
}
|
|
@@ -387,49 +399,49 @@ class q {
|
|
|
387
399
|
]
|
|
388
400
|
});
|
|
389
401
|
}
|
|
390
|
-
updatePhysics(t, e, i,
|
|
402
|
+
updatePhysics(t, e, i, s, n, o) {
|
|
391
403
|
if (e <= 0 || !this.computeReady)
|
|
392
404
|
return;
|
|
393
|
-
const
|
|
394
|
-
|
|
395
|
-
const l =
|
|
405
|
+
const a = this._physicsData, c = this.physicsSettings;
|
|
406
|
+
a[0] = t, a[1] = i.particleSpeed, a[2] = c.gravity, a[3] = c.turbulence, a[4] = c.attractorStrength, a[5] = c.damping, a[6] = c.attractorPosition[0], a[7] = c.attractorPosition[1], a[8] = c.attractorPosition[2], this._physicsDataU32View[9] = e, a[10] = c.confinementEnabled ? 1 : 0, a[11] = c.confinementShape === "sphere" ? 1 : 0, a[12] = c.confinementMode === "kill" ? 1 : 0, a[13] = c.confinementSpace === "local" ? 1 : 0, a[14] = c.confinementBoxHalfSize[0], a[15] = c.confinementBoxHalfSize[1], a[16] = c.confinementBoxHalfSize[2], a[17] = c.confinementSphereRadius, a[18] = c.confinementRestitution, a[19] = c.confinementFriction, a[20] = c.confinementCenter[0], a[21] = c.confinementCenter[1], a[22] = c.confinementCenter[2], a[23] = c.softBoundaryEnabled ? 1 : 0, a[24] = c.softBoundaryStrength, a[25] = c.softBoundaryFalloff, a[26] = i.velocityStretchEnabled ? 1 : 0, a[27] = i.velocityStretchFactor ?? 1, a[28] = 0, a[29] = 0, a[30] = 0, a[31] = 0, this.device.queue.writeBuffer(this.physicsUniformBuffer, 0, a);
|
|
407
|
+
const l = o || this.device.createCommandEncoder({ label: "ParticlePhysicsEncoder" }), u = l.beginComputePass({ label: "ParticlePhysicsPass" });
|
|
396
408
|
u.setPipeline(this.computePipeline), u.setBindGroup(0, this.computeBindGroup);
|
|
397
|
-
const
|
|
398
|
-
u.dispatchWorkgroups(
|
|
409
|
+
const f = Math.max(1, Math.ceil(e / 64));
|
|
410
|
+
u.dispatchWorkgroups(f, 1, 1), u.end(), o || this.device.queue.submit([l.finish()]), this.lastUpdateTime = performance.now() / 1e3;
|
|
399
411
|
}
|
|
400
|
-
async readbackAndProcessParticles(t, e, i,
|
|
412
|
+
async readbackAndProcessParticles(t, e, i, s, n) {
|
|
401
413
|
if (t <= 0)
|
|
402
414
|
return { activeCount: 0, shouldUpdate: !1 };
|
|
403
415
|
if (this._stagingInUse)
|
|
404
416
|
return { activeCount: t, shouldUpdate: !1 };
|
|
405
417
|
try {
|
|
406
418
|
this._stagingInUse = !0;
|
|
407
|
-
const
|
|
419
|
+
const o = this.device.createCommandEncoder({
|
|
408
420
|
label: "ParticleReadbackEncoder"
|
|
409
|
-
}),
|
|
410
|
-
|
|
411
|
-
|
|
421
|
+
}), a = t * 8 * 4;
|
|
422
|
+
o.copyBufferToBuffer(
|
|
423
|
+
s,
|
|
412
424
|
0,
|
|
413
425
|
this._particleDataStagingBuffer,
|
|
414
426
|
0,
|
|
415
|
-
|
|
427
|
+
a
|
|
416
428
|
);
|
|
417
|
-
const
|
|
418
|
-
return
|
|
419
|
-
|
|
429
|
+
const c = t * 4 * 4;
|
|
430
|
+
return o.copyBufferToBuffer(
|
|
431
|
+
n,
|
|
420
432
|
0,
|
|
421
433
|
this._velocityStagingBuffer,
|
|
422
434
|
0,
|
|
423
|
-
|
|
424
|
-
), this.device.queue.submit([
|
|
435
|
+
c
|
|
436
|
+
), this.device.queue.submit([o.finish()]), await Promise.all([
|
|
425
437
|
(async () => {
|
|
426
|
-
await this._particleDataStagingBuffer.mapAsync(GPUMapMode.READ, 0,
|
|
427
|
-
const l = new Float32Array(this._particleDataStagingBuffer.getMappedRange(0,
|
|
438
|
+
await this._particleDataStagingBuffer.mapAsync(GPUMapMode.READ, 0, a);
|
|
439
|
+
const l = new Float32Array(this._particleDataStagingBuffer.getMappedRange(0, a));
|
|
428
440
|
e.set(l), this._particleDataStagingBuffer.unmap();
|
|
429
441
|
})(),
|
|
430
442
|
(async () => {
|
|
431
|
-
await this._velocityStagingBuffer.mapAsync(GPUMapMode.READ, 0,
|
|
432
|
-
const l = new Float32Array(this._velocityStagingBuffer.getMappedRange(0,
|
|
443
|
+
await this._velocityStagingBuffer.mapAsync(GPUMapMode.READ, 0, c);
|
|
444
|
+
const l = new Float32Array(this._velocityStagingBuffer.getMappedRange(0, c));
|
|
433
445
|
i.set(l), this._velocityStagingBuffer.unmap();
|
|
434
446
|
})()
|
|
435
447
|
]), this._stagingInUse = !1, {
|
|
@@ -437,8 +449,8 @@ class q {
|
|
|
437
449
|
particleVelocities: i,
|
|
438
450
|
shouldUpdate: !0
|
|
439
451
|
};
|
|
440
|
-
} catch (
|
|
441
|
-
return this._stagingInUse = !1, console.error("Error reading back particle data:",
|
|
452
|
+
} catch (o) {
|
|
453
|
+
return this._stagingInUse = !1, o && o.name === "AbortError" || console.error("Error reading back particle data:", o), { activeCount: t, shouldUpdate: !1 };
|
|
442
454
|
}
|
|
443
455
|
}
|
|
444
456
|
setDamping(t) {
|
|
@@ -465,37 +477,37 @@ class q {
|
|
|
465
477
|
* @param {GPUBuffer} velocityBuffer
|
|
466
478
|
* @returns {Promise<{particleData: Float32Array, particleVelocities: Float32Array, shouldUpdate: boolean}>}
|
|
467
479
|
*/
|
|
468
|
-
async readbackForRendering(t, e, i,
|
|
480
|
+
async readbackForRendering(t, e, i, s, n) {
|
|
469
481
|
if (t <= 0)
|
|
470
482
|
return { shouldUpdate: !1 };
|
|
471
483
|
if (this._renderStagingInUse)
|
|
472
484
|
return { shouldUpdate: !1 };
|
|
473
485
|
try {
|
|
474
486
|
this._renderStagingInUse = !0;
|
|
475
|
-
const
|
|
487
|
+
const o = t * 8 * 4, a = t * 4 * 4, c = this.device.createCommandEncoder({
|
|
476
488
|
label: "RenderReadbackEncoder"
|
|
477
489
|
});
|
|
478
|
-
return
|
|
479
|
-
|
|
490
|
+
return c.copyBufferToBuffer(
|
|
491
|
+
s,
|
|
480
492
|
0,
|
|
481
493
|
this._renderStagingParticleBuffer,
|
|
482
494
|
0,
|
|
483
|
-
|
|
484
|
-
),
|
|
485
|
-
|
|
495
|
+
o
|
|
496
|
+
), c.copyBufferToBuffer(
|
|
497
|
+
n,
|
|
486
498
|
0,
|
|
487
499
|
this._renderStagingVelocityBuffer,
|
|
488
500
|
0,
|
|
489
|
-
|
|
490
|
-
), this.device.queue.submit([
|
|
501
|
+
a
|
|
502
|
+
), this.device.queue.submit([c.finish()]), await Promise.all([
|
|
491
503
|
(async () => {
|
|
492
|
-
await this._renderStagingParticleBuffer.mapAsync(GPUMapMode.READ, 0,
|
|
493
|
-
const l = new Float32Array(this._renderStagingParticleBuffer.getMappedRange(0,
|
|
504
|
+
await this._renderStagingParticleBuffer.mapAsync(GPUMapMode.READ, 0, o);
|
|
505
|
+
const l = new Float32Array(this._renderStagingParticleBuffer.getMappedRange(0, o));
|
|
494
506
|
e.set(l), this._renderStagingParticleBuffer.unmap();
|
|
495
507
|
})(),
|
|
496
508
|
(async () => {
|
|
497
|
-
await this._renderStagingVelocityBuffer.mapAsync(GPUMapMode.READ, 0,
|
|
498
|
-
const l = new Float32Array(this._renderStagingVelocityBuffer.getMappedRange(0,
|
|
509
|
+
await this._renderStagingVelocityBuffer.mapAsync(GPUMapMode.READ, 0, a);
|
|
510
|
+
const l = new Float32Array(this._renderStagingVelocityBuffer.getMappedRange(0, a));
|
|
499
511
|
i.set(l), this._renderStagingVelocityBuffer.unmap();
|
|
500
512
|
})()
|
|
501
513
|
]), this._renderStagingInUse = !1, {
|
|
@@ -503,22 +515,71 @@ class q {
|
|
|
503
515
|
particleVelocities: i,
|
|
504
516
|
shouldUpdate: !0
|
|
505
517
|
};
|
|
506
|
-
} catch (
|
|
507
|
-
return this._renderStagingInUse = !1, console.error("Error in rendering readback:",
|
|
518
|
+
} catch (o) {
|
|
519
|
+
return this._renderStagingInUse = !1, console.error("Error in rendering readback:", o), { shouldUpdate: !1 };
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Non-blocking readback for CPU-side particle scripting.
|
|
524
|
+
* Uses dedicated staging buffers that never contend with cleanup or rendering readback.
|
|
525
|
+
* Copies GPU data into caller-provided Float32Arrays.
|
|
526
|
+
* @param {number} activeParticles
|
|
527
|
+
* @param {Float32Array} outParticleData
|
|
528
|
+
* @param {Float32Array} outVelocities
|
|
529
|
+
* @param {GPUBuffer} instanceBuffer
|
|
530
|
+
* @param {GPUBuffer} velocityBuffer
|
|
531
|
+
* @returns {Promise<{shouldUpdate: boolean}>}
|
|
532
|
+
*/
|
|
533
|
+
async readbackForScript(t, e, i, s, n) {
|
|
534
|
+
if (t <= 0)
|
|
535
|
+
return { shouldUpdate: !1 };
|
|
536
|
+
if (this._scriptStagingInUse)
|
|
537
|
+
return { shouldUpdate: !1 };
|
|
538
|
+
try {
|
|
539
|
+
this._scriptStagingInUse = !0;
|
|
540
|
+
const o = t * 8 * 4, a = t * 4 * 4, c = this.device.createCommandEncoder({
|
|
541
|
+
label: "ScriptReadbackEncoder"
|
|
542
|
+
});
|
|
543
|
+
return c.copyBufferToBuffer(
|
|
544
|
+
s,
|
|
545
|
+
0,
|
|
546
|
+
this._scriptStagingParticleBuffer,
|
|
547
|
+
0,
|
|
548
|
+
o
|
|
549
|
+
), c.copyBufferToBuffer(
|
|
550
|
+
n,
|
|
551
|
+
0,
|
|
552
|
+
this._scriptStagingVelocityBuffer,
|
|
553
|
+
0,
|
|
554
|
+
a
|
|
555
|
+
), this.device.queue.submit([c.finish()]), await Promise.all([
|
|
556
|
+
(async () => {
|
|
557
|
+
await this._scriptStagingParticleBuffer.mapAsync(GPUMapMode.READ, 0, o);
|
|
558
|
+
const l = new Float32Array(this._scriptStagingParticleBuffer.getMappedRange(0, o));
|
|
559
|
+
e.set(l), this._scriptStagingParticleBuffer.unmap();
|
|
560
|
+
})(),
|
|
561
|
+
(async () => {
|
|
562
|
+
await this._scriptStagingVelocityBuffer.mapAsync(GPUMapMode.READ, 0, a);
|
|
563
|
+
const l = new Float32Array(this._scriptStagingVelocityBuffer.getMappedRange(0, a));
|
|
564
|
+
i.set(l), this._scriptStagingVelocityBuffer.unmap();
|
|
565
|
+
})()
|
|
566
|
+
]), this._scriptStagingInUse = !1, { shouldUpdate: !0 };
|
|
567
|
+
} catch (o) {
|
|
568
|
+
return this._scriptStagingInUse = !1, console.error("Error in script readback:", o), { shouldUpdate: !1 };
|
|
508
569
|
}
|
|
509
570
|
}
|
|
510
571
|
/**
|
|
511
572
|
* Destroy all GPU buffers owned by this physics instance.
|
|
512
573
|
*/
|
|
513
574
|
destroy() {
|
|
514
|
-
this.physicsUniformBuffer.destroy(), this._particleDataStagingBuffer.destroy(), this._velocityStagingBuffer.destroy(), this._renderStagingParticleBuffer.destroy(), this._renderStagingVelocityBuffer.destroy();
|
|
575
|
+
this.physicsUniformBuffer.destroy(), this._particleDataStagingBuffer.destroy(), this._velocityStagingBuffer.destroy(), this._renderStagingParticleBuffer.destroy(), this._renderStagingVelocityBuffer.destroy(), this._scriptStagingParticleBuffer.destroy(), this._scriptStagingVelocityBuffer.destroy();
|
|
515
576
|
}
|
|
516
577
|
setSoftBoundary(t) {
|
|
517
578
|
const e = this.physicsSettings;
|
|
518
579
|
t.enabled !== void 0 && (e.softBoundaryEnabled = t.enabled), t.strength !== void 0 && (e.softBoundaryStrength = t.strength), t.falloff !== void 0 && (e.softBoundaryFalloff = t.falloff);
|
|
519
580
|
}
|
|
520
581
|
}
|
|
521
|
-
class
|
|
582
|
+
class ds {
|
|
522
583
|
constructor(t) {
|
|
523
584
|
this.device = t, this.defaultTexture = null, this.createDefaultTexture();
|
|
524
585
|
}
|
|
@@ -557,315 +618,583 @@ class $ {
|
|
|
557
618
|
t && t.label !== "defaultParticleTexture" && t.destroy();
|
|
558
619
|
}
|
|
559
620
|
}
|
|
560
|
-
|
|
561
|
-
|
|
621
|
+
const yi = Object.freeze({
|
|
622
|
+
sin: Math.sin,
|
|
623
|
+
cos: Math.cos,
|
|
624
|
+
abs: Math.abs,
|
|
625
|
+
floor: Math.floor,
|
|
626
|
+
ceil: Math.ceil,
|
|
627
|
+
round: Math.round,
|
|
628
|
+
min: Math.min,
|
|
629
|
+
max: Math.max,
|
|
630
|
+
sqrt: Math.sqrt,
|
|
631
|
+
pow: Math.pow,
|
|
632
|
+
random: Math.random,
|
|
633
|
+
PI: Math.PI,
|
|
634
|
+
TAU: Math.PI * 2,
|
|
635
|
+
clamp(r, t, e) {
|
|
636
|
+
return r < t ? t : r > e ? e : r;
|
|
637
|
+
},
|
|
638
|
+
lerp(r, t, e) {
|
|
639
|
+
return r + (t - r) * e;
|
|
640
|
+
},
|
|
641
|
+
smoothstep(r, t, e) {
|
|
642
|
+
const i = yi.clamp((e - r) / (t - r), 0, 1);
|
|
643
|
+
return i * i * (3 - 2 * i);
|
|
644
|
+
}
|
|
645
|
+
}), Ze = /* @__PURE__ */ new Set([
|
|
646
|
+
"particleSize",
|
|
647
|
+
"particleSpeed",
|
|
648
|
+
"particleColor",
|
|
649
|
+
"startColor",
|
|
650
|
+
"endColor",
|
|
651
|
+
"opacity",
|
|
652
|
+
"emissionRate",
|
|
653
|
+
"gravityStrength",
|
|
654
|
+
"dampingStrength",
|
|
655
|
+
"attractorStrength",
|
|
656
|
+
"attractorPosition",
|
|
657
|
+
"pulseAmplitude",
|
|
658
|
+
"pulseFrequency",
|
|
659
|
+
"bloomIntensity"
|
|
660
|
+
]);
|
|
661
|
+
class fs {
|
|
662
|
+
constructor(t) {
|
|
663
|
+
this._collection = t, this._pd = null, this._vd = null, this._pi = 0, this._vi = 0;
|
|
664
|
+
}
|
|
665
|
+
_bind(t, e, i) {
|
|
666
|
+
return this._pd = t, this._vd = e, this._pi = i * 8, this._vi = i * 4, this;
|
|
667
|
+
}
|
|
668
|
+
// Position
|
|
669
|
+
get x() {
|
|
670
|
+
return this._pd[this._pi];
|
|
671
|
+
}
|
|
672
|
+
set x(t) {
|
|
673
|
+
this._pd[this._pi] = t, this._collection._dirty = !0;
|
|
674
|
+
}
|
|
675
|
+
get y() {
|
|
676
|
+
return this._pd[this._pi + 1];
|
|
677
|
+
}
|
|
678
|
+
set y(t) {
|
|
679
|
+
this._pd[this._pi + 1] = t, this._collection._dirty = !0;
|
|
680
|
+
}
|
|
681
|
+
get z() {
|
|
682
|
+
return this._pd[this._pi + 2];
|
|
683
|
+
}
|
|
684
|
+
set z(t) {
|
|
685
|
+
this._pd[this._pi + 2] = t, this._collection._dirty = !0;
|
|
686
|
+
}
|
|
687
|
+
// Color
|
|
688
|
+
get r() {
|
|
689
|
+
return this._pd[this._pi + 3];
|
|
690
|
+
}
|
|
691
|
+
set r(t) {
|
|
692
|
+
this._pd[this._pi + 3] = t, this._collection._dirty = !0;
|
|
693
|
+
}
|
|
694
|
+
get g() {
|
|
695
|
+
return this._pd[this._pi + 4];
|
|
696
|
+
}
|
|
697
|
+
set g(t) {
|
|
698
|
+
this._pd[this._pi + 4] = t, this._collection._dirty = !0;
|
|
699
|
+
}
|
|
700
|
+
get b() {
|
|
701
|
+
return this._pd[this._pi + 5];
|
|
702
|
+
}
|
|
703
|
+
set b(t) {
|
|
704
|
+
this._pd[this._pi + 5] = t, this._collection._dirty = !0;
|
|
705
|
+
}
|
|
706
|
+
// Age / Lifetime
|
|
707
|
+
get age() {
|
|
708
|
+
return this._pd[this._pi + 6];
|
|
709
|
+
}
|
|
710
|
+
set age(t) {
|
|
711
|
+
this._pd[this._pi + 6] = t, this._collection._dirty = !0;
|
|
712
|
+
}
|
|
713
|
+
get lifetime() {
|
|
714
|
+
return this._pd[this._pi + 7];
|
|
715
|
+
}
|
|
716
|
+
set lifetime(t) {
|
|
717
|
+
this._pd[this._pi + 7] = t, this._collection._dirty = !0;
|
|
718
|
+
}
|
|
719
|
+
// Velocity
|
|
720
|
+
get vx() {
|
|
721
|
+
return this._vd[this._vi];
|
|
722
|
+
}
|
|
723
|
+
set vx(t) {
|
|
724
|
+
this._vd[this._vi] = t, this._collection._dirty = !0;
|
|
725
|
+
}
|
|
726
|
+
get vy() {
|
|
727
|
+
return this._vd[this._vi + 1];
|
|
728
|
+
}
|
|
729
|
+
set vy(t) {
|
|
730
|
+
this._vd[this._vi + 1] = t, this._collection._dirty = !0;
|
|
731
|
+
}
|
|
732
|
+
get vz() {
|
|
733
|
+
return this._vd[this._vi + 2];
|
|
734
|
+
}
|
|
735
|
+
set vz(t) {
|
|
736
|
+
this._vd[this._vi + 2] = t, this._collection._dirty = !0;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
class ps {
|
|
740
|
+
constructor() {
|
|
741
|
+
this._proxy = new fs(this), this._pd = null, this._vd = null, this.count = 0, this._dirty = !1;
|
|
742
|
+
}
|
|
743
|
+
_bind(t, e, i) {
|
|
744
|
+
this._pd = t, this._vd = e, this.count = i, this._dirty = !1;
|
|
745
|
+
}
|
|
746
|
+
get(t) {
|
|
747
|
+
return t < 0 || t >= this.count ? null : this._proxy._bind(this._pd, this._vd, t);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
const hs = 1e6;
|
|
751
|
+
function ms(r) {
|
|
752
|
+
let t = 0;
|
|
753
|
+
return r.replace(
|
|
754
|
+
/\b(for|while)\s*\([^)]*\)\s*\{/g,
|
|
755
|
+
(e) => {
|
|
756
|
+
const i = `__lc${t++}`;
|
|
757
|
+
return `${e} if(++${i}>${hs})throw new Error("Loop limit exceeded");`;
|
|
758
|
+
}
|
|
759
|
+
).replace(
|
|
760
|
+
/\b(for|while)\s*\([^)]*\)\s*\{/g,
|
|
761
|
+
// already handled above
|
|
762
|
+
(e) => e
|
|
763
|
+
).replace(
|
|
764
|
+
// Prepend counter declarations at the top
|
|
765
|
+
/^/,
|
|
766
|
+
() => {
|
|
767
|
+
let e = "";
|
|
768
|
+
for (let i = 0; i < t; i++)
|
|
769
|
+
e += `let __lc${i}=0;`;
|
|
770
|
+
return e;
|
|
771
|
+
}
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
const vt = /* @__PURE__ */ new Map();
|
|
775
|
+
for (const r of Ze)
|
|
776
|
+
vt.set(r.toLowerCase(), r);
|
|
777
|
+
function ys(r) {
|
|
778
|
+
const t = { value: !1 }, e = /* @__PURE__ */ new Set();
|
|
779
|
+
return new Proxy(r, {
|
|
780
|
+
get(s, n) {
|
|
781
|
+
if (n === "__dirty") return t.value;
|
|
782
|
+
if (n === "__resetDirty") return () => {
|
|
783
|
+
t.value = !1;
|
|
784
|
+
};
|
|
785
|
+
if (typeof n != "string") return;
|
|
786
|
+
if (Ze.has(n)) return s[n];
|
|
787
|
+
const o = vt.get(n.toLowerCase());
|
|
788
|
+
if (o)
|
|
789
|
+
return e.has(n) || (e.add(n), console.warn(`[ParticleScript] config.${n} → did you mean config.${o}?`)), s[o];
|
|
790
|
+
},
|
|
791
|
+
set(s, n, o) {
|
|
792
|
+
if (typeof n != "string") return !0;
|
|
793
|
+
let a = n;
|
|
794
|
+
if (!Ze.has(a)) {
|
|
795
|
+
const c = vt.get(a.toLowerCase());
|
|
796
|
+
if (c)
|
|
797
|
+
e.has(n) || (e.add(n), console.warn(`[ParticleScript] config.${n} → did you mean config.${c}?`)), a = c;
|
|
798
|
+
else
|
|
799
|
+
return !0;
|
|
800
|
+
}
|
|
801
|
+
return s[a] = o, t.value = !0, !0;
|
|
802
|
+
}
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
class si {
|
|
806
|
+
/**
|
|
807
|
+
* @param {string} source - User script source code
|
|
808
|
+
* @param {object} config - ParticleSystem config (will be proxied)
|
|
809
|
+
* @param {number} maxParticles - Max particle count for pre-allocation
|
|
810
|
+
*/
|
|
811
|
+
constructor(t, e, i) {
|
|
812
|
+
this._particles = new ps(), this._configProxy = ys(e), this._configSnapshot = null, this._fn = null, this._error = !1, this.compile(t);
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Compile script source into a sandboxed function.
|
|
816
|
+
*/
|
|
817
|
+
compile(t) {
|
|
818
|
+
if (this._fn = null, this._error = !1, !(!t || typeof t != "string"))
|
|
819
|
+
try {
|
|
820
|
+
const i = `
|
|
821
|
+
return function(__deltaTime, __time, __currentFrame, __totalFrames, __particles, __config, __math) {
|
|
822
|
+
var window = void 0, document = void 0, globalThis = void 0;
|
|
823
|
+
var Function = void 0, eval = void 0, fetch = void 0;
|
|
824
|
+
var importScripts = void 0, XMLHttpRequest = void 0, WebSocket = void 0;
|
|
825
|
+
var deltaTime = __deltaTime, time = __time;
|
|
826
|
+
var currentFrame = __currentFrame, totalFrames = __totalFrames;
|
|
827
|
+
var particles = __particles, config = __config, math = __math;
|
|
828
|
+
${ms(t)}
|
|
829
|
+
};`, s = new Function(i);
|
|
830
|
+
this._fn = s();
|
|
831
|
+
} catch (e) {
|
|
832
|
+
console.warn("[ParticleScript] Compilation error:", e.message), this._fn = null, this._error = !0;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
/**
|
|
836
|
+
* Execute the script for one frame.
|
|
837
|
+
* @param {number} deltaTime
|
|
838
|
+
* @param {number} time - seconds since system start
|
|
839
|
+
* @param {number} frame - frame counter
|
|
840
|
+
* @param {number} totalFrames - estimated total frames
|
|
841
|
+
* @param {Float32Array} particleData - read/write
|
|
842
|
+
* @param {Float32Array} velocityData - read/write
|
|
843
|
+
* @param {number} count - active particle count
|
|
844
|
+
* @returns {boolean} true if config was modified
|
|
845
|
+
*/
|
|
846
|
+
execute(t, e, i, s, n, o, a) {
|
|
847
|
+
if (!this._fn || this._error) return { configDirty: !1, particlesDirty: !1 };
|
|
848
|
+
this._particles._bind(n, o, a), this._configProxy.__resetDirty();
|
|
849
|
+
try {
|
|
850
|
+
this._fn(t, e, i, s, this._particles, this._configProxy, yi);
|
|
851
|
+
} catch (c) {
|
|
852
|
+
console.warn("[ParticleScript] Runtime error:", c.message);
|
|
853
|
+
}
|
|
854
|
+
return {
|
|
855
|
+
configDirty: this._configProxy.__dirty,
|
|
856
|
+
particlesDirty: this._particles._dirty
|
|
857
|
+
};
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* Deep-clone the scriptable config properties for later restoration.
|
|
861
|
+
*/
|
|
862
|
+
snapshotConfig(t) {
|
|
863
|
+
const e = {};
|
|
864
|
+
for (const i of Ze) {
|
|
865
|
+
const s = t[i];
|
|
866
|
+
s !== void 0 && (e[i] = Array.isArray(s) ? [...s] : s);
|
|
867
|
+
}
|
|
868
|
+
this._configSnapshot = e;
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* Restore config properties from the snapshot.
|
|
872
|
+
*/
|
|
873
|
+
restoreConfig(t) {
|
|
874
|
+
if (this._configSnapshot) {
|
|
875
|
+
for (const e of Ze)
|
|
876
|
+
if (e in this._configSnapshot) {
|
|
877
|
+
const i = this._configSnapshot[e];
|
|
878
|
+
t[e] = Array.isArray(i) ? [...i] : i;
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
/**
|
|
883
|
+
* Cleanup.
|
|
884
|
+
*/
|
|
885
|
+
destroy() {
|
|
886
|
+
this._fn = null, this._particles = null, this._configProxy = null, this._configSnapshot = null;
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
async function gi(r) {
|
|
890
|
+
const t = new DataView(r);
|
|
562
891
|
if (t.getUint32(0, !0) !== 1179937895)
|
|
563
892
|
throw new Error("Invalid GLB file: incorrect magic number");
|
|
564
893
|
const i = t.getUint32(4, !0);
|
|
565
894
|
if (i !== 2)
|
|
566
895
|
throw new Error(`Unsupported GLB version: ${i} (only version 2 is supported)`);
|
|
567
|
-
const
|
|
568
|
-
let
|
|
569
|
-
for (;
|
|
570
|
-
const
|
|
571
|
-
if (
|
|
572
|
-
const
|
|
573
|
-
|
|
574
|
-
} else
|
|
575
|
-
|
|
896
|
+
const s = t.getUint32(8, !0);
|
|
897
|
+
let n = 12, o = null, a = null;
|
|
898
|
+
for (; n < s; ) {
|
|
899
|
+
const P = t.getUint32(n, !0), _ = t.getUint32(n + 4, !0), T = r.slice(n + 8, n + 8 + P);
|
|
900
|
+
if (_ === 1313821514) {
|
|
901
|
+
const N = new TextDecoder("utf-8").decode(T);
|
|
902
|
+
o = JSON.parse(N);
|
|
903
|
+
} else _ === 5130562 && (a = T);
|
|
904
|
+
n += 8 + P;
|
|
576
905
|
}
|
|
577
|
-
if (!
|
|
906
|
+
if (!o)
|
|
578
907
|
throw new Error("GLB file missing JSON chunk");
|
|
579
|
-
if (!
|
|
908
|
+
if (!o.meshes || o.meshes.length === 0)
|
|
580
909
|
throw new Error("GLB file contains no meshes");
|
|
581
|
-
const l =
|
|
910
|
+
const l = o.meshes[0].primitives[0];
|
|
582
911
|
if (!l)
|
|
583
912
|
throw new Error("First mesh has no primitives");
|
|
584
913
|
const u = l.attributes.POSITION;
|
|
585
914
|
if (u === void 0)
|
|
586
915
|
throw new Error("Mesh primitive missing POSITION attribute");
|
|
587
|
-
const
|
|
588
|
-
let
|
|
916
|
+
const f = gt(o, a, u, 3, 5126);
|
|
917
|
+
let h;
|
|
589
918
|
if (l.attributes.NORMAL !== void 0)
|
|
590
|
-
|
|
919
|
+
h = gt(o, a, l.attributes.NORMAL, 3, 5126);
|
|
591
920
|
else {
|
|
592
|
-
const
|
|
593
|
-
if (
|
|
921
|
+
const P = l.indices;
|
|
922
|
+
if (P === void 0)
|
|
594
923
|
throw new Error("Cannot generate normals without indices");
|
|
595
|
-
const
|
|
596
|
-
|
|
924
|
+
const _ = ri(o, a, P);
|
|
925
|
+
h = gs(f, _);
|
|
597
926
|
}
|
|
598
|
-
const
|
|
599
|
-
if (
|
|
927
|
+
const m = l.indices;
|
|
928
|
+
if (m === void 0)
|
|
600
929
|
throw new Error("Mesh primitive missing indices");
|
|
601
|
-
const
|
|
602
|
-
let
|
|
603
|
-
l.attributes.TEXCOORD_0 !== void 0 && (
|
|
604
|
-
let
|
|
605
|
-
if (
|
|
606
|
-
const
|
|
607
|
-
|
|
608
|
-
}
|
|
609
|
-
let
|
|
610
|
-
if (
|
|
930
|
+
const S = ri(o, a, m), R = f.length / 3, D = S.length;
|
|
931
|
+
let C = null;
|
|
932
|
+
l.attributes.TEXCOORD_0 !== void 0 && (C = gt(o, a, l.attributes.TEXCOORD_0, 2, 5126));
|
|
933
|
+
let B = !1;
|
|
934
|
+
if (o.materials && o.materials.length > 0) {
|
|
935
|
+
const P = o.materials[0];
|
|
936
|
+
P.pbrMetallicRoughness && P.pbrMetallicRoughness.baseColorTexture !== void 0 && (B = !0);
|
|
937
|
+
}
|
|
938
|
+
let A = null;
|
|
939
|
+
if (o.skins && o.skins.length > 0)
|
|
611
940
|
try {
|
|
612
|
-
|
|
613
|
-
} catch (
|
|
614
|
-
console.warn("Failed to extract animation data:",
|
|
941
|
+
A = _s(o, a, l), console.log("Animation data extracted:", A);
|
|
942
|
+
} catch (P) {
|
|
943
|
+
console.warn("Failed to extract animation data:", P);
|
|
615
944
|
}
|
|
616
945
|
return {
|
|
617
|
-
positions:
|
|
618
|
-
normals:
|
|
619
|
-
indices:
|
|
620
|
-
texCoords:
|
|
621
|
-
vertexCount:
|
|
622
|
-
indexCount:
|
|
623
|
-
animationData:
|
|
624
|
-
hasBaseColorTexture:
|
|
946
|
+
positions: f,
|
|
947
|
+
normals: h,
|
|
948
|
+
indices: S,
|
|
949
|
+
texCoords: C,
|
|
950
|
+
vertexCount: R,
|
|
951
|
+
indexCount: D,
|
|
952
|
+
animationData: A,
|
|
953
|
+
hasBaseColorTexture: B
|
|
625
954
|
};
|
|
626
955
|
}
|
|
627
|
-
function
|
|
628
|
-
const
|
|
956
|
+
function gt(r, t, e, i, s) {
|
|
957
|
+
const n = r.accessors[e], a = {
|
|
629
958
|
SCALAR: 1,
|
|
630
959
|
VEC2: 2,
|
|
631
960
|
VEC3: 3,
|
|
632
961
|
VEC4: 4
|
|
633
|
-
}[
|
|
634
|
-
if (
|
|
635
|
-
throw new Error(`Attribute accessor type mismatch: expected ${i} components, got ${
|
|
636
|
-
if (
|
|
637
|
-
throw new Error(`Attribute component type mismatch: expected ${
|
|
638
|
-
const l = (
|
|
639
|
-
for (let
|
|
640
|
-
|
|
641
|
-
return
|
|
962
|
+
}[n.type];
|
|
963
|
+
if (a !== i)
|
|
964
|
+
throw new Error(`Attribute accessor type mismatch: expected ${i} components, got ${a}`);
|
|
965
|
+
if (n.componentType !== s)
|
|
966
|
+
throw new Error(`Attribute component type mismatch: expected ${s}, got ${n.componentType}`);
|
|
967
|
+
const l = (r.bufferViews[n.bufferView].byteOffset || 0) + (n.byteOffset || 0), u = n.count, f = new DataView(t, l, u * i * 4), h = new Float32Array(u * i);
|
|
968
|
+
for (let m = 0; m < u * i; m++)
|
|
969
|
+
h[m] = f.getFloat32(m * 4, !0);
|
|
970
|
+
return h;
|
|
642
971
|
}
|
|
643
|
-
function
|
|
644
|
-
const i =
|
|
972
|
+
function ri(r, t, e) {
|
|
973
|
+
const i = r.accessors[e];
|
|
645
974
|
if (i.type !== "SCALAR")
|
|
646
975
|
throw new Error(`Indices accessor must be SCALAR, got ${i.type}`);
|
|
647
|
-
const
|
|
976
|
+
const n = (r.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), o = i.count;
|
|
648
977
|
if (i.componentType === 5123) {
|
|
649
|
-
const
|
|
650
|
-
for (let l = 0; l <
|
|
651
|
-
|
|
652
|
-
return
|
|
978
|
+
const a = new DataView(t, n, o * 2), c = new Uint16Array(o);
|
|
979
|
+
for (let l = 0; l < o; l++)
|
|
980
|
+
c[l] = a.getUint16(l * 2, !0);
|
|
981
|
+
return c;
|
|
653
982
|
} else if (i.componentType === 5125) {
|
|
654
|
-
const
|
|
655
|
-
for (let l = 0; l <
|
|
656
|
-
|
|
657
|
-
return
|
|
983
|
+
const a = new DataView(t, n, o * 4), c = new Uint32Array(o);
|
|
984
|
+
for (let l = 0; l < o; l++)
|
|
985
|
+
c[l] = a.getUint32(l * 4, !0);
|
|
986
|
+
return c;
|
|
658
987
|
} else
|
|
659
988
|
throw new Error(`Unsupported index component type: ${i.componentType}`);
|
|
660
989
|
}
|
|
661
|
-
function
|
|
662
|
-
const e = new Float32Array(
|
|
990
|
+
function gs(r, t) {
|
|
991
|
+
const e = new Float32Array(r.length);
|
|
663
992
|
for (let i = 0; i < t.length; i += 3) {
|
|
664
|
-
const
|
|
665
|
-
u[1] *
|
|
666
|
-
u[2] *
|
|
667
|
-
u[0] *
|
|
668
|
-
],
|
|
669
|
-
|
|
993
|
+
const s = t[i] * 3, n = t[i + 1] * 3, o = t[i + 2] * 3, a = [r[s], r[s + 1], r[s + 2]], c = [r[n], r[n + 1], r[n + 2]], l = [r[o], r[o + 1], r[o + 2]], u = [c[0] - a[0], c[1] - a[1], c[2] - a[2]], f = [l[0] - a[0], l[1] - a[1], l[2] - a[2]], h = [
|
|
994
|
+
u[1] * f[2] - u[2] * f[1],
|
|
995
|
+
u[2] * f[0] - u[0] * f[2],
|
|
996
|
+
u[0] * f[1] - u[1] * f[0]
|
|
997
|
+
], m = Math.sqrt(h[0] * h[0] + h[1] * h[1] + h[2] * h[2]);
|
|
998
|
+
m > 0 && (h[0] /= m, h[1] /= m, h[2] /= m), e[s] = e[n] = e[o] = h[0], e[s + 1] = e[n + 1] = e[o + 1] = h[1], e[s + 2] = e[n + 2] = e[o + 2] = h[2];
|
|
670
999
|
}
|
|
671
1000
|
return e;
|
|
672
1001
|
}
|
|
673
|
-
function
|
|
674
|
-
const i =
|
|
1002
|
+
function bs(r, t, e) {
|
|
1003
|
+
const i = r.accessors[e];
|
|
675
1004
|
if (i.type !== "VEC4")
|
|
676
1005
|
throw new Error(`JOINTS_0 must be VEC4, got ${i.type}`);
|
|
677
|
-
const
|
|
1006
|
+
const n = (r.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), o = i.count;
|
|
678
1007
|
if (i.componentType === 5121) {
|
|
679
|
-
const
|
|
680
|
-
for (let l = 0; l <
|
|
681
|
-
|
|
682
|
-
return
|
|
1008
|
+
const a = new DataView(t, n, o * 4), c = new Uint8Array(o * 4);
|
|
1009
|
+
for (let l = 0; l < o * 4; l++)
|
|
1010
|
+
c[l] = a.getUint8(l);
|
|
1011
|
+
return c;
|
|
683
1012
|
} else if (i.componentType === 5123) {
|
|
684
|
-
const
|
|
685
|
-
for (let l = 0; l <
|
|
686
|
-
|
|
687
|
-
return
|
|
1013
|
+
const a = new DataView(t, n, o * 8), c = new Uint8Array(o * 4);
|
|
1014
|
+
for (let l = 0; l < o * 4; l++)
|
|
1015
|
+
c[l] = a.getUint16(l * 2, !0);
|
|
1016
|
+
return c;
|
|
688
1017
|
} else
|
|
689
1018
|
throw new Error(`Unsupported JOINTS_0 component type: ${i.componentType}`);
|
|
690
1019
|
}
|
|
691
|
-
function
|
|
692
|
-
const i =
|
|
1020
|
+
function Ss(r, t, e) {
|
|
1021
|
+
const i = r.accessors[e];
|
|
693
1022
|
if (i.type !== "VEC4")
|
|
694
1023
|
throw new Error(`WEIGHTS_0 must be VEC4, got ${i.type}`);
|
|
695
|
-
const
|
|
1024
|
+
const n = (r.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), o = i.count;
|
|
696
1025
|
if (i.componentType === 5126) {
|
|
697
|
-
const
|
|
698
|
-
for (let l = 0; l <
|
|
699
|
-
|
|
700
|
-
return
|
|
1026
|
+
const a = new DataView(t, n, o * 16), c = new Float32Array(o * 4);
|
|
1027
|
+
for (let l = 0; l < o * 4; l++)
|
|
1028
|
+
c[l] = a.getFloat32(l * 4, !0);
|
|
1029
|
+
return c;
|
|
701
1030
|
} else if (i.componentType === 5121) {
|
|
702
|
-
const
|
|
703
|
-
for (let l = 0; l <
|
|
704
|
-
|
|
705
|
-
return
|
|
1031
|
+
const a = new DataView(t, n, o * 4), c = new Float32Array(o * 4);
|
|
1032
|
+
for (let l = 0; l < o * 4; l++)
|
|
1033
|
+
c[l] = a.getUint8(l) / 255;
|
|
1034
|
+
return c;
|
|
706
1035
|
} else
|
|
707
1036
|
throw new Error(`Unsupported WEIGHTS_0 component type: ${i.componentType}`);
|
|
708
1037
|
}
|
|
709
|
-
function
|
|
710
|
-
const i =
|
|
1038
|
+
function xs(r, t, e) {
|
|
1039
|
+
const i = r.accessors[e];
|
|
711
1040
|
if (i.type !== "MAT4")
|
|
712
1041
|
throw new Error(`Expected MAT4, got ${i.type}`);
|
|
713
1042
|
if (i.componentType !== 5126)
|
|
714
1043
|
throw new Error(`Expected FLOAT component type for MAT4, got ${i.componentType}`);
|
|
715
|
-
const
|
|
716
|
-
for (let l = 0; l <
|
|
717
|
-
|
|
718
|
-
return
|
|
1044
|
+
const n = (r.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), o = i.count, a = new DataView(t, n, o * 64), c = new Float32Array(o * 16);
|
|
1045
|
+
for (let l = 0; l < o * 16; l++)
|
|
1046
|
+
c[l] = a.getFloat32(l * 4, !0);
|
|
1047
|
+
return c;
|
|
719
1048
|
}
|
|
720
|
-
function
|
|
721
|
-
const i =
|
|
1049
|
+
function vs(r, t, e) {
|
|
1050
|
+
const i = r.accessors[e];
|
|
722
1051
|
if (i.type !== "SCALAR")
|
|
723
1052
|
throw new Error(`Expected SCALAR, got ${i.type}`);
|
|
724
1053
|
if (i.componentType !== 5126)
|
|
725
1054
|
throw new Error(`Expected FLOAT component type for SCALAR, got ${i.componentType}`);
|
|
726
|
-
const
|
|
727
|
-
for (let l = 0; l <
|
|
728
|
-
|
|
729
|
-
return
|
|
1055
|
+
const n = (r.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), o = i.count, a = new DataView(t, n, o * 4), c = new Float32Array(o);
|
|
1056
|
+
for (let l = 0; l < o; l++)
|
|
1057
|
+
c[l] = a.getFloat32(l * 4, !0);
|
|
1058
|
+
return c;
|
|
730
1059
|
}
|
|
731
|
-
function
|
|
732
|
-
const i =
|
|
733
|
-
if (!
|
|
1060
|
+
function Ps(r, t, e) {
|
|
1061
|
+
const i = r.accessors[e], n = { VEC3: 3, VEC4: 4 }[i.type];
|
|
1062
|
+
if (!n)
|
|
734
1063
|
throw new Error(`Expected VEC3 or VEC4, got ${i.type}`);
|
|
735
1064
|
if (i.componentType !== 5126)
|
|
736
1065
|
throw new Error(`Expected FLOAT component type, got ${i.componentType}`);
|
|
737
|
-
const
|
|
738
|
-
for (let
|
|
739
|
-
u[
|
|
1066
|
+
const a = (r.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), c = i.count, l = new DataView(t, a, c * n * 4), u = new Float32Array(c * n);
|
|
1067
|
+
for (let f = 0; f < c * n; f++)
|
|
1068
|
+
u[f] = l.getFloat32(f * 4, !0);
|
|
740
1069
|
return u;
|
|
741
1070
|
}
|
|
742
|
-
function
|
|
743
|
-
const i =
|
|
744
|
-
if (!
|
|
1071
|
+
function _s(r, t, e) {
|
|
1072
|
+
const i = r.skins[0], s = i.joints, n = xs(r, t, i.inverseBindMatrices), o = e.attributes.JOINTS_0 !== void 0 ? bs(r, t, e.attributes.JOINTS_0) : null, a = e.attributes.WEIGHTS_0 !== void 0 ? Ss(r, t, e.attributes.WEIGHTS_0) : null;
|
|
1073
|
+
if (!o || !a)
|
|
745
1074
|
throw new Error("Mesh missing JOINTS_0 or WEIGHTS_0 attributes");
|
|
746
|
-
const
|
|
1075
|
+
const c = r.nodes.map((u) => ({
|
|
747
1076
|
translation: u.translation || [0, 0, 0],
|
|
748
1077
|
rotation: u.rotation || [0, 0, 0, 1],
|
|
749
1078
|
scale: u.scale || [1, 1, 1],
|
|
750
1079
|
children: u.children || [],
|
|
751
1080
|
name: u.name || ""
|
|
752
1081
|
})), l = [];
|
|
753
|
-
if (
|
|
754
|
-
for (const u of
|
|
755
|
-
const
|
|
756
|
-
let
|
|
757
|
-
for (const
|
|
758
|
-
const
|
|
759
|
-
|
|
760
|
-
targetNode:
|
|
761
|
-
targetPath:
|
|
762
|
-
interpolation:
|
|
763
|
-
timestamps:
|
|
764
|
-
values:
|
|
1082
|
+
if (r.animations && r.animations.length > 0)
|
|
1083
|
+
for (const u of r.animations) {
|
|
1084
|
+
const f = [];
|
|
1085
|
+
let h = 0;
|
|
1086
|
+
for (const m of u.channels) {
|
|
1087
|
+
const S = u.samplers[m.sampler], R = vs(r, t, S.input), D = Ps(r, t, S.output), C = R[R.length - 1];
|
|
1088
|
+
C > h && (h = C), f.push({
|
|
1089
|
+
targetNode: m.target.node,
|
|
1090
|
+
targetPath: m.target.path,
|
|
1091
|
+
interpolation: S.interpolation || "LINEAR",
|
|
1092
|
+
timestamps: R,
|
|
1093
|
+
values: D
|
|
765
1094
|
});
|
|
766
1095
|
}
|
|
767
1096
|
l.push({
|
|
768
1097
|
name: u.name || `Animation ${l.length}`,
|
|
769
|
-
duration:
|
|
770
|
-
channels:
|
|
1098
|
+
duration: h,
|
|
1099
|
+
channels: f
|
|
771
1100
|
});
|
|
772
1101
|
}
|
|
773
1102
|
return {
|
|
774
|
-
joints:
|
|
775
|
-
inverseBindMatrices:
|
|
776
|
-
jointIndices:
|
|
777
|
-
jointWeights:
|
|
778
|
-
nodes:
|
|
1103
|
+
joints: s,
|
|
1104
|
+
inverseBindMatrices: n,
|
|
1105
|
+
jointIndices: o,
|
|
1106
|
+
jointWeights: a,
|
|
1107
|
+
nodes: c,
|
|
779
1108
|
animations: l
|
|
780
1109
|
};
|
|
781
1110
|
}
|
|
782
|
-
async function
|
|
783
|
-
const t = new DataView(
|
|
1111
|
+
async function ws(r) {
|
|
1112
|
+
const t = new DataView(r);
|
|
784
1113
|
if (t.getUint32(0, !0) !== 1179937895)
|
|
785
1114
|
throw new Error("Invalid GLB file: incorrect magic number");
|
|
786
1115
|
const i = t.getUint32(4, !0);
|
|
787
1116
|
if (i !== 2)
|
|
788
1117
|
throw new Error(`Unsupported GLB version: ${i}`);
|
|
789
|
-
const
|
|
790
|
-
let
|
|
791
|
-
for (;
|
|
792
|
-
const
|
|
793
|
-
if (
|
|
794
|
-
const
|
|
795
|
-
|
|
796
|
-
} else
|
|
797
|
-
|
|
1118
|
+
const s = t.getUint32(8, !0);
|
|
1119
|
+
let n = 12, o = null, a = null;
|
|
1120
|
+
for (; n < s; ) {
|
|
1121
|
+
const A = t.getUint32(n, !0), P = t.getUint32(n + 4, !0), _ = r.slice(n + 8, n + 8 + A);
|
|
1122
|
+
if (P === 1313821514) {
|
|
1123
|
+
const L = new TextDecoder("utf-8").decode(_);
|
|
1124
|
+
o = JSON.parse(L);
|
|
1125
|
+
} else P === 5130562 && (a = _);
|
|
1126
|
+
n += 8 + A;
|
|
798
1127
|
}
|
|
799
|
-
if (!
|
|
1128
|
+
if (!o)
|
|
800
1129
|
throw new Error("GLB file missing JSON chunk");
|
|
801
|
-
if (!
|
|
1130
|
+
if (!o.materials || o.materials.length === 0)
|
|
802
1131
|
return null;
|
|
803
|
-
const
|
|
804
|
-
if (!
|
|
1132
|
+
const c = o.materials[0];
|
|
1133
|
+
if (!c.pbrMetallicRoughness || c.pbrMetallicRoughness.baseColorTexture === void 0)
|
|
805
1134
|
return null;
|
|
806
|
-
const l =
|
|
807
|
-
if (!
|
|
1135
|
+
const l = c.pbrMetallicRoughness.baseColorTexture.index;
|
|
1136
|
+
if (!o.textures || !o.textures[l])
|
|
808
1137
|
return null;
|
|
809
|
-
const
|
|
810
|
-
if (
|
|
1138
|
+
const f = o.textures[l].source;
|
|
1139
|
+
if (f === void 0 || !o.images || !o.images[f])
|
|
811
1140
|
return null;
|
|
812
|
-
const
|
|
813
|
-
if (
|
|
1141
|
+
const h = o.images[f], m = h.mimeType || "image/png";
|
|
1142
|
+
if (h.bufferView === void 0)
|
|
814
1143
|
return null;
|
|
815
|
-
if (!
|
|
1144
|
+
if (!a)
|
|
816
1145
|
throw new Error("GLB file missing BIN chunk (required for embedded textures)");
|
|
817
|
-
const
|
|
818
|
-
return { imageBlob: new Blob([
|
|
1146
|
+
const S = o.bufferViews[h.bufferView], R = S.byteOffset || 0, D = S.byteLength, C = a.slice(R, R + D);
|
|
1147
|
+
return { imageBlob: new Blob([C], { type: m }), mimeType: m };
|
|
819
1148
|
}
|
|
820
|
-
const
|
|
1149
|
+
const ni = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
821
1150
|
__proto__: null,
|
|
822
|
-
extractGLBTexture:
|
|
823
|
-
parseGLB:
|
|
1151
|
+
extractGLBTexture: ws,
|
|
1152
|
+
parseGLB: gi
|
|
824
1153
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
825
|
-
function
|
|
1154
|
+
function ai(r, t, e) {
|
|
826
1155
|
return [
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
1156
|
+
r[0] + (t[0] - r[0]) * e,
|
|
1157
|
+
r[1] + (t[1] - r[1]) * e,
|
|
1158
|
+
r[2] + (t[2] - r[2]) * e
|
|
830
1159
|
];
|
|
831
1160
|
}
|
|
832
|
-
function
|
|
833
|
-
let i =
|
|
834
|
-
if (i < 0 && (i = -i,
|
|
1161
|
+
function oi(r, t, e) {
|
|
1162
|
+
let i = r[0] * t[0] + r[1] * t[1] + r[2] * t[2] + r[3] * t[3], s = t;
|
|
1163
|
+
if (i < 0 && (i = -i, s = [-t[0], -t[1], -t[2], -t[3]]), i > 0.9995) {
|
|
835
1164
|
const l = [
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
1165
|
+
r[0] + (s[0] - r[0]) * e,
|
|
1166
|
+
r[1] + (s[1] - r[1]) * e,
|
|
1167
|
+
r[2] + (s[2] - r[2]) * e,
|
|
1168
|
+
r[3] + (s[3] - r[3]) * e
|
|
840
1169
|
];
|
|
841
|
-
return
|
|
1170
|
+
return Bs(l);
|
|
842
1171
|
}
|
|
843
|
-
const
|
|
1172
|
+
const n = Math.acos(i), o = Math.sin(n), a = Math.sin((1 - e) * n) / o, c = Math.sin(e * n) / o;
|
|
844
1173
|
return [
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
1174
|
+
r[0] * a + s[0] * c,
|
|
1175
|
+
r[1] * a + s[1] * c,
|
|
1176
|
+
r[2] * a + s[2] * c,
|
|
1177
|
+
r[3] * a + s[3] * c
|
|
849
1178
|
];
|
|
850
1179
|
}
|
|
851
|
-
function
|
|
852
|
-
const t = Math.sqrt(
|
|
853
|
-
return t > 1e-4 ? [
|
|
1180
|
+
function Bs(r) {
|
|
1181
|
+
const t = Math.sqrt(r[0] * r[0] + r[1] * r[1] + r[2] * r[2] + r[3] * r[3]);
|
|
1182
|
+
return t > 1e-4 ? [r[0] / t, r[1] / t, r[2] / t, r[3] / t] : [0, 0, 0, 1];
|
|
854
1183
|
}
|
|
855
|
-
function
|
|
856
|
-
const t =
|
|
1184
|
+
function Rs(r) {
|
|
1185
|
+
const t = r[0], e = r[1], i = r[2], s = r[3], n = t + t, o = e + e, a = i + i, c = t * n, l = t * o, u = t * a, f = e * o, h = e * a, m = i * a, S = s * n, R = s * o, D = s * a;
|
|
857
1186
|
return new Float32Array([
|
|
858
|
-
1 - (
|
|
859
|
-
l +
|
|
860
|
-
u -
|
|
1187
|
+
1 - (f + m),
|
|
1188
|
+
l + D,
|
|
1189
|
+
u - R,
|
|
861
1190
|
0,
|
|
862
|
-
l -
|
|
863
|
-
1 - (
|
|
864
|
-
|
|
1191
|
+
l - D,
|
|
1192
|
+
1 - (c + m),
|
|
1193
|
+
h + S,
|
|
865
1194
|
0,
|
|
866
|
-
u +
|
|
867
|
-
|
|
868
|
-
1 - (
|
|
1195
|
+
u + R,
|
|
1196
|
+
h - S,
|
|
1197
|
+
1 - (c + f),
|
|
869
1198
|
0,
|
|
870
1199
|
0,
|
|
871
1200
|
0,
|
|
@@ -873,8 +1202,8 @@ function se(c) {
|
|
|
873
1202
|
1
|
|
874
1203
|
]);
|
|
875
1204
|
}
|
|
876
|
-
function
|
|
877
|
-
const i =
|
|
1205
|
+
function Ms(r, t, e) {
|
|
1206
|
+
const i = Rs(t);
|
|
878
1207
|
return new Float32Array([
|
|
879
1208
|
i[0] * e[0],
|
|
880
1209
|
i[1] * e[0],
|
|
@@ -888,20 +1217,20 @@ function re(c, t, e) {
|
|
|
888
1217
|
i[9] * e[2],
|
|
889
1218
|
i[10] * e[2],
|
|
890
1219
|
0,
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
1220
|
+
r[0],
|
|
1221
|
+
r[1],
|
|
1222
|
+
r[2],
|
|
894
1223
|
1
|
|
895
1224
|
]);
|
|
896
1225
|
}
|
|
897
|
-
function
|
|
1226
|
+
function li(r, t) {
|
|
898
1227
|
const e = new Float32Array(16);
|
|
899
1228
|
for (let i = 0; i < 4; i++)
|
|
900
|
-
for (let
|
|
901
|
-
e[i * 4 +
|
|
1229
|
+
for (let s = 0; s < 4; s++)
|
|
1230
|
+
e[i * 4 + s] = r[0 + s] * t[i * 4 + 0] + r[4 + s] * t[i * 4 + 1] + r[8 + s] * t[i * 4 + 2] + r[12 + s] * t[i * 4 + 3];
|
|
902
1231
|
return e;
|
|
903
1232
|
}
|
|
904
|
-
class
|
|
1233
|
+
class Ts {
|
|
905
1234
|
constructor(t) {
|
|
906
1235
|
this.joints = t.joints, this.inverseBindMatrices = t.inverseBindMatrices, this.jointWeights = t.jointWeights, this.jointIndices = t.jointIndices, this.nodes = t.nodes, this.animations = t.animations, this.restPositions = null, this.restNormals = null, this.currentAnimIndex = 0, this.currentTime = 0, this.playing = !0, this.speed = 1, this.loop = !0, this.jointLocalTransforms = new Array(this.nodes.length), this.jointGlobalTransforms = new Array(this.nodes.length), this.jointFinalMatrices = new Array(this.joints.length);
|
|
907
1236
|
for (let e = 0; e < this.nodes.length; e++)
|
|
@@ -925,33 +1254,33 @@ class ne {
|
|
|
925
1254
|
async initGPUSkinning(t, e, i) {
|
|
926
1255
|
try {
|
|
927
1256
|
this._gpuDevice = t, this._gpuOutputBuffer = e;
|
|
928
|
-
const
|
|
929
|
-
for (let l = 0; l <
|
|
930
|
-
const u = l * 8,
|
|
931
|
-
|
|
1257
|
+
const s = this.restPositions.length / 3, n = new Float32Array(s * 8);
|
|
1258
|
+
for (let l = 0; l < s; l++) {
|
|
1259
|
+
const u = l * 8, f = l * 3, h = l * 2;
|
|
1260
|
+
n[u] = this.restPositions[f], n[u + 1] = this.restPositions[f + 1], n[u + 2] = this.restPositions[f + 2], n[u + 3] = this.restNormals[f], n[u + 4] = this.restNormals[f + 1], n[u + 5] = this.restNormals[f + 2], n[u + 6] = i ? i[h] : 0, n[u + 7] = i ? i[h + 1] : 0;
|
|
932
1261
|
}
|
|
933
1262
|
this._gpuRestDataBuffer = t.createBuffer({
|
|
934
|
-
size:
|
|
1263
|
+
size: n.byteLength,
|
|
935
1264
|
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
|
936
1265
|
label: "skinning_restData"
|
|
937
|
-
}), t.queue.writeBuffer(this._gpuRestDataBuffer, 0,
|
|
1266
|
+
}), t.queue.writeBuffer(this._gpuRestDataBuffer, 0, n), this._gpuJointWeightsBuffer = t.createBuffer({
|
|
938
1267
|
size: this.jointWeights.byteLength,
|
|
939
1268
|
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
|
940
1269
|
label: "skinning_jointWeights"
|
|
941
1270
|
}), t.queue.writeBuffer(this._gpuJointWeightsBuffer, 0, this.jointWeights);
|
|
942
|
-
const
|
|
1271
|
+
const o = new Uint32Array(this.jointIndices.length);
|
|
943
1272
|
for (let l = 0; l < this.jointIndices.length; l++)
|
|
944
|
-
|
|
1273
|
+
o[l] = this.jointIndices[l];
|
|
945
1274
|
this._gpuJointIndicesBuffer = t.createBuffer({
|
|
946
|
-
size:
|
|
1275
|
+
size: o.byteLength,
|
|
947
1276
|
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
|
948
1277
|
label: "skinning_jointIndices"
|
|
949
|
-
}), t.queue.writeBuffer(this._gpuJointIndicesBuffer, 0,
|
|
1278
|
+
}), t.queue.writeBuffer(this._gpuJointIndicesBuffer, 0, o), this._gpuJointMatricesBuffer = t.createBuffer({
|
|
950
1279
|
size: this.joints.length * 16 * 4,
|
|
951
1280
|
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
|
952
1281
|
label: "skinning_jointMatrices"
|
|
953
1282
|
}), this._gpuJointMatricesData = new Float32Array(this.joints.length * 16);
|
|
954
|
-
const { skinningComputeShader:
|
|
1283
|
+
const { skinningComputeShader: a } = await Promise.resolve().then(() => _i), c = t.createBindGroupLayout({
|
|
955
1284
|
entries: [
|
|
956
1285
|
{ binding: 0, visibility: GPUShaderStage.COMPUTE, buffer: { type: "read-only-storage" } },
|
|
957
1286
|
{ binding: 1, visibility: GPUShaderStage.COMPUTE, buffer: { type: "read-only-storage" } },
|
|
@@ -961,13 +1290,13 @@ class ne {
|
|
|
961
1290
|
]
|
|
962
1291
|
});
|
|
963
1292
|
this._gpuSkinningPipeline = t.createComputePipeline({
|
|
964
|
-
layout: t.createPipelineLayout({ bindGroupLayouts: [
|
|
1293
|
+
layout: t.createPipelineLayout({ bindGroupLayouts: [c] }),
|
|
965
1294
|
compute: {
|
|
966
|
-
module: t.createShaderModule({ code:
|
|
1295
|
+
module: t.createShaderModule({ code: a }),
|
|
967
1296
|
entryPoint: "main"
|
|
968
1297
|
}
|
|
969
1298
|
}), this._gpuSkinningBindGroup = t.createBindGroup({
|
|
970
|
-
layout:
|
|
1299
|
+
layout: c,
|
|
971
1300
|
entries: [
|
|
972
1301
|
{ binding: 0, resource: { buffer: this._gpuRestDataBuffer } },
|
|
973
1302
|
{ binding: 1, resource: { buffer: this._gpuJointWeightsBuffer } },
|
|
@@ -975,9 +1304,9 @@ class ne {
|
|
|
975
1304
|
{ binding: 3, resource: { buffer: this._gpuJointMatricesBuffer } },
|
|
976
1305
|
{ binding: 4, resource: { buffer: this._gpuOutputBuffer } }
|
|
977
1306
|
]
|
|
978
|
-
}), this._gpuVertexCount =
|
|
979
|
-
} catch (
|
|
980
|
-
console.warn("GPU skinning init failed, using CPU fallback:",
|
|
1307
|
+
}), this._gpuVertexCount = s, this._gpuSkinningReady = !0, console.log(`GPU skinning initialized: ${s} vertices, ${this.joints.length} joints`);
|
|
1308
|
+
} catch (s) {
|
|
1309
|
+
console.warn("GPU skinning init failed, using CPU fallback:", s), this._gpuSkinningReady = !1;
|
|
981
1310
|
}
|
|
982
1311
|
}
|
|
983
1312
|
/**
|
|
@@ -1027,48 +1356,48 @@ class ne {
|
|
|
1027
1356
|
* Build topological order for node traversal (parent before child).
|
|
1028
1357
|
*/
|
|
1029
1358
|
_buildTopologicalOrder() {
|
|
1030
|
-
const t = /* @__PURE__ */ new Set(), e = [], i = (
|
|
1031
|
-
if (t.has(
|
|
1032
|
-
t.add(
|
|
1033
|
-
const
|
|
1359
|
+
const t = /* @__PURE__ */ new Set(), e = [], i = (n) => {
|
|
1360
|
+
if (t.has(n)) return;
|
|
1361
|
+
t.add(n);
|
|
1362
|
+
const o = this.nodes[n];
|
|
1363
|
+
for (const a of o.children)
|
|
1364
|
+
i(a);
|
|
1365
|
+
e.push(n);
|
|
1366
|
+
}, s = /* @__PURE__ */ new Set();
|
|
1367
|
+
for (const n of this.nodes)
|
|
1034
1368
|
for (const o of n.children)
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
for (const r of this.nodes)
|
|
1039
|
-
for (const n of r.children)
|
|
1040
|
-
a.add(n);
|
|
1041
|
-
for (let r = 0; r < this.nodes.length; r++)
|
|
1042
|
-
a.has(r) || i(r);
|
|
1369
|
+
s.add(o);
|
|
1370
|
+
for (let n = 0; n < this.nodes.length; n++)
|
|
1371
|
+
s.has(n) || i(n);
|
|
1043
1372
|
this.topologicalOrder = e.reverse();
|
|
1044
1373
|
}
|
|
1045
1374
|
/**
|
|
1046
1375
|
* Sample a single channel at the given time.
|
|
1047
1376
|
*/
|
|
1048
1377
|
_sampleChannel(t, e) {
|
|
1049
|
-
const { timestamps: i, values:
|
|
1378
|
+
const { timestamps: i, values: s, interpolation: n, targetPath: o } = t;
|
|
1050
1379
|
if (e <= i[0])
|
|
1051
|
-
return this._extractValue(
|
|
1380
|
+
return this._extractValue(s, 0, o);
|
|
1052
1381
|
if (e >= i[i.length - 1])
|
|
1053
|
-
return this._extractValue(
|
|
1054
|
-
let
|
|
1055
|
-
for (;
|
|
1056
|
-
const
|
|
1057
|
-
i[
|
|
1382
|
+
return this._extractValue(s, i.length - 1, o);
|
|
1383
|
+
let a = 0, c = i.length - 1;
|
|
1384
|
+
for (; c - a > 1; ) {
|
|
1385
|
+
const S = Math.floor((a + c) / 2);
|
|
1386
|
+
i[S] <= e ? a = S : c = S;
|
|
1058
1387
|
}
|
|
1059
|
-
const l = i[
|
|
1060
|
-
return
|
|
1388
|
+
const l = i[a], u = i[c], f = (e - l) / (u - l), h = this._extractValue(s, a, o), m = this._extractValue(s, c, o);
|
|
1389
|
+
return n === "STEP" ? h : o === "rotation" ? oi(h, m, f) : ai(h, m, f);
|
|
1061
1390
|
}
|
|
1062
1391
|
/**
|
|
1063
1392
|
* Extract value from values array at the given index.
|
|
1064
1393
|
*/
|
|
1065
1394
|
_extractValue(t, e, i) {
|
|
1066
1395
|
if (i === "rotation") {
|
|
1067
|
-
const
|
|
1068
|
-
return [t[
|
|
1396
|
+
const s = e * 4;
|
|
1397
|
+
return [t[s], t[s + 1], t[s + 2], t[s + 3]];
|
|
1069
1398
|
} else {
|
|
1070
|
-
const
|
|
1071
|
-
return [t[
|
|
1399
|
+
const s = e * 3;
|
|
1400
|
+
return [t[s], t[s + 1], t[s + 2]];
|
|
1072
1401
|
}
|
|
1073
1402
|
}
|
|
1074
1403
|
/**
|
|
@@ -1077,14 +1406,14 @@ class ne {
|
|
|
1077
1406
|
_computeLocalTransforms(t) {
|
|
1078
1407
|
const e = this.animations[this.currentAnimIndex];
|
|
1079
1408
|
for (let i = 0; i < this.nodes.length; i++) {
|
|
1080
|
-
const
|
|
1081
|
-
let
|
|
1082
|
-
for (const
|
|
1083
|
-
if (
|
|
1084
|
-
const l = this._sampleChannel(
|
|
1085
|
-
|
|
1409
|
+
const s = this.nodes[i];
|
|
1410
|
+
let n = s.translation, o = s.rotation, a = s.scale;
|
|
1411
|
+
for (const c of e.channels)
|
|
1412
|
+
if (c.targetNode === i) {
|
|
1413
|
+
const l = this._sampleChannel(c, t);
|
|
1414
|
+
c.targetPath === "translation" ? n = l : c.targetPath === "rotation" ? o = l : c.targetPath === "scale" && (a = l);
|
|
1086
1415
|
}
|
|
1087
|
-
this.jointLocalTransforms[i] =
|
|
1416
|
+
this.jointLocalTransforms[i] = Ms(n, o, a);
|
|
1088
1417
|
}
|
|
1089
1418
|
}
|
|
1090
1419
|
/**
|
|
@@ -1094,12 +1423,12 @@ class ne {
|
|
|
1094
1423
|
const t = new Array(this.nodes.length).fill(-1);
|
|
1095
1424
|
for (let e = 0; e < this.nodes.length; e++) {
|
|
1096
1425
|
const i = this.nodes[e];
|
|
1097
|
-
for (const
|
|
1098
|
-
t[
|
|
1426
|
+
for (const s of i.children)
|
|
1427
|
+
t[s] = e;
|
|
1099
1428
|
}
|
|
1100
1429
|
for (const e of this.topologicalOrder) {
|
|
1101
1430
|
const i = t[e];
|
|
1102
|
-
i === -1 ? this.jointGlobalTransforms[e] = this.jointLocalTransforms[e] : this.jointGlobalTransforms[e] =
|
|
1431
|
+
i === -1 ? this.jointGlobalTransforms[e] = this.jointLocalTransforms[e] : this.jointGlobalTransforms[e] = li(
|
|
1103
1432
|
this.jointGlobalTransforms[i],
|
|
1104
1433
|
this.jointLocalTransforms[e]
|
|
1105
1434
|
);
|
|
@@ -1110,8 +1439,8 @@ class ne {
|
|
|
1110
1439
|
*/
|
|
1111
1440
|
_computeFinalMatrices() {
|
|
1112
1441
|
for (let t = 0; t < this.joints.length; t++) {
|
|
1113
|
-
const e = this.joints[t], i = this.jointGlobalTransforms[e],
|
|
1114
|
-
this.jointFinalMatrices[t] =
|
|
1442
|
+
const e = this.joints[t], i = this.jointGlobalTransforms[e], s = t * 16, n = this.inverseBindMatrices.slice(s, s + 16);
|
|
1443
|
+
this.jointFinalMatrices[t] = li(i, n);
|
|
1115
1444
|
}
|
|
1116
1445
|
}
|
|
1117
1446
|
/**
|
|
@@ -1119,30 +1448,30 @@ class ne {
|
|
|
1119
1448
|
* Inlined math, no temporary array allocations.
|
|
1120
1449
|
*/
|
|
1121
1450
|
_applySkinning() {
|
|
1122
|
-
const t = this.restPositions.length / 3, e = this.restPositions, i = this.restNormals,
|
|
1451
|
+
const t = this.restPositions.length / 3, e = this.restPositions, i = this.restNormals, s = this.skinnedPositions, n = this.skinnedNormals, o = this.jointWeights, a = this.jointIndices, c = this.jointFinalMatrices;
|
|
1123
1452
|
for (let l = 0; l < t; l++) {
|
|
1124
|
-
const u = l * 3,
|
|
1125
|
-
let
|
|
1126
|
-
for (let
|
|
1127
|
-
const
|
|
1128
|
-
if (
|
|
1129
|
-
const
|
|
1130
|
-
|
|
1453
|
+
const u = l * 3, f = l * 4, h = e[u], m = e[u + 1], S = e[u + 2], R = i[u], D = i[u + 1], C = i[u + 2];
|
|
1454
|
+
let B = 0, A = 0, P = 0, _ = 0, T = 0, L = 0;
|
|
1455
|
+
for (let k = 0; k < 4; k++) {
|
|
1456
|
+
const X = o[f + k];
|
|
1457
|
+
if (X === 0) continue;
|
|
1458
|
+
const z = c[a[f + k]];
|
|
1459
|
+
B += (z[0] * h + z[4] * m + z[8] * S + z[12]) * X, A += (z[1] * h + z[5] * m + z[9] * S + z[13]) * X, P += (z[2] * h + z[6] * m + z[10] * S + z[14]) * X, _ += (z[0] * R + z[4] * D + z[8] * C) * X, T += (z[1] * R + z[5] * D + z[9] * C) * X, L += (z[2] * R + z[6] * D + z[10] * C) * X;
|
|
1131
1460
|
}
|
|
1132
|
-
const
|
|
1133
|
-
|
|
1461
|
+
const N = Math.sqrt(_ * _ + T * T + L * L);
|
|
1462
|
+
N > 1e-4 && (n[u] = _ / N, n[u + 1] = T / N, n[u + 2] = L / N), s[u] = B, s[u + 1] = A, s[u + 2] = P;
|
|
1134
1463
|
}
|
|
1135
1464
|
}
|
|
1136
1465
|
}
|
|
1137
|
-
function
|
|
1138
|
-
const t = atob(
|
|
1466
|
+
function ci(r) {
|
|
1467
|
+
const t = atob(r), e = new Uint8Array(t.length);
|
|
1139
1468
|
for (let i = 0; i < t.length; i++)
|
|
1140
1469
|
e[i] = t.charCodeAt(i);
|
|
1141
1470
|
return e.buffer;
|
|
1142
1471
|
}
|
|
1143
|
-
class
|
|
1472
|
+
class bt {
|
|
1144
1473
|
constructor(t, e) {
|
|
1145
|
-
this.device = t, this.config = e, this.MAX_PARTICLES = e.maxParticles || 1e4, this.particleCount = e.particleCount || 100, this.activeParticles = 0, this.emitting = !1, this.currentEmissionTime = 0, this.particleData = new Float32Array(this.MAX_PARTICLES * 8), this.particleVelocities = new Float32Array(this.MAX_PARTICLES * 4), this.instanceBuffer = t.createBuffer({
|
|
1474
|
+
this.device = t, this.config = e, this.MAX_PARTICLES = e.maxParticles || 1e4, this.particleCount = e.particleCount || 100, this.activeParticles = 0, this.emitting = !1, this.currentEmissionTime = 0, this.destroyed = !1, this.particleData = new Float32Array(this.MAX_PARTICLES * 8), this.particleVelocities = new Float32Array(this.MAX_PARTICLES * 4), this.instanceBuffer = t.createBuffer({
|
|
1146
1475
|
size: this.MAX_PARTICLES * 8 * 4,
|
|
1147
1476
|
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
|
|
1148
1477
|
label: "particleInstanceBuffer"
|
|
@@ -1157,8 +1486,8 @@ class C {
|
|
|
1157
1486
|
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC,
|
|
1158
1487
|
label: "particleTrailBuffer"
|
|
1159
1488
|
}), this._trailResetData = new Float32Array(this.MAX_PARTICLES * 4), this.appearanceUniformBuffer = t.createBuffer({
|
|
1160
|
-
size:
|
|
1161
|
-
// appearance uniforms + pulse + GLB rotation + system offset + sim rotation
|
|
1489
|
+
size: 208,
|
|
1490
|
+
// appearance uniforms + pulse + GLB rotation + system offset + sim rotation + noise distortion
|
|
1162
1491
|
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
|
|
1163
1492
|
label: "appearanceUniformBuffer"
|
|
1164
1493
|
}), this.bloomIntensityBuffer = t.createBuffer({
|
|
@@ -1166,7 +1495,7 @@ class C {
|
|
|
1166
1495
|
// intensity (f32) + padding
|
|
1167
1496
|
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
|
|
1168
1497
|
label: "systemBloomIntensityBuffer"
|
|
1169
|
-
}), e.overrideXVelocity === void 0 && (e.overrideXVelocity = !1), e.overrideYVelocity === void 0 && (e.overrideYVelocity = !1), e.overrideZVelocity === void 0 && (e.overrideZVelocity = !1), e.xVelocity === void 0 && (e.xVelocity = 0), e.yVelocity === void 0 && (e.yVelocity = 0), e.zVelocity === void 0 && (e.zVelocity = 0), e.textureEnabled === void 0 && (e.textureEnabled = !1), e.glbModelEnabled === void 0 && (e.glbModelEnabled = !1), e.textureType === void 0 && (e.textureType = "image"), e.glbFileName === void 0 && (e.glbFileName = null), e.animationIndex === void 0 && (e.animationIndex = 0), e.animationSpeed === void 0 && (e.animationSpeed = 1), e.animationLoop === void 0 && (e.animationLoop = !0), e.useGlbTexture === void 0 && (e.useGlbTexture = !1), e.glbHasTexture === void 0 && (e.glbHasTexture = !1), e.particleShape === void 0 && (e.particleShape = "square"), e.particleShapeRotation
|
|
1498
|
+
}), e.overrideXVelocity === void 0 && (e.overrideXVelocity = !1), e.overrideYVelocity === void 0 && (e.overrideYVelocity = !1), e.overrideZVelocity === void 0 && (e.overrideZVelocity = !1), e.xVelocity === void 0 && (e.xVelocity = 0), e.yVelocity === void 0 && (e.yVelocity = 0), e.zVelocity === void 0 && (e.zVelocity = 0), e.textureEnabled === void 0 && (e.textureEnabled = !1), e.glbModelEnabled === void 0 && (e.glbModelEnabled = !1), e.textureType === void 0 && (e.textureType = "image"), e.glbFileName === void 0 && (e.glbFileName = null), e.animationIndex === void 0 && (e.animationIndex = 0), e.animationSpeed === void 0 && (e.animationSpeed = 1), e.animationLoop === void 0 && (e.animationLoop = !0), e.useGlbTexture === void 0 && (e.useGlbTexture = !1), e.glbHasTexture === void 0 && (e.glbHasTexture = !1), e.particleShape === void 0 && (e.particleShape = "square"), e.particleShapeRotation !== void 0 && (e.rotation = (e.rotation || 0) + e.particleShapeRotation, delete e.particleShapeRotation), e.particleShapeRotationX === void 0 && (e.particleShapeRotationX = 0), e.particleShapeRotationY === void 0 && (e.particleShapeRotationY = 0), e.particleShapeRotationZ === void 0 && (e.particleShapeRotationZ = 0), e.particleColor === void 0 && (e.particleColor = [1, 1, 1]), e.startColor === void 0 && (e.startColor = [1, 0, 0]), e.endColor === void 0 && (e.endColor = [0, 0, 1]), e.fadeEnabled === void 0 && (e.fadeEnabled = !0), e.colorTransitionEnabled === void 0 && (e.colorTransitionEnabled = !1), e.randomColorEnabled === void 0 && (e.randomColorEnabled = !1), e.randomColors === void 0 && (e.randomColors = []), e.particleSize === void 0 && (e.particleSize = 0.1), e.particleSpeed === void 0 && (e.particleSpeed = 1), e.opacity === void 0 && (e.opacity = 1), e.aspectRatio === void 0 && (e.aspectRatio = 1), e.rotation === void 0 && (e.rotation = 0), e.rotationMode === void 0 && (e.rotationMode = "fixed"), e.minRotation === void 0 && (e.minRotation = 0), e.maxRotation === void 0 && (e.maxRotation = 90), e.randomSize === void 0 && (e.randomSize = !1), e.minSize === void 0 && (e.minSize = 0.05), e.maxSize === void 0 && (e.maxSize = 0.15), e.randomSpeed === void 0 && (e.randomSpeed = !1), e.minSpeed === void 0 && (e.minSpeed = 0.1), e.maxSpeed === void 0 && (e.maxSpeed = 1), e.fadeSizeEnabled === void 0 && (e.fadeSizeEnabled = !1), e.increaseSizeEnabled === void 0 && (e.increaseSizeEnabled = !1), e.sizeLifetimeSpeed === void 0 && (e.sizeLifetimeSpeed = 1), e.bloomEnabled === void 0 && (e.bloomEnabled = !0), e.bloomIntensity === void 0 && (e.bloomIntensity = 1), e.bloomColor === void 0 && (e.bloomColor = [1, 1, 1]), e.gravityEnabled === void 0 && (e.gravityEnabled = !1), e.gravityStrength === void 0 && (e.gravityStrength = 2), e.dampingEnabled === void 0 && (e.dampingEnabled = !1), e.dampingStrength === void 0 && (e.dampingStrength = 1), e.attractorEnabled === void 0 && (e.attractorEnabled = !1), e.attractorStrength === void 0 && (e.attractorStrength = 1), e.attractorPosition === void 0 && (e.attractorPosition = [0, 0, 0]), e.burstMode === void 0 && (e.burstMode = !1), e.emissionShape === void 0 && (e.emissionShape = "cube"), e.lifetime === void 0 && (e.lifetime = 5), e.emissionRate === void 0 && (e.emissionRate = 10), e.emissionDuration === void 0 && (e.emissionDuration = 10), e.emissionDurationInfinite === void 0 && (e.emissionDurationInfinite = !1), e.emissionDuration > 300 && (e.emissionDurationInfinite = !0, e.emissionDuration = 10), e.outerLength === void 0 && (e.outerLength = e.cubeLength ?? 2), e.innerLength === void 0 && (e.innerLength = 0), e.outerRadius === void 0 && (e.outerRadius = 2), e.innerRadius === void 0 && (e.innerRadius = 0), e.squareSize === void 0 && (e.squareSize = 2), e.squareInnerSize === void 0 && (e.squareInnerSize = 0), e.circleInnerRadius === void 0 && (e.circleInnerRadius = 0), e.circleOuterRadius === void 0 && (e.circleOuterRadius = 2), e.circleVelocityDirection === void 0 && (e.circleVelocityDirection = "outward"), e.cylinderInnerRadius === void 0 && (e.cylinderInnerRadius = 0), e.cylinderOuterRadius === void 0 && (e.cylinderOuterRadius = 2), e.cylinderHeight === void 0 && (e.cylinderHeight = 4), e.cylinderVelocityDirection === void 0 && (e.cylinderVelocityDirection = "outward"), e.planeWidth === void 0 && (e.planeWidth = 2), e.planeDepth === void 0 && (e.planeDepth = 2), e.coneOuterRadius === void 0 && (e.coneOuterRadius = 2), e.coneInnerRadius === void 0 && (e.coneInnerRadius = 0), e.coneHeight === void 0 && (e.coneHeight = 4), e.torusMajorRadius === void 0 && (e.torusMajorRadius = 2), e.torusMinorRadius === void 0 && (e.torusMinorRadius = 0.5), e.lineLength === void 0 && (e.lineLength = 4), e.hemisphereOuterRadius === void 0 && (e.hemisphereOuterRadius = 2), e.hemisphereInnerRadius === void 0 && (e.hemisphereInnerRadius = 0), e.discRadius === void 0 && (e.discRadius = 2), e.annulusInnerRadius === void 0 && (e.annulusInnerRadius = 1), e.annulusOuterRadius === void 0 && (e.annulusOuterRadius = 2), e.capsuleRadius === void 0 && (e.capsuleRadius = 0.5), e.capsuleHeight === void 0 && (e.capsuleHeight = 4), e.arcStartAngle === void 0 && (e.arcStartAngle = 0), e.arcEndAngle === void 0 && (e.arcEndAngle = 180), e.arcInnerRadius === void 0 && (e.arcInnerRadius = 0), e.arcOuterRadius === void 0 && (e.arcOuterRadius = 2), e.spiralTurns === void 0 && (e.spiralTurns = 3), e.spiralRadiusStart === void 0 && (e.spiralRadiusStart = 0.5), e.spiralRadiusEnd === void 0 && (e.spiralRadiusEnd = 2), e.spiralHeight === void 0 && (e.spiralHeight = 4), e.frustumRadiusNear === void 0 && (e.frustumRadiusNear = 0.5), e.frustumRadiusFar === void 0 && (e.frustumRadiusFar = 2), e.frustumHeight === void 0 && (e.frustumHeight = 4), e.cubeSurfaceSize === void 0 && (e.cubeSurfaceSize = 2), e.sphereSurfaceRadius === void 0 && (e.sphereSurfaceRadius = 2), e.boxFrameSize === void 0 && (e.boxFrameSize = 2), e.polygonSides === void 0 && (e.polygonSides = 6), e.polygonRadius === void 0 && (e.polygonRadius = 2), e.emissionRotationX === void 0 && (e.emissionRotationX = 0), e.emissionRotationY === void 0 && (e.emissionRotationY = 0), e.emissionRotationZ === void 0 && (e.emissionRotationZ = 0), e.emissionPositionX === void 0 && (e.emissionPositionX = e.emissionTranslationX ?? 0), e.emissionPositionY === void 0 && (e.emissionPositionY = e.emissionTranslationY ?? 0), e.emissionPositionZ === void 0 && (e.emissionPositionZ = e.emissionTranslationZ ?? 0), e.pulseEnabled === void 0 && (e.pulseEnabled = !1), e.pulseAmplitude === void 0 && (e.pulseAmplitude = 0.5), e.pulseFrequency === void 0 && (e.pulseFrequency = 1), e.pulsePhaseRandom === void 0 && (e.pulsePhaseRandom = 0), e.pulseOpacity === void 0 && (e.pulseOpacity = !1), e.confinementEnabled === void 0 && (e.confinementEnabled = !1), e.confinementShape === void 0 && (e.confinementShape = "box"), e.confinementMode === void 0 && (e.confinementMode = "bounce"), e.confinementSpace === void 0 && (e.confinementSpace = "world"), e.confinementBoxHalfSize === void 0 && (e.confinementBoxHalfSize = [2, 2, 2]), e.confinementSphereRadius === void 0 && (e.confinementSphereRadius = 3), e.confinementRestitution === void 0 && (e.confinementRestitution = 0.8), e.confinementFriction === void 0 && (e.confinementFriction = 0.1), e.softBoundaryEnabled === void 0 && (e.softBoundaryEnabled = !1), e.softBoundaryStrength === void 0 && (e.softBoundaryStrength = 5), e.softBoundaryFalloff === void 0 && (e.softBoundaryFalloff = 0.5), e.depthWriteEnabled === void 0 && (e.depthWriteEnabled = !1), e.velocityStretchEnabled === void 0 && (e.velocityStretchEnabled = !1), e.velocityStretchFactor === void 0 && (e.velocityStretchFactor = 1), e.blendMode === void 0 && (e.blendMode = "normal"), e.noiseDistortEnabled === void 0 && (e.noiseDistortEnabled = !1), e.noiseTilingX === void 0 && (e.noiseTilingX = 3), e.noiseTilingY === void 0 && (e.noiseTilingY = 3), e.noiseSpeed === void 0 && (e.noiseSpeed = -1.5), e.noiseAmplitude === void 0 && (e.noiseAmplitude = 0.08), e.emissionTrailEnabled === void 0 && (e.emissionTrailEnabled = !1), e.emissionTrailDuration === void 0 && (e.emissionTrailDuration = 1), e.emissionTrailWidth === void 0 && (e.emissionTrailWidth = 0.3), e.emissionTrailMinDistance === void 0 && (e.emissionTrailMinDistance = 0.05), e.emissionTrailMaxPoints === void 0 && (e.emissionTrailMaxPoints = 256), e.emissionTrailSegments === void 0 && (e.emissionTrailSegments = 8), e.emissionTrailMode === void 0 && (e.emissionTrailMode = "ribbon"), e.emissionTrailShape === void 0 && (e.emissionTrailShape = "straight"), e.emissionTrailShapeAmplitude === void 0 && (e.emissionTrailShapeAmplitude = 0.1), e.emissionTrailShapeFrequency === void 0 && (e.emissionTrailShapeFrequency = 4), e.emissionTrailShapeSpeed === void 0 && (e.emissionTrailShapeSpeed = 0), e.shapeDisplay === void 0 && (e.shapeDisplay = !0), e.followSystemTranslation === void 0 && (e.followSystemTranslation = !0), e.followSystemId === void 0 && (e.followSystemId = null), this._newEmissions = [], this._emptyEmissions = [], this._pendingFollowEmissions = this._emptyEmissions, this.glbVertexBuffer = null, this.glbIndexBuffer = null, this.glbIndexCount = 0, this.glbIndexFormat = "uint16", this.glbMeshData = null, this.glbRawArrayBuffer = null, this.glbAnimator = null, this.glbAnimated = !1, this._glbInterleavedData = null, this._appearanceData = new Float32Array(52), this._bloomIntensityData = new Float32Array(16), this._simPosition = [0, 0, 0], this._simVelocity = [0, 0, 0], this._simRotMatrix = null, this._simRotX = 0, this._simRotZ = 0, this._emitSimRotY = 0, this.emitter = new cs(e), this.physics = new us(t, this.MAX_PARTICLES), this.textureManager = new ds(t), e.gravityEnabled && this.setGravity(e.gravityStrength || 0), e.dampingEnabled && this.physics.setDamping(e.dampingStrength || 0), e.attractorEnabled && e.attractorPosition && this.setAttractor(e.attractorStrength || 0, e.attractorPosition), e.confinementEnabled && this.setConfinement({
|
|
1170
1499
|
enabled: !0,
|
|
1171
1500
|
shape: e.confinementShape,
|
|
1172
1501
|
mode: e.confinementMode,
|
|
@@ -1179,26 +1508,33 @@ class C {
|
|
|
1179
1508
|
enabled: !0,
|
|
1180
1509
|
strength: e.softBoundaryStrength,
|
|
1181
1510
|
falloff: e.softBoundaryFalloff
|
|
1182
|
-
}), this.particleTexture = this.textureManager.getDefaultTexture(), this.updateBloomIntensity(), this.updateAppearanceUniform(), this.frameCount = 0, this.shouldReset = !1, this.initComputePipeline(t);
|
|
1511
|
+
}), this.particleTexture = this.textureManager.getDefaultTexture(), this.updateBloomIntensity(), this.updateAppearanceUniform(), this.frameCount = 0, this.shouldReset = !1, this._scriptParticleData = new Float32Array(this.MAX_PARTICLES * 8), this._scriptVelocityData = new Float32Array(this.MAX_PARTICLES * 4), this._scriptReadbackPending = !1, this._scriptReadbackReady = !1, this._scriptFrame = 0, this._scriptTime = 0, this._scriptConfigRestored = !1, this._particleScript = null, e.script && (this._particleScript = new si(e.script, e, this.MAX_PARTICLES)), this.initComputePipeline(t);
|
|
1183
1512
|
}
|
|
1184
1513
|
async initComputePipeline(t) {
|
|
1185
1514
|
this.computeReady = await this.physics.initComputePipeline(this.instanceBuffer, this.velocityBuffer, this.trailBuffer);
|
|
1186
1515
|
}
|
|
1516
|
+
/**
|
|
1517
|
+
* Set or clear the per-frame CPU script for this particle system.
|
|
1518
|
+
* @param {string|null} source - Script source code, or null to disable
|
|
1519
|
+
*/
|
|
1520
|
+
setScript(t) {
|
|
1521
|
+
this._particleScript && (this._particleScript.destroy(), this._particleScript = null), this._scriptReadbackPending = !1, this._scriptReadbackReady = !1, this._scriptFrame = 0, this._scriptTime = 0, this._scriptConfigRestored = !1, t ? (this.config.script = t, this._particleScript = new si(t, this.config, this.MAX_PARTICLES), this._particleScript.snapshotConfig(this.config)) : delete this.config.script;
|
|
1522
|
+
}
|
|
1187
1523
|
async setTexture(t) {
|
|
1188
|
-
this.textureManager.destroyTexture(this.particleTexture), this.particleTexture = await this.textureManager.loadTexture(t), this.config.textureEnabled = !0, this.updateAppearanceUniform(), this.updateBuffers();
|
|
1524
|
+
this.destroyed || (this.textureManager.destroyTexture(this.particleTexture), this.particleTexture = await this.textureManager.loadTexture(t), this.config.textureEnabled = !0, this.updateAppearanceUniform(), this.updateBuffers());
|
|
1189
1525
|
}
|
|
1190
1526
|
resetTexture() {
|
|
1191
|
-
this.textureManager.destroyTexture(this.particleTexture), this.particleTexture = this.textureManager.getDefaultTexture(), this.config.textureEnabled = !1, this.updateAppearanceUniform(), this.updateBuffers();
|
|
1527
|
+
this.destroyed || (this.textureManager.destroyTexture(this.particleTexture), this.particleTexture = this.textureManager.getDefaultTexture(), this.config.textureEnabled = !1, this.updateAppearanceUniform(), this.updateBuffers());
|
|
1192
1528
|
}
|
|
1193
1529
|
async setGLBModel(t) {
|
|
1194
1530
|
try {
|
|
1195
1531
|
this.glbRawArrayBuffer = t;
|
|
1196
|
-
const e = await
|
|
1532
|
+
const e = await gi(t);
|
|
1197
1533
|
this.glbMeshData = e, this.config.glbHasTexture = e.hasBaseColorTexture || !1;
|
|
1198
1534
|
const i = new Float32Array(e.vertexCount * 8);
|
|
1199
|
-
for (let
|
|
1200
|
-
const
|
|
1201
|
-
i[
|
|
1535
|
+
for (let s = 0; s < e.vertexCount; s++) {
|
|
1536
|
+
const n = s * 8, o = s * 3, a = s * 2;
|
|
1537
|
+
i[n + 0] = e.positions[o + 0], i[n + 1] = e.positions[o + 1], i[n + 2] = e.positions[o + 2], i[n + 3] = e.normals[o + 0], i[n + 4] = e.normals[o + 1], i[n + 5] = e.normals[o + 2], e.texCoords ? (i[n + 6] = e.texCoords[a + 0], i[n + 7] = e.texCoords[a + 1]) : (i[n + 6] = 0, i[n + 7] = 0);
|
|
1202
1538
|
}
|
|
1203
1539
|
if (this.glbVertexBuffer && this.glbVertexBuffer.destroy(), this.glbIndexBuffer && this.glbIndexBuffer.destroy(), this.glbVertexBuffer = this.device.createBuffer({
|
|
1204
1540
|
size: i.byteLength,
|
|
@@ -1209,11 +1545,11 @@ class C {
|
|
|
1209
1545
|
usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST,
|
|
1210
1546
|
label: "glbIndexBuffer"
|
|
1211
1547
|
}), this.device.queue.writeBuffer(this.glbIndexBuffer, 0, e.indices), this.glbIndexCount = e.indexCount, this.glbIndexFormat = e.indices instanceof Uint32Array ? "uint32" : "uint16", this.config.glbModelEnabled = !0, this.config.textureType = "glb", e.animationData) {
|
|
1212
|
-
this.glbAnimator = new
|
|
1548
|
+
this.glbAnimator = new Ts(e.animationData), this.glbAnimator.setRestPose(e.positions, e.normals), this.glbAnimated = !0, this.config.glbAnimated = !0, this.glbAnimator.loop = this.config.animationLoop, this._glbInterleavedData = new Float32Array(e.vertexCount * 8);
|
|
1213
1549
|
try {
|
|
1214
1550
|
await this.glbAnimator.initGPUSkinning(this.device, this.glbVertexBuffer, e.texCoords);
|
|
1215
|
-
} catch (
|
|
1216
|
-
console.warn("GPU skinning init failed, using CPU fallback:",
|
|
1551
|
+
} catch (s) {
|
|
1552
|
+
console.warn("GPU skinning init failed, using CPU fallback:", s);
|
|
1217
1553
|
}
|
|
1218
1554
|
console.log(`GLB animated model loaded: ${e.animationData.animations.length} animations`);
|
|
1219
1555
|
} else
|
|
@@ -1236,21 +1572,21 @@ class C {
|
|
|
1236
1572
|
*/
|
|
1237
1573
|
setSimulationTransform(t) {
|
|
1238
1574
|
if (t.position && (this._simPosition[0] = t.position[0], this._simPosition[1] = t.position[1], this._simPosition[2] = t.position[2]), t.rotation) {
|
|
1239
|
-
this._simRotX = t.rotation[0], this._simRotZ = t.rotation[1];
|
|
1240
|
-
const e = Math.cos(this._simRotX), i = Math.sin(this._simRotX),
|
|
1575
|
+
this._simRotX = t.rotation[0] || 0, this._simRotZ = t.rotation[1] || 0, this._simRotY = t.rotation[2] || 0;
|
|
1576
|
+
const e = Math.cos(this._simRotX), i = Math.sin(this._simRotX), s = Math.cos(this._simRotZ), n = Math.sin(this._simRotZ), o = Math.cos(this._simRotY), a = Math.sin(this._simRotY);
|
|
1241
1577
|
this._simRotMatrix = [
|
|
1242
|
-
|
|
1243
|
-
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
-
|
|
1248
|
-
|
|
1249
|
-
i,
|
|
1250
|
-
e
|
|
1578
|
+
o * s,
|
|
1579
|
+
-o * n * e + a * i,
|
|
1580
|
+
o * n * i + a * e,
|
|
1581
|
+
n,
|
|
1582
|
+
s * e,
|
|
1583
|
+
-s * i,
|
|
1584
|
+
-a * s,
|
|
1585
|
+
a * n * e + o * i,
|
|
1586
|
+
-a * n * i + o * e
|
|
1251
1587
|
];
|
|
1252
1588
|
} else
|
|
1253
|
-
this._simRotMatrix = null, this._simRotX = 0, this._simRotZ = 0;
|
|
1589
|
+
this._simRotMatrix = null, this._simRotX = 0, this._simRotZ = 0, this._simRotY = 0;
|
|
1254
1590
|
t.velocity && (this._simVelocity[0] = t.velocity[0], this._simVelocity[1] = t.velocity[1], this._simVelocity[2] = t.velocity[2]);
|
|
1255
1591
|
}
|
|
1256
1592
|
clearSimulationTransform() {
|
|
@@ -1261,19 +1597,20 @@ class C {
|
|
|
1261
1597
|
if (this.glbAnimator._gpuSkinningReady)
|
|
1262
1598
|
return !0;
|
|
1263
1599
|
const t = this.glbAnimator.skinnedPositions, e = this.glbAnimator.skinnedNormals, i = this.glbMeshData.texCoords;
|
|
1264
|
-
for (let
|
|
1265
|
-
const
|
|
1266
|
-
this._glbInterleavedData[
|
|
1600
|
+
for (let s = 0; s < this.glbMeshData.vertexCount; s++) {
|
|
1601
|
+
const n = s * 8, o = s * 3, a = s * 2;
|
|
1602
|
+
this._glbInterleavedData[n] = t[o], this._glbInterleavedData[n + 1] = t[o + 1], this._glbInterleavedData[n + 2] = t[o + 2], this._glbInterleavedData[n + 3] = e[o], this._glbInterleavedData[n + 4] = e[o + 1], this._glbInterleavedData[n + 5] = e[o + 2], i ? (this._glbInterleavedData[n + 6] = i[a], this._glbInterleavedData[n + 7] = i[a + 1]) : (this._glbInterleavedData[n + 6] = 0, this._glbInterleavedData[n + 7] = 0);
|
|
1267
1603
|
}
|
|
1268
1604
|
return this.device.queue.writeBuffer(this.glbVertexBuffer, 0, this._glbInterleavedData), !0;
|
|
1269
1605
|
}
|
|
1270
1606
|
updateAppearanceUniform() {
|
|
1607
|
+
if (this.destroyed) return;
|
|
1271
1608
|
let t = 0;
|
|
1272
1609
|
this.config.rotationMode === "random" ? t = 1 : this.config.rotationMode === "velocity" && (t = 2);
|
|
1273
|
-
const i = { square: 0, circle: 1, triangle: 2, diamond: 3, star: 4, hexagon: 5, ring: 6, heart: 7, cross: 8, spark: 9, leaf: 10, capsule: 11, crescent: 12, line: 13, "curved-line": 14 }[this.config.particleShape] ?? 0,
|
|
1274
|
-
|
|
1275
|
-
const
|
|
1276
|
-
|
|
1610
|
+
const i = { square: 0, circle: 1, triangle: 2, diamond: 3, star: 4, hexagon: 5, ring: 6, heart: 7, cross: 8, spark: 9, leaf: 10, capsule: 11, crescent: 12, line: 13, "curved-line": 14 }[this.config.particleShape] ?? 0, s = this._appearanceData;
|
|
1611
|
+
s[0] = this.config.fadeEnabled ? 1 : 0, s[1] = this.config.randomColorEnabled ? 2 : this.config.colorTransitionEnabled ? 1 : 0, s[2] = this.config.particleSize, s[3] = this.config.textureEnabled ? 1 : 0, s[4] = this.config.particleColor[0], s[5] = this.config.particleColor[1], s[6] = this.config.particleColor[2], s[7] = this.config.rotation || 0, s[8] = this.config.startColor[0], s[9] = this.config.startColor[1], s[10] = this.config.startColor[2], s[11] = t, s[12] = this.config.endColor[0], s[13] = this.config.endColor[1], s[14] = this.config.endColor[2], s[15] = this.config.minRotation || 0, s[16] = this.config.maxRotation || 90, s[17] = this.config.aspectRatio || 1, s[18] = this.config.randomSize ? 1 : 0, s[19] = this.config.minSize || 0.1, s[20] = this.config.maxSize || 0.5, s[21] = this.config.fadeSizeEnabled ? 1 : 0, s[22] = this.config.opacity !== void 0 ? this.config.opacity : 1, s[23] = this.config.increaseSizeEnabled ? 1 : 0, s[24] = this.config.sizeLifetimeSpeed ?? 1, s[25] = i, s[26] = 0, s[27] = this.config.pulseEnabled ? 1 : 0, s[28] = this.config.pulseAmplitude ?? 0.5, s[29] = this.config.pulseFrequency ?? 1, s[30] = this.config.pulsePhaseRandom ?? 0, s[31] = this.config.pulseOpacity ? 1 : 0, s[32] = this.config.particleShapeRotationX || 0, s[33] = this.config.particleShapeRotationY || 0, s[34] = this.config.particleShapeRotationZ || 0, s[35] = 0, (s[32] !== 0 || s[33] !== 0 || s[34] !== 0) && console.log(`[updateAppearanceUniform] ${this.config.name}: d[32-34] = ${s[32]}, ${s[33]}, ${s[34]}`);
|
|
1612
|
+
const n = this.config.followSystemTranslation ?? !0;
|
|
1613
|
+
s[36] = n ? this._simPosition[0] : 0, s[37] = n ? this._simPosition[1] : 0, s[38] = n ? this._simPosition[2] : 0, s[39] = 0, s[40] = this._simRotX, s[41] = this._simRotZ, s[42] = this.config.velocityStretchEnabled ? 1 : 0, s[43] = this.config.velocityStretchFactor ?? 1, s[44] = this.config.noiseDistortEnabled ? 1 : 0, s[45] = this.config.noiseTilingX ?? 3, s[46] = this.config.noiseTilingY ?? 3, s[47] = this.config.noiseSpeed ?? -1.5, s[48] = this.config.noiseAmplitude ?? 0.08, s[49] = n ? this._simVelocity[0] : 0, s[50] = n ? this._simVelocity[1] : 0, s[51] = n ? this._simVelocity[2] : 0, this.device.queue.writeBuffer(this.appearanceUniformBuffer, 0, s);
|
|
1277
1614
|
}
|
|
1278
1615
|
updateBloomIntensity() {
|
|
1279
1616
|
const t = this._bloomIntensityData;
|
|
@@ -1282,7 +1619,7 @@ class C {
|
|
|
1282
1619
|
t[4] = e[0], t[5] = e[1], t[6] = e[2], this.device.queue.writeBuffer(this.bloomIntensityBuffer, 0, t);
|
|
1283
1620
|
}
|
|
1284
1621
|
spawnParticles() {
|
|
1285
|
-
if (this.activeParticles = 0, this.currentEmissionTime = 0, this._newEmissions.length = 0, this._pendingFollowEmissions = this._emptyEmissions, this.device.queue.writeBuffer(this.trailBuffer, 0, this._trailResetData, 0, this.MAX_PARTICLES * 4), this.glbAnimator && (this.glbAnimator.currentTime = 0, this.glbAnimator.playing = !0), this.config.followSystemId) {
|
|
1622
|
+
if (this.activeParticles = 0, this.currentEmissionTime = 0, this._newEmissions.length = 0, this._pendingFollowEmissions = this._emptyEmissions, this._scriptFrame = 0, this._scriptTime = 0, this._scriptReadbackPending = !1, this._scriptReadbackReady = !1, this._scriptConfigRestored = !1, this._particleScript && (this._particleScript._configSnapshot ? (this._particleScript.restoreConfig(this.config), this.config.gravityEnabled && this.setGravity(this.config.gravityStrength), this.config.dampingEnabled && this.physics.setDamping(this.config.dampingStrength), this.config.attractorEnabled && this.setAttractor(this.config.attractorStrength, this.config.attractorPosition), this.updateAppearanceUniform(), this.updateBloomIntensity()) : this._particleScript.snapshotConfig(this.config)), this.device.queue.writeBuffer(this.trailBuffer, 0, this._trailResetData, 0, this.MAX_PARTICLES * 4), this.glbAnimator && (this.glbAnimator.currentTime = 0, this.glbAnimator.playing = !0), this.config.followSystemId) {
|
|
1286
1623
|
this.emitting = !0, this.particleCount = this.MAX_PARTICLES;
|
|
1287
1624
|
return;
|
|
1288
1625
|
}
|
|
@@ -1291,42 +1628,57 @@ class C {
|
|
|
1291
1628
|
this.particleCount = t;
|
|
1292
1629
|
let e = 0;
|
|
1293
1630
|
const i = 500;
|
|
1294
|
-
for (let
|
|
1295
|
-
if (this.emitParticle(), e++, e >= i ||
|
|
1296
|
-
const
|
|
1631
|
+
for (let s = 0; s < t; s++)
|
|
1632
|
+
if (this.emitParticle(), e++, e >= i || s === t - 1) {
|
|
1633
|
+
const n = s - e + 1, o = n * 8, a = n * 4;
|
|
1297
1634
|
this.device.queue.writeBuffer(
|
|
1298
1635
|
this.instanceBuffer,
|
|
1299
|
-
|
|
1636
|
+
o * 4,
|
|
1300
1637
|
// Offset in bytes
|
|
1301
1638
|
this.particleData,
|
|
1302
|
-
|
|
1639
|
+
o,
|
|
1303
1640
|
e * 8
|
|
1304
1641
|
), this.device.queue.writeBuffer(
|
|
1305
1642
|
this.velocityBuffer,
|
|
1306
|
-
|
|
1643
|
+
a * 4,
|
|
1307
1644
|
// Offset in bytes
|
|
1308
1645
|
this.particleVelocities,
|
|
1309
|
-
|
|
1646
|
+
a,
|
|
1310
1647
|
e * 4
|
|
1311
1648
|
), e = 0;
|
|
1312
1649
|
}
|
|
1313
1650
|
this.emitting = !1;
|
|
1314
1651
|
} else {
|
|
1315
1652
|
this.emitting = !0;
|
|
1316
|
-
const t = this.config.lifetime || 5, e = Math.
|
|
1653
|
+
const t = this.config.lifetime || 5, e = this.config.emissionDurationInfinite ? t : Math.min(this.config.emissionDuration || 10, t);
|
|
1317
1654
|
this.particleCount = Math.min(Math.ceil((this.config.emissionRate || 10) * e), this.MAX_PARTICLES);
|
|
1318
1655
|
}
|
|
1319
1656
|
}
|
|
1657
|
+
// Effective emission window: Infinity when "Infinite Duration" is on (emits forever).
|
|
1658
|
+
// Used by the emission/respawn gates; buffer sizing handles infinity separately.
|
|
1659
|
+
get effectiveEmissionDuration() {
|
|
1660
|
+
return this.config.emissionDurationInfinite ? 1 / 0 : this.config.emissionDuration ?? 10;
|
|
1661
|
+
}
|
|
1662
|
+
// Apply the simulation rotation (and, when not following translation, the world offset) to a
|
|
1663
|
+
// freshly emitted particle at `index`, in local space. MUST be called from BOTH emit routes —
|
|
1664
|
+
// the initial spawn (emitParticle) AND the continuous recycle (respawnParticle). Without it on the
|
|
1665
|
+
// recycle path, a moving emitter's particles lose the sim rotation (e.g. the heading-follow yaw)
|
|
1666
|
+
// after their first lifetime cycle, so the emission orientation silently reverts to the un-rotated
|
|
1667
|
+
// shape mid-flight — the "orientation ne suit pas l'axe" bug.
|
|
1668
|
+
_applySimTransformToParticle(t) {
|
|
1669
|
+
this._emitSimRotY = this._simRotY || 0;
|
|
1670
|
+
const e = t * 8, i = t * 4;
|
|
1671
|
+
if (this._simRotMatrix) {
|
|
1672
|
+
const s = this._simRotMatrix, n = this.particleData[e], o = this.particleData[e + 1], a = this.particleData[e + 2], c = this.particleVelocities[i], l = this.particleVelocities[i + 1], u = this.particleVelocities[i + 2];
|
|
1673
|
+
this.particleData[e] = s[0] * n + s[1] * o + s[2] * a, this.particleData[e + 1] = s[3] * n + s[4] * o + s[5] * a, this.particleData[e + 2] = s[6] * n + s[7] * o + s[8] * a, this.particleVelocities[i] = s[0] * c + s[1] * l + s[2] * u, this.particleVelocities[i + 1] = s[3] * c + s[4] * l + s[5] * u, this.particleVelocities[i + 2] = s[6] * c + s[7] * l + s[8] * u;
|
|
1674
|
+
}
|
|
1675
|
+
(this.config.followSystemTranslation ?? !0) || (this.particleData[e] += this._simPosition[0], this.particleData[e + 1] += this._simPosition[1], this.particleData[e + 2] += this._simPosition[2]);
|
|
1676
|
+
}
|
|
1320
1677
|
emitParticle() {
|
|
1321
1678
|
if (this.activeParticles >= this.particleCount) return !1;
|
|
1322
1679
|
this.emitter.emitParticle(this.particleData, this.activeParticles, this.particleVelocities);
|
|
1323
1680
|
const t = this.activeParticles * 8, e = this.activeParticles * 4;
|
|
1324
|
-
|
|
1325
|
-
let i = this.particleData[t], a = this.particleData[t + 1], r = this.particleData[t + 2], n = this.particleVelocities[e], o = this.particleVelocities[e + 1], s = this.particleVelocities[e + 2];
|
|
1326
|
-
const l = this._simRotMatrix;
|
|
1327
|
-
this.particleData[t] = l[0] * i + l[1] * a + l[2] * r, this.particleData[t + 1] = l[3] * i + l[4] * a + l[5] * r, this.particleData[t + 2] = l[6] * i + l[7] * a + l[8] * r, this.particleVelocities[e] = l[0] * n + l[1] * o + l[2] * s, this.particleVelocities[e + 1] = l[3] * n + l[4] * o + l[5] * s, this.particleVelocities[e + 2] = l[6] * n + l[7] * o + l[8] * s;
|
|
1328
|
-
}
|
|
1329
|
-
return (this.config.followSystemTranslation ?? !0) || (this.particleData[t] += this._simPosition[0], this.particleData[t + 1] += this._simPosition[1], this.particleData[t + 2] += this._simPosition[2]), this._newEmissions.push(
|
|
1681
|
+
return this._applySimTransformToParticle(this.activeParticles), this._newEmissions.push(
|
|
1330
1682
|
this.particleData[t],
|
|
1331
1683
|
this.particleData[t + 1],
|
|
1332
1684
|
this.particleData[t + 2],
|
|
@@ -1341,29 +1693,59 @@ class C {
|
|
|
1341
1693
|
*/
|
|
1342
1694
|
emitFollowerParticle(t, e, i) {
|
|
1343
1695
|
if (this.activeParticles >= this.particleCount) return !1;
|
|
1344
|
-
const
|
|
1345
|
-
this.particleData[
|
|
1346
|
-
const
|
|
1347
|
-
return this.emitter.calculateVelocity(
|
|
1696
|
+
const s = this.activeParticles * 8, n = t + (this.config.emissionPositionX || 0), o = e + (this.config.emissionPositionY || 0), a = i + (this.config.emissionPositionZ || 0);
|
|
1697
|
+
this.particleData[s] = n, this.particleData[s + 1] = o, this.particleData[s + 2] = a;
|
|
1698
|
+
const c = this.activeParticles * 4;
|
|
1699
|
+
return this.emitter.calculateVelocity(n, o, a, this.particleVelocities, c), this.emitter.setParticleColor(this.particleData, s), this.emitter.setParticleLifetime(this.particleData, s), this.activeParticles++, !0;
|
|
1348
1700
|
}
|
|
1349
1701
|
updateParticles(t, e) {
|
|
1702
|
+
if (this._particleScript && this._scriptReadbackReady) {
|
|
1703
|
+
this._scriptReadbackReady = !1, this._scriptTime += t, this._scriptFrame++;
|
|
1704
|
+
const a = this.config.emissionDurationInfinite ? 1 / 0 : (this.config.emissionDuration || 0) + (this.config.lifetime || 0);
|
|
1705
|
+
if (a > 0 && this._scriptTime >= a && !this._scriptConfigRestored)
|
|
1706
|
+
this._scriptConfigRestored = !0, this._particleScript._configSnapshot && (this._particleScript.restoreConfig(this.config), this.updateAppearanceUniform(), this.updateBloomIntensity(), this.config.gravityEnabled && this.setGravity(this.config.gravityStrength), this.config.dampingEnabled && this.physics.setDamping(this.config.dampingStrength), this.config.attractorEnabled && this.setAttractor(this.config.attractorStrength, this.config.attractorPosition));
|
|
1707
|
+
else if (!this._scriptConfigRestored) {
|
|
1708
|
+
const c = a > 0 ? Math.ceil(a / 0.016666666666666666) : 0, { configDirty: l, particlesDirty: u } = this._particleScript.execute(
|
|
1709
|
+
t,
|
|
1710
|
+
this._scriptTime,
|
|
1711
|
+
this._scriptFrame,
|
|
1712
|
+
c,
|
|
1713
|
+
this._scriptParticleData,
|
|
1714
|
+
this._scriptVelocityData,
|
|
1715
|
+
this.activeParticles
|
|
1716
|
+
);
|
|
1717
|
+
u && this.activeParticles > 0 && (this.device.queue.writeBuffer(
|
|
1718
|
+
this.instanceBuffer,
|
|
1719
|
+
0,
|
|
1720
|
+
this._scriptParticleData,
|
|
1721
|
+
0,
|
|
1722
|
+
this.activeParticles * 8
|
|
1723
|
+
), this.device.queue.writeBuffer(
|
|
1724
|
+
this.velocityBuffer,
|
|
1725
|
+
0,
|
|
1726
|
+
this._scriptVelocityData,
|
|
1727
|
+
0,
|
|
1728
|
+
this.activeParticles * 4
|
|
1729
|
+
)), l && (this.updateAppearanceUniform(), this.updateBloomIntensity(), this.config.gravityEnabled && this.setGravity(this.config.gravityStrength), this.config.dampingEnabled && this.physics.setDamping(this.config.dampingStrength), this.config.attractorEnabled && this.setAttractor(this.config.attractorStrength, this.config.attractorPosition));
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1350
1732
|
this.physics.physicsAccumulator += t;
|
|
1351
|
-
const i = performance.now() / 1e3,
|
|
1352
|
-
if (this.emitting)
|
|
1353
|
-
if (this.currentEmissionTime += t, this.currentEmissionTime < this.
|
|
1354
|
-
const
|
|
1355
|
-
let
|
|
1733
|
+
const i = performance.now() / 1e3, n = i - this.physics.lastUpdateTime > 1 / this.physics.minUpdatesPerSecond, o = this.activeParticles;
|
|
1734
|
+
if (!this.emitting && !this.config.burstMode && !this.config.followSystemId && this.currentEmissionTime < this.effectiveEmissionDuration && (this.emitting = !0), this.emitting)
|
|
1735
|
+
if (this.currentEmissionTime += t, this.currentEmissionTime < this.effectiveEmissionDuration) {
|
|
1736
|
+
const a = this.activeParticles;
|
|
1737
|
+
let c = !1;
|
|
1356
1738
|
if (this.config.followSystemId) {
|
|
1357
1739
|
if (this._pendingFollowEmissions.length > 0) {
|
|
1358
1740
|
const l = this._pendingFollowEmissions.length / 6;
|
|
1359
1741
|
for (let u = 0; u < l; u++) {
|
|
1360
|
-
const
|
|
1742
|
+
const f = u * 6;
|
|
1361
1743
|
if (this.emitFollowerParticle(
|
|
1362
|
-
this._pendingFollowEmissions[
|
|
1363
|
-
this._pendingFollowEmissions[
|
|
1364
|
-
this._pendingFollowEmissions[
|
|
1744
|
+
this._pendingFollowEmissions[f],
|
|
1745
|
+
this._pendingFollowEmissions[f + 1],
|
|
1746
|
+
this._pendingFollowEmissions[f + 2]
|
|
1365
1747
|
))
|
|
1366
|
-
|
|
1748
|
+
c = !0;
|
|
1367
1749
|
else
|
|
1368
1750
|
break;
|
|
1369
1751
|
}
|
|
@@ -1378,12 +1760,12 @@ class C {
|
|
|
1378
1760
|
const u = this.config.emissionRate * t;
|
|
1379
1761
|
Math.random() < u && (l = 1);
|
|
1380
1762
|
}
|
|
1381
|
-
l === 0 &&
|
|
1763
|
+
l === 0 && n && this.config.emissionRate > 0 && this.activeParticles < this.particleCount && (l = 1);
|
|
1382
1764
|
for (let u = 0; u < l && this.emitParticle(); u++)
|
|
1383
|
-
|
|
1765
|
+
c = !0;
|
|
1384
1766
|
}
|
|
1385
|
-
if (
|
|
1386
|
-
const l = this.activeParticles -
|
|
1767
|
+
if (c) {
|
|
1768
|
+
const l = this.activeParticles - a, u = a * 8, f = a * 4;
|
|
1387
1769
|
this.device.queue.writeBuffer(
|
|
1388
1770
|
this.instanceBuffer,
|
|
1389
1771
|
u * 4,
|
|
@@ -1393,10 +1775,10 @@ class C {
|
|
|
1393
1775
|
l * 8
|
|
1394
1776
|
), this.device.queue.writeBuffer(
|
|
1395
1777
|
this.velocityBuffer,
|
|
1396
|
-
|
|
1778
|
+
f * 4,
|
|
1397
1779
|
// Offset in bytes (float32 = 4 bytes)
|
|
1398
1780
|
this.particleVelocities,
|
|
1399
|
-
|
|
1781
|
+
f,
|
|
1400
1782
|
l * 4
|
|
1401
1783
|
);
|
|
1402
1784
|
}
|
|
@@ -1405,20 +1787,30 @@ class C {
|
|
|
1405
1787
|
for (; this.physics.physicsAccumulator >= this.physics.fixedDeltaTime; )
|
|
1406
1788
|
this.physics.updatePhysics(
|
|
1407
1789
|
this.physics.fixedDeltaTime,
|
|
1408
|
-
|
|
1790
|
+
o,
|
|
1409
1791
|
this.config,
|
|
1410
1792
|
this.instanceBuffer,
|
|
1411
1793
|
this.velocityBuffer,
|
|
1412
1794
|
e
|
|
1413
1795
|
), this.physics.physicsAccumulator -= this.physics.fixedDeltaTime, this.physics.physicsClock += this.physics.fixedDeltaTime;
|
|
1414
|
-
|
|
1796
|
+
n && o > 0 && (this.physics.updatePhysics(
|
|
1415
1797
|
this.physics.fixedDeltaTime,
|
|
1416
|
-
|
|
1798
|
+
o,
|
|
1417
1799
|
this.config,
|
|
1418
1800
|
this.instanceBuffer,
|
|
1419
1801
|
this.velocityBuffer,
|
|
1420
1802
|
e
|
|
1421
|
-
), this.physics.lastUpdateTime = i), this.frameCount
|
|
1803
|
+
), this.physics.lastUpdateTime = i), this.frameCount++, (this.activeParticles >= this.particleCount || this.frameCount % 300 === 0) && this.readbackAndProcessParticles(), this._particleScript && this.activeParticles > 0 && !this._scriptReadbackPending && (this._scriptReadbackPending = !0, this.physics.readbackForScript(
|
|
1804
|
+
this.activeParticles,
|
|
1805
|
+
this._scriptParticleData,
|
|
1806
|
+
this._scriptVelocityData,
|
|
1807
|
+
this.instanceBuffer,
|
|
1808
|
+
this.velocityBuffer
|
|
1809
|
+
).then((a) => {
|
|
1810
|
+
this._scriptReadbackPending = !1, a.shouldUpdate && (this._scriptReadbackReady = !0);
|
|
1811
|
+
}).catch(() => {
|
|
1812
|
+
this._scriptReadbackPending = !1;
|
|
1813
|
+
}));
|
|
1422
1814
|
}
|
|
1423
1815
|
async readbackAndProcessParticles() {
|
|
1424
1816
|
if (!(this.activeParticles <= 0))
|
|
@@ -1430,58 +1822,60 @@ class C {
|
|
|
1430
1822
|
this.instanceBuffer,
|
|
1431
1823
|
this.velocityBuffer
|
|
1432
1824
|
)).shouldUpdate) return;
|
|
1433
|
-
let e = 0;
|
|
1434
|
-
for (let
|
|
1435
|
-
const
|
|
1436
|
-
if (
|
|
1437
|
-
if (this.emitting && this.currentEmissionTime < this.
|
|
1438
|
-
this.respawnParticle(
|
|
1825
|
+
let e = 0, i = !1;
|
|
1826
|
+
for (let s = 0; s < this.activeParticles; s++) {
|
|
1827
|
+
const n = this.particleData[s * 8 + 6], o = this.particleData[s * 8 + 7];
|
|
1828
|
+
if (n >= o) {
|
|
1829
|
+
if (this.emitting && this.currentEmissionTime < this.effectiveEmissionDuration && e < this.particleCount) {
|
|
1830
|
+
this.respawnParticle(s, e), e++, i = !0;
|
|
1439
1831
|
continue;
|
|
1440
1832
|
}
|
|
1441
1833
|
continue;
|
|
1442
1834
|
}
|
|
1443
|
-
if (e !==
|
|
1444
|
-
const
|
|
1445
|
-
this.particleData.copyWithin(
|
|
1446
|
-
const
|
|
1447
|
-
this.particleVelocities.copyWithin(
|
|
1835
|
+
if (e !== s) {
|
|
1836
|
+
const a = s * 8, c = e * 8;
|
|
1837
|
+
this.particleData.copyWithin(c, a, a + 8);
|
|
1838
|
+
const l = s * 4, u = e * 4;
|
|
1839
|
+
this.particleVelocities.copyWithin(u, l, l + 4), i = !0;
|
|
1448
1840
|
}
|
|
1449
1841
|
e++;
|
|
1450
1842
|
}
|
|
1451
|
-
e !== this.activeParticles && (this.activeParticles = e, this.device.queue.writeBuffer(this.instanceBuffer, 0, this.particleData, 0, this.activeParticles * 8), this.device.queue.writeBuffer(this.velocityBuffer, 0, this.particleVelocities, 0, this.activeParticles * 4));
|
|
1843
|
+
(e !== this.activeParticles || i) && (this.activeParticles = e, this.device.queue.writeBuffer(this.instanceBuffer, 0, this.particleData, 0, this.activeParticles * 8), this.device.queue.writeBuffer(this.velocityBuffer, 0, this.particleVelocities, 0, this.activeParticles * 4));
|
|
1452
1844
|
} catch (t) {
|
|
1453
|
-
console.error("Error reading back particle data:", t);
|
|
1845
|
+
t && t.name === "AbortError" || console.error("Error reading back particle data:", t);
|
|
1454
1846
|
}
|
|
1455
1847
|
}
|
|
1456
1848
|
respawnParticle(t, e) {
|
|
1457
|
-
!this.emitting || this.currentEmissionTime >= this.
|
|
1849
|
+
!this.emitting || this.currentEmissionTime >= this.effectiveEmissionDuration || this.config.followSystemId || (this.emitter.emitParticle(this.particleData, e, this.particleVelocities), this._applySimTransformToParticle(e));
|
|
1458
1850
|
}
|
|
1459
1851
|
updateBuffers() {
|
|
1460
|
-
this.activeParticles > 0 && this.device.queue.writeBuffer(this.instanceBuffer, 0, this.particleData, 0, this.activeParticles * 8);
|
|
1852
|
+
this.destroyed || !this.particleData || this.activeParticles > 0 && this.device.queue.writeBuffer(this.instanceBuffer, 0, this.particleData, 0, this.activeParticles * 8);
|
|
1461
1853
|
}
|
|
1462
1854
|
updateParticleColors() {
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1855
|
+
if (!(this.destroyed || !this.particleData)) {
|
|
1856
|
+
for (let t = 0; t < this.activeParticles; t++) {
|
|
1857
|
+
const e = t * 8;
|
|
1858
|
+
if (this.config.randomColorEnabled && this.config.randomColors.length > 0) {
|
|
1859
|
+
const i = this.config.randomColors, s = i[Math.floor(Math.random() * i.length)];
|
|
1860
|
+
this.particleData[e + 3] = s[0], this.particleData[e + 4] = s[1], this.particleData[e + 5] = s[2];
|
|
1861
|
+
} else this.config.colorTransitionEnabled ? (this.particleData[e + 3] = this.config.startColor[0], this.particleData[e + 4] = this.config.startColor[1], this.particleData[e + 5] = this.config.startColor[2]) : (this.particleData[e + 3] = this.config.particleColor[0], this.particleData[e + 4] = this.config.particleColor[1], this.particleData[e + 5] = this.config.particleColor[2]);
|
|
1862
|
+
}
|
|
1863
|
+
this.activeParticles > 0 && this.device.queue.writeBuffer(this.instanceBuffer, 0, this.particleData, 0, this.activeParticles * 8);
|
|
1469
1864
|
}
|
|
1470
|
-
this.activeParticles > 0 && this.device.queue.writeBuffer(this.instanceBuffer, 0, this.particleData, 0, this.activeParticles * 8);
|
|
1471
1865
|
}
|
|
1472
1866
|
updateParticleVelocities() {
|
|
1473
1867
|
for (let t = 0; t < this.activeParticles; t++) {
|
|
1474
|
-
const e = t * 8, i = t * 4,
|
|
1475
|
-
|
|
1868
|
+
const e = t * 8, i = t * 4, s = this.particleData[e], n = this.particleData[e + 1], o = this.particleData[e + 2], a = this.particleVelocities[i], c = this.particleVelocities[i + 1], l = this.particleVelocities[i + 2], u = Math.sqrt(
|
|
1869
|
+
a * a + c * c + l * l
|
|
1476
1870
|
);
|
|
1477
1871
|
if (u > 1e-3) {
|
|
1478
|
-
const
|
|
1479
|
-
this.particleVelocities[i] =
|
|
1872
|
+
const f = this.config.particleSpeed * 2;
|
|
1873
|
+
this.particleVelocities[i] = a / u * f, this.particleVelocities[i + 1] = c / u * f, this.particleVelocities[i + 2] = l / u * f;
|
|
1480
1874
|
} else {
|
|
1481
|
-
const
|
|
1482
|
-
if (
|
|
1483
|
-
const
|
|
1484
|
-
this.particleVelocities[i] =
|
|
1875
|
+
const f = Math.sqrt(s * s + n * n + o * o);
|
|
1876
|
+
if (f > 1e-3) {
|
|
1877
|
+
const h = this.config.particleSpeed * 2;
|
|
1878
|
+
this.particleVelocities[i] = s / f * h, this.particleVelocities[i + 1] = n / f * h, this.particleVelocities[i + 2] = o / f * h;
|
|
1485
1879
|
} else
|
|
1486
1880
|
this.particleVelocities[i] = 0, this.particleVelocities[i + 1] = this.config.particleSpeed * 2, this.particleVelocities[i + 2] = 0;
|
|
1487
1881
|
}
|
|
@@ -1510,7 +1904,7 @@ class C {
|
|
|
1510
1904
|
* Call this when the system is no longer needed.
|
|
1511
1905
|
*/
|
|
1512
1906
|
destroy() {
|
|
1513
|
-
this.instanceBuffer.destroy(), this.velocityBuffer.destroy(), this.trailBuffer.destroy(), this.appearanceUniformBuffer.destroy(), this.bloomIntensityBuffer.destroy(), this.physics.destroy(), this.glbVertexBuffer && (this.glbVertexBuffer.destroy(), this.glbVertexBuffer = null), this.glbIndexBuffer && (this.glbIndexBuffer.destroy(), this.glbIndexBuffer = null), this.textureManager.destroyTexture(this.particleTexture), this.glbAnimator = null, this.glbMeshData = null, this.glbRawArrayBuffer = null, this.particleData = null, this.particleVelocities = null;
|
|
1907
|
+
this.destroyed = !0, this.instanceBuffer.destroy(), this.velocityBuffer.destroy(), this.trailBuffer.destroy(), this.appearanceUniformBuffer.destroy(), this.bloomIntensityBuffer.destroy(), this.physics.destroy(), this.glbVertexBuffer && (this.glbVertexBuffer.destroy(), this.glbVertexBuffer = null), this.glbIndexBuffer && (this.glbIndexBuffer.destroy(), this.glbIndexBuffer = null), this.textureManager.destroyTexture(this.particleTexture), this._particleScript && (this._particleScript.destroy(), this._particleScript = null), this.glbAnimator = null, this.glbMeshData = null, this.glbRawArrayBuffer = null, this.particleData = null, this.particleVelocities = null, this._scriptParticleData = null, this._scriptVelocityData = null;
|
|
1514
1908
|
}
|
|
1515
1909
|
setGravity(t) {
|
|
1516
1910
|
this.physics.setGravity(t);
|
|
@@ -1519,27 +1913,27 @@ class C {
|
|
|
1519
1913
|
this.physics.setAttractor(t, e);
|
|
1520
1914
|
}
|
|
1521
1915
|
setConfinement(t) {
|
|
1522
|
-
const e = t.space === "local" ? [this.config.
|
|
1523
|
-
this.physics.setConfinement({ ...t, center:
|
|
1916
|
+
const e = t.center || this.config.confinementCenter || [0, 0, 0], i = t.space === "local" ? [this.config.emissionPositionX || 0, this.config.emissionPositionY || 0, this.config.emissionPositionZ || 0] : [0, 0, 0], s = [i[0] + (e[0] || 0), i[1] + (e[1] || 0), i[2] + (e[2] || 0)];
|
|
1917
|
+
this.physics.setConfinement({ ...t, center: s });
|
|
1524
1918
|
}
|
|
1525
1919
|
setSoftBoundary(t) {
|
|
1526
1920
|
this.physics.setSoftBoundary(t);
|
|
1527
1921
|
}
|
|
1528
1922
|
}
|
|
1529
|
-
class
|
|
1923
|
+
class Es {
|
|
1530
1924
|
constructor(t) {
|
|
1531
|
-
this.device = t, this.particleSystems = [], this.activeSystemIndex = 0, this.systemCounter = 1, this.onSystemCreated = null;
|
|
1925
|
+
this.device = t, this.particleSystems = [], this.activeSystemIndex = 0, this.systemCounter = 1, this.onSystemCreated = null, this.loop = void 0, this.ready = !0;
|
|
1532
1926
|
}
|
|
1533
1927
|
createParticleSystem(t = {}) {
|
|
1534
|
-
const e = this.systemCounter++, i = t.name || `System ${e + 1}`,
|
|
1928
|
+
const e = this.systemCounter++, i = t.name || `System ${e + 1}`, s = {
|
|
1535
1929
|
...t,
|
|
1536
1930
|
name: i,
|
|
1537
1931
|
id: e
|
|
1538
|
-
},
|
|
1932
|
+
}, n = new bt(this.device, s);
|
|
1539
1933
|
return this.particleSystems.push({
|
|
1540
|
-
system:
|
|
1541
|
-
config:
|
|
1542
|
-
}), this.particleSystems.length === 1 && (this.activeSystemIndex = 0), this.onSystemCreated && typeof this.onSystemCreated == "function" && this.onSystemCreated(e,
|
|
1934
|
+
system: n,
|
|
1935
|
+
config: s
|
|
1936
|
+
}), this.particleSystems.length === 1 && (this.activeSystemIndex = 0), this.onSystemCreated && typeof this.onSystemCreated == "function" && this.onSystemCreated(e, s), e;
|
|
1543
1937
|
}
|
|
1544
1938
|
getActiveSystem() {
|
|
1545
1939
|
return this.particleSystems.length === 0 ? null : this.particleSystems[this.activeSystemIndex].system;
|
|
@@ -1566,8 +1960,8 @@ class me {
|
|
|
1566
1960
|
const e = this.particleSystems[t].config;
|
|
1567
1961
|
this.particleSystems[t].system.destroy(), this.particleSystems.splice(t, 1);
|
|
1568
1962
|
const i = e.id;
|
|
1569
|
-
for (const { config:
|
|
1570
|
-
|
|
1963
|
+
for (const { config: s } of this.particleSystems)
|
|
1964
|
+
s.followSystemId === i && (s.followSystemId = null);
|
|
1571
1965
|
return this.particleSystems.length === 0 ? this.activeSystemIndex = 0 : t <= this.activeSystemIndex && (this.activeSystemIndex = Math.max(0, this.activeSystemIndex - 1)), !0;
|
|
1572
1966
|
}
|
|
1573
1967
|
return !1;
|
|
@@ -1579,21 +1973,21 @@ class me {
|
|
|
1579
1973
|
updateAllSystems(t) {
|
|
1580
1974
|
const e = this.device.createCommandEncoder({ label: "BatchedPhysicsEncoder" });
|
|
1581
1975
|
let i = !1;
|
|
1582
|
-
for (const { system:
|
|
1583
|
-
if (
|
|
1584
|
-
const
|
|
1585
|
-
|
|
1976
|
+
for (const { system: s, config: n } of this.particleSystems) {
|
|
1977
|
+
if (n.hidden || n.followSystemId) continue;
|
|
1978
|
+
const o = s.activeParticles > 0;
|
|
1979
|
+
s.updateParticles(t, e), (o || s.activeParticles > 0) && (i = !0);
|
|
1586
1980
|
}
|
|
1587
|
-
for (const { system:
|
|
1588
|
-
if (
|
|
1589
|
-
const
|
|
1590
|
-
|
|
1591
|
-
const
|
|
1592
|
-
|
|
1981
|
+
for (const { system: s, config: n } of this.particleSystems) {
|
|
1982
|
+
if (n.hidden || !n.followSystemId) continue;
|
|
1983
|
+
const o = this.getSystemById(n.followSystemId);
|
|
1984
|
+
o && (s._pendingFollowEmissions = o.system._newEmissions);
|
|
1985
|
+
const a = s.activeParticles > 0;
|
|
1986
|
+
s.updateParticles(t, e), (a || s.activeParticles > 0) && (i = !0);
|
|
1593
1987
|
}
|
|
1594
1988
|
i && this.device.queue.submit([e.finish()]);
|
|
1595
|
-
for (const { system:
|
|
1596
|
-
|
|
1989
|
+
for (const { system: s } of this.particleSystems)
|
|
1990
|
+
s._newEmissions.length = 0, s._pendingFollowEmissions = s._emptyEmissions;
|
|
1597
1991
|
}
|
|
1598
1992
|
getSystemsList() {
|
|
1599
1993
|
return this.particleSystems.map(({ config: t }, e) => ({
|
|
@@ -1618,68 +2012,71 @@ class me {
|
|
|
1618
2012
|
var e;
|
|
1619
2013
|
if (!t || !t.systems || !Array.isArray(t.systems))
|
|
1620
2014
|
return console.error("Invalid scene data provided"), !1;
|
|
2015
|
+
this.ready = !1;
|
|
1621
2016
|
try {
|
|
1622
2017
|
this.particleSystems = [], this.systemCounter = 1;
|
|
1623
|
-
for (const
|
|
1624
|
-
const
|
|
1625
|
-
...
|
|
1626
|
-
id:
|
|
1627
|
-
},
|
|
2018
|
+
for (const s of t.systems) {
|
|
2019
|
+
const n = this.systemCounter++, o = {
|
|
2020
|
+
...s,
|
|
2021
|
+
id: n
|
|
2022
|
+
}, a = new bt(this.device, o);
|
|
1628
2023
|
this.particleSystems.push({
|
|
1629
|
-
system:
|
|
1630
|
-
config:
|
|
2024
|
+
system: a,
|
|
2025
|
+
config: o
|
|
1631
2026
|
});
|
|
1632
2027
|
}
|
|
1633
2028
|
const i = {};
|
|
1634
|
-
t.systems.forEach((
|
|
1635
|
-
i[
|
|
2029
|
+
t.systems.forEach((s, n) => {
|
|
2030
|
+
i[s.id] = this.particleSystems[n].config.id;
|
|
1636
2031
|
});
|
|
1637
|
-
for (const { config:
|
|
1638
|
-
|
|
1639
|
-
t.activeSystemIndex !== void 0 && t.activeSystemIndex >= 0 && t.activeSystemIndex < this.particleSystems.length ? this.activeSystemIndex = t.activeSystemIndex : this.activeSystemIndex = 0;
|
|
1640
|
-
for (const { system:
|
|
1641
|
-
if (
|
|
2032
|
+
for (const { config: s } of this.particleSystems)
|
|
2033
|
+
s.followSystemId && i[s.followSystemId] !== void 0 && (s.followSystemId = i[s.followSystemId]);
|
|
2034
|
+
t.activeSystemIndex !== void 0 && t.activeSystemIndex >= 0 && t.activeSystemIndex < this.particleSystems.length ? this.activeSystemIndex = t.activeSystemIndex : this.activeSystemIndex = 0, this.loop = t.loop;
|
|
2035
|
+
for (const { system: s, config: n } of this.particleSystems)
|
|
2036
|
+
if (n.glbModelEnabled)
|
|
1642
2037
|
try {
|
|
1643
|
-
let
|
|
1644
|
-
if (
|
|
1645
|
-
|
|
1646
|
-
else if (
|
|
1647
|
-
const
|
|
1648
|
-
|
|
2038
|
+
let o = null;
|
|
2039
|
+
if (n.glbModelData)
|
|
2040
|
+
o = ci(n.glbModelData);
|
|
2041
|
+
else if (n.glbFileName) {
|
|
2042
|
+
const a = await fetch(`/${n.glbFileName}`);
|
|
2043
|
+
a.ok ? o = await a.arrayBuffer() : console.warn(`GLB file not found: ${n.glbFileName}`);
|
|
1649
2044
|
}
|
|
1650
|
-
if (
|
|
1651
|
-
if (await
|
|
2045
|
+
if (o) {
|
|
2046
|
+
if (await s.setGLBModel(o), n.animationIndex !== void 0 && s.glbAnimator && s.glbAnimator.setAnimation(n.animationIndex), n.animationSpeed !== void 0 && s.glbAnimator && (s.glbAnimator.speed = n.animationSpeed), n.animationLoop !== void 0 && s.glbAnimator && (s.glbAnimator.loop = n.animationLoop), n.useGlbTexture && (n.textureEnabled = !0), n.useGlbTexture && ((e = s.glbMeshData) != null && e.hasBaseColorTexture))
|
|
1652
2047
|
try {
|
|
1653
|
-
const { extractGLBTexture:
|
|
1654
|
-
if (
|
|
1655
|
-
const l = await createImageBitmap(
|
|
1656
|
-
await
|
|
2048
|
+
const { extractGLBTexture: a } = await Promise.resolve().then(() => ni), c = await a(o);
|
|
2049
|
+
if (c) {
|
|
2050
|
+
const l = await createImageBitmap(c.imageBlob);
|
|
2051
|
+
await s.setTexture(l), console.log(`GLB embedded texture restored for ${n.name}`);
|
|
1657
2052
|
}
|
|
1658
|
-
} catch (
|
|
1659
|
-
console.warn(`Failed to restore GLB texture for ${
|
|
2053
|
+
} catch (a) {
|
|
2054
|
+
console.warn(`Failed to restore GLB texture for ${n.name}:`, a), n.useGlbTexture = !1;
|
|
1660
2055
|
}
|
|
1661
2056
|
} else
|
|
1662
|
-
|
|
1663
|
-
} catch (
|
|
1664
|
-
console.warn(`Failed to load GLB for ${
|
|
2057
|
+
n.glbModelEnabled = !1;
|
|
2058
|
+
} catch (o) {
|
|
2059
|
+
console.warn(`Failed to load GLB for ${n.name}:`, o), n.glbModelEnabled = !1;
|
|
1665
2060
|
}
|
|
1666
|
-
for (const { system:
|
|
1667
|
-
if (
|
|
2061
|
+
for (const { system: s, config: n } of this.particleSystems)
|
|
2062
|
+
if (n.textureEnabled && !n.glbModelEnabled && n.textureImageData)
|
|
1668
2063
|
try {
|
|
1669
|
-
const
|
|
1670
|
-
await new Promise((
|
|
1671
|
-
|
|
2064
|
+
const o = new Image();
|
|
2065
|
+
await new Promise((c, l) => {
|
|
2066
|
+
o.onload = c, o.onerror = l, o.src = n.textureImageData;
|
|
1672
2067
|
});
|
|
1673
|
-
const
|
|
1674
|
-
await
|
|
1675
|
-
} catch (
|
|
1676
|
-
console.warn(`Failed to restore texture for ${
|
|
2068
|
+
const a = await createImageBitmap(o);
|
|
2069
|
+
await s.setTexture(a);
|
|
2070
|
+
} catch (o) {
|
|
2071
|
+
console.warn(`Failed to restore texture for ${n.name}:`, o), n.textureEnabled = !1;
|
|
1677
2072
|
}
|
|
1678
|
-
for (const { system:
|
|
1679
|
-
|
|
2073
|
+
for (const { system: s, config: n } of this.particleSystems)
|
|
2074
|
+
s.updateAppearanceUniform(), (n.particleShapeRotationX || n.particleShapeRotationY || n.particleShapeRotationZ) && console.log(`[replaceSystems] ${n.name}: glbRotation XYZ = ${n.particleShapeRotationX}, ${n.particleShapeRotationY}, ${n.particleShapeRotationZ} | glbModelEnabled=${n.glbModelEnabled} | glbMeshData=${!!s.glbMeshData}`);
|
|
1680
2075
|
return this.respawnAllSystems(), !0;
|
|
1681
2076
|
} catch (i) {
|
|
1682
2077
|
return console.error("Error replacing systems:", i), !1;
|
|
2078
|
+
} finally {
|
|
2079
|
+
this.ready = !0;
|
|
1683
2080
|
}
|
|
1684
2081
|
}
|
|
1685
2082
|
/**
|
|
@@ -1690,132 +2087,139 @@ class me {
|
|
|
1690
2087
|
* @returns {boolean} - Whether the addition was successful
|
|
1691
2088
|
*/
|
|
1692
2089
|
async addSystems(t, e = [0, 0, 0]) {
|
|
1693
|
-
var
|
|
2090
|
+
var s;
|
|
1694
2091
|
if (!t || !t.systems || !Array.isArray(t.systems))
|
|
1695
2092
|
return console.error("Invalid scene data provided"), !1;
|
|
2093
|
+
this.ready = !1;
|
|
2094
|
+
const i = [];
|
|
1696
2095
|
try {
|
|
1697
|
-
for (const
|
|
1698
|
-
const
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
2096
|
+
for (const a of t.systems) {
|
|
2097
|
+
const c = this.systemCounter++;
|
|
2098
|
+
i.push(c);
|
|
2099
|
+
const l = {
|
|
2100
|
+
...a,
|
|
2101
|
+
id: c,
|
|
2102
|
+
// Apply world-space offset to emission translation
|
|
2103
|
+
emissionPositionX: (a.emissionPositionX || 0) + e[0],
|
|
2104
|
+
emissionPositionY: (a.emissionPositionY || 0) + e[1],
|
|
2105
|
+
emissionPositionZ: (a.emissionPositionZ || 0) + e[2]
|
|
1705
2106
|
};
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
2107
|
+
a.attractorEnabled && a.attractorPosition && (l.attractorPosition = [
|
|
2108
|
+
a.attractorPosition[0] + e[0],
|
|
2109
|
+
a.attractorPosition[1] + e[1],
|
|
2110
|
+
a.attractorPosition[2] + e[2]
|
|
1710
2111
|
]);
|
|
1711
|
-
const
|
|
2112
|
+
const u = new bt(this.device, l);
|
|
1712
2113
|
this.particleSystems.push({
|
|
1713
|
-
system:
|
|
1714
|
-
config:
|
|
1715
|
-
}), this.onSystemCreated && typeof this.onSystemCreated == "function" && this.onSystemCreated(
|
|
2114
|
+
system: u,
|
|
2115
|
+
config: l
|
|
2116
|
+
}), this.onSystemCreated && typeof this.onSystemCreated == "function" && this.onSystemCreated(c, l);
|
|
1716
2117
|
}
|
|
1717
|
-
const
|
|
1718
|
-
t.systems.forEach((
|
|
1719
|
-
|
|
2118
|
+
const n = this.particleSystems.length - t.systems.length, o = {};
|
|
2119
|
+
t.systems.forEach((a, c) => {
|
|
2120
|
+
o[a.id] = this.particleSystems[n + c].config.id;
|
|
1720
2121
|
});
|
|
1721
|
-
for (let
|
|
1722
|
-
const { config:
|
|
1723
|
-
|
|
2122
|
+
for (let a = n; a < this.particleSystems.length; a++) {
|
|
2123
|
+
const { config: c } = this.particleSystems[a];
|
|
2124
|
+
c.followSystemId && o[c.followSystemId] !== void 0 && (c.followSystemId = o[c.followSystemId]);
|
|
1724
2125
|
}
|
|
1725
|
-
for (const { system:
|
|
1726
|
-
if (
|
|
2126
|
+
for (const { system: a, config: c } of this.particleSystems)
|
|
2127
|
+
if (c.glbModelEnabled && !a.glbMeshData)
|
|
1727
2128
|
try {
|
|
1728
|
-
let
|
|
1729
|
-
if (
|
|
1730
|
-
|
|
1731
|
-
else if (
|
|
1732
|
-
const
|
|
1733
|
-
|
|
2129
|
+
let l = null;
|
|
2130
|
+
if (c.glbModelData)
|
|
2131
|
+
l = ci(c.glbModelData);
|
|
2132
|
+
else if (c.glbFileName) {
|
|
2133
|
+
const u = await fetch(`/${c.glbFileName}`);
|
|
2134
|
+
u.ok ? l = await u.arrayBuffer() : console.warn(`GLB file not found: ${c.glbFileName}`);
|
|
1734
2135
|
}
|
|
1735
|
-
if (
|
|
1736
|
-
if (await
|
|
2136
|
+
if (l) {
|
|
2137
|
+
if (await a.setGLBModel(l), c.animationIndex !== void 0 && a.glbAnimator && a.glbAnimator.setAnimation(c.animationIndex), c.animationSpeed !== void 0 && a.glbAnimator && (a.glbAnimator.speed = c.animationSpeed), c.animationLoop !== void 0 && a.glbAnimator && (a.glbAnimator.loop = c.animationLoop), c.useGlbTexture && (c.textureEnabled = !0), c.useGlbTexture && ((s = a.glbMeshData) != null && s.hasBaseColorTexture))
|
|
1737
2138
|
try {
|
|
1738
|
-
const { extractGLBTexture:
|
|
1739
|
-
if (
|
|
1740
|
-
const
|
|
1741
|
-
await
|
|
2139
|
+
const { extractGLBTexture: u } = await Promise.resolve().then(() => ni), f = await u(l);
|
|
2140
|
+
if (f) {
|
|
2141
|
+
const h = await createImageBitmap(f.imageBlob);
|
|
2142
|
+
await a.setTexture(h), console.log(`GLB embedded texture restored for ${c.name}`);
|
|
1742
2143
|
}
|
|
1743
|
-
} catch (
|
|
1744
|
-
console.warn(`Failed to restore GLB texture for ${
|
|
2144
|
+
} catch (u) {
|
|
2145
|
+
console.warn(`Failed to restore GLB texture for ${c.name}:`, u), c.useGlbTexture = !1;
|
|
1745
2146
|
}
|
|
1746
2147
|
} else
|
|
1747
|
-
|
|
1748
|
-
} catch (
|
|
1749
|
-
console.warn(`Failed to load GLB for ${
|
|
2148
|
+
c.glbModelEnabled = !1;
|
|
2149
|
+
} catch (l) {
|
|
2150
|
+
console.warn(`Failed to load GLB for ${c.name}:`, l), c.glbModelEnabled = !1;
|
|
1750
2151
|
}
|
|
1751
|
-
for (const { system:
|
|
1752
|
-
if (
|
|
2152
|
+
for (const { system: a, config: c } of this.particleSystems)
|
|
2153
|
+
if (c.textureEnabled && !c.glbModelEnabled && c.textureImageData && !a._textureRestored)
|
|
1753
2154
|
try {
|
|
1754
|
-
const
|
|
1755
|
-
await new Promise((
|
|
1756
|
-
|
|
2155
|
+
const l = new Image();
|
|
2156
|
+
await new Promise((f, h) => {
|
|
2157
|
+
l.onload = f, l.onerror = h, l.src = c.textureImageData;
|
|
1757
2158
|
});
|
|
1758
|
-
const
|
|
1759
|
-
await
|
|
1760
|
-
} catch (
|
|
1761
|
-
console.warn(`Failed to restore texture for ${
|
|
2159
|
+
const u = await createImageBitmap(l);
|
|
2160
|
+
await a.setTexture(u), a._textureRestored = !0;
|
|
2161
|
+
} catch (l) {
|
|
2162
|
+
console.warn(`Failed to restore texture for ${c.name}:`, l), c.textureEnabled = !1;
|
|
1762
2163
|
}
|
|
1763
|
-
return
|
|
1764
|
-
} catch (
|
|
1765
|
-
return console.error("Error adding systems:",
|
|
2164
|
+
return i;
|
|
2165
|
+
} catch (n) {
|
|
2166
|
+
return console.error("Error adding systems:", n), !1;
|
|
2167
|
+
} finally {
|
|
2168
|
+
this.ready = !0;
|
|
1766
2169
|
}
|
|
1767
2170
|
}
|
|
1768
2171
|
}
|
|
1769
|
-
async function
|
|
1770
|
-
if (!
|
|
2172
|
+
async function Cs(r) {
|
|
2173
|
+
if (!r)
|
|
1771
2174
|
throw new Error("canvas is required for initWebGPU()");
|
|
1772
2175
|
if (!navigator.gpu)
|
|
1773
2176
|
throw new Error("WebGPU not supported on this browser.");
|
|
1774
|
-
const t =
|
|
2177
|
+
const t = r.getContext("webgpu"), i = await (await navigator.gpu.requestAdapter()).requestDevice(), s = navigator.gpu.getPreferredCanvasFormat();
|
|
1775
2178
|
return t.configure({
|
|
1776
2179
|
device: i,
|
|
1777
|
-
format:
|
|
2180
|
+
format: s,
|
|
1778
2181
|
alphaMode: "premultiplied"
|
|
1779
|
-
}), { device: i, context: t, format:
|
|
2182
|
+
}), { device: i, context: t, format: s, canvas: r };
|
|
1780
2183
|
}
|
|
1781
|
-
|
|
1782
|
-
|
|
2184
|
+
const le = "rgba16float";
|
|
2185
|
+
function ui(r, t, e, i) {
|
|
2186
|
+
const s = r.createTexture({
|
|
1783
2187
|
size: [e, i],
|
|
1784
|
-
format:
|
|
2188
|
+
format: le,
|
|
1785
2189
|
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
|
|
1786
2190
|
mipLevelCount: 1,
|
|
1787
2191
|
sampleCount: 1
|
|
1788
|
-
}),
|
|
2192
|
+
}), n = r.createTexture({
|
|
1789
2193
|
size: [e, i],
|
|
1790
|
-
format:
|
|
2194
|
+
format: le,
|
|
1791
2195
|
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
|
|
1792
2196
|
mipLevelCount: 1,
|
|
1793
2197
|
sampleCount: 1
|
|
1794
|
-
}),
|
|
2198
|
+
}), o = r.createTexture({
|
|
1795
2199
|
size: [e, i],
|
|
1796
|
-
format:
|
|
2200
|
+
format: le,
|
|
1797
2201
|
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
|
|
1798
2202
|
mipLevelCount: 1,
|
|
1799
2203
|
sampleCount: 1
|
|
1800
2204
|
});
|
|
1801
|
-
return { sceneTexture:
|
|
2205
|
+
return { sceneTexture: s, bloomTexA: n, bloomTexB: o };
|
|
1802
2206
|
}
|
|
1803
|
-
function
|
|
1804
|
-
return
|
|
2207
|
+
function di(r, t, e) {
|
|
2208
|
+
return r.createTexture({
|
|
1805
2209
|
size: [t, e],
|
|
1806
2210
|
format: "depth24plus",
|
|
1807
2211
|
usage: GPUTextureUsage.RENDER_ATTACHMENT
|
|
1808
2212
|
});
|
|
1809
2213
|
}
|
|
1810
|
-
function
|
|
1811
|
-
const i =
|
|
2214
|
+
function Ge(r, t, e) {
|
|
2215
|
+
const i = r.createBuffer({
|
|
1812
2216
|
size: t.byteLength,
|
|
1813
2217
|
usage: e,
|
|
1814
2218
|
mappedAtCreation: !0
|
|
1815
2219
|
});
|
|
1816
2220
|
return new t.constructor(i.getMappedRange()).set(t), i.unmap(), i;
|
|
1817
2221
|
}
|
|
1818
|
-
const
|
|
2222
|
+
const bi = `
|
|
1819
2223
|
struct Uniforms {
|
|
1820
2224
|
transform: mat4x4<f32>,
|
|
1821
2225
|
cameraPosition: vec3<f32>,
|
|
@@ -1860,6 +2264,14 @@ const j = `
|
|
|
1860
2264
|
simRotZ: f32, // simulation rotation Z (radians)
|
|
1861
2265
|
velocityStretchEnabled: f32, // 0=off, 1=on
|
|
1862
2266
|
velocityStretchFactor: f32, // multiplier for stretch (0-10)
|
|
2267
|
+
noiseDistortEnabled: f32, // 0=off, 1=on — UV distortion by scrolling noise (flames)
|
|
2268
|
+
noiseTilingX: f32, // noise tiling along U
|
|
2269
|
+
noiseTilingY: f32, // noise tiling along V
|
|
2270
|
+
noiseSpeed: f32, // vertical scroll speed (negative = noise rises, flame dances upward)
|
|
2271
|
+
noiseAmplitude: f32, // UV distortion amplitude
|
|
2272
|
+
systemVelX: f32, // emitter/system world velocity (for velocity-aligned rotation
|
|
2273
|
+
systemVelY: f32, // of trail particles that move WITH the emitter, e.g. a ball —
|
|
2274
|
+
systemVelZ: f32, // their local velocity is ~0 so they need the system velocity)
|
|
1863
2275
|
}
|
|
1864
2276
|
|
|
1865
2277
|
@binding(0) @group(0) var<uniform> uniforms : Uniforms;
|
|
@@ -1881,6 +2293,22 @@ const j = `
|
|
|
1881
2293
|
@location(0) color : vec3<f32>,
|
|
1882
2294
|
@location(1) alpha : f32,
|
|
1883
2295
|
@location(2) texCoord : vec2<f32>,
|
|
2296
|
+
@location(3) noiseOffset : vec2<f32>,
|
|
2297
|
+
}
|
|
2298
|
+
|
|
2299
|
+
fn hash21(p: vec2<f32>) -> f32 {
|
|
2300
|
+
return fract(sin(dot(p, vec2<f32>(127.1, 311.7))) * 43758.5453);
|
|
2301
|
+
}
|
|
2302
|
+
|
|
2303
|
+
fn valueNoise(p: vec2<f32>) -> f32 {
|
|
2304
|
+
let i = floor(p);
|
|
2305
|
+
let f = fract(p);
|
|
2306
|
+
let u = f * f * (3.0 - 2.0 * f);
|
|
2307
|
+
let a = hash21(i);
|
|
2308
|
+
let b = hash21(i + vec2<f32>(1.0, 0.0));
|
|
2309
|
+
let c = hash21(i + vec2<f32>(0.0, 1.0));
|
|
2310
|
+
let d = hash21(i + vec2<f32>(1.0, 1.0));
|
|
2311
|
+
return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
|
|
1884
2312
|
}
|
|
1885
2313
|
|
|
1886
2314
|
@vertex
|
|
@@ -1958,9 +2386,13 @@ const j = `
|
|
|
1958
2386
|
fract(sin(lifetime * 12345.67) * 43758.5453) *
|
|
1959
2387
|
(appearance.maxRotation - appearance.minRotation);
|
|
1960
2388
|
} else if (appearance.rotationMode == 2.0) {
|
|
1961
|
-
// Calculate rotation based on velocity direction in screen space
|
|
1962
|
-
//
|
|
1963
|
-
|
|
2389
|
+
// Calculate rotation based on velocity direction in screen space. Use the COMBINED velocity
|
|
2390
|
+
// (particle-local + system/emitter): a trail particle riding a moving emitter (e.g. the driven
|
|
2391
|
+
// ball) has ~0 local velocity, so without the system term it would never align to the motion
|
|
2392
|
+
// ("la particule ne suit jamais la direction de la vélocité"). Stays a camera-facing billboard,
|
|
2393
|
+
// just rotated to point along the movement.
|
|
2394
|
+
let combinedVel = input.particleVelocity + vec3<f32>(appearance.systemVelX, appearance.systemVelY, appearance.systemVelZ);
|
|
2395
|
+
let viewVelocity = (uniforms.transform * vec4<f32>(combinedVel, 0.0)).xyz;
|
|
1964
2396
|
|
|
1965
2397
|
// Calculate the angle from the transformed velocity
|
|
1966
2398
|
// We only care about the XY plane in screen space
|
|
@@ -2023,6 +2455,14 @@ const j = `
|
|
|
2023
2455
|
// Convert the quad position to texture coordinates (0,0 to 1,1)
|
|
2024
2456
|
output.texCoord = vec2<f32>(input.position.x + 0.5, -input.position.y + 0.5);
|
|
2025
2457
|
|
|
2458
|
+
// Per-particle phase (seeded from lifetime) desynchronizes flames sharing
|
|
2459
|
+
// the same system; y carries the vertical noise scroll over time.
|
|
2460
|
+
let noisePhase = fract(sin(lifetime * 76543.21) * 43758.5453) * 6.283185;
|
|
2461
|
+
output.noiseOffset = vec2<f32>(
|
|
2462
|
+
noisePhase,
|
|
2463
|
+
uniforms.elapsedTime * appearance.noiseSpeed + noisePhase
|
|
2464
|
+
);
|
|
2465
|
+
|
|
2026
2466
|
return output;
|
|
2027
2467
|
}
|
|
2028
2468
|
|
|
@@ -2139,13 +2579,27 @@ const j = `
|
|
|
2139
2579
|
}
|
|
2140
2580
|
|
|
2141
2581
|
if (appearance.textureEnabled > 0.5) {
|
|
2142
|
-
|
|
2582
|
+
var sampleUV = input.texCoord;
|
|
2583
|
+
if (appearance.noiseDistortEnabled > 0.5) {
|
|
2584
|
+
// Flame-style distortion: a scrolling noise field offsets the sample UV
|
|
2585
|
+
// (n = noise(uv×tiling + (phase, t×speed + phase)) − 0.5)
|
|
2586
|
+
let nUV = input.texCoord * vec2<f32>(appearance.noiseTilingX, appearance.noiseTilingY)
|
|
2587
|
+
+ input.noiseOffset;
|
|
2588
|
+
let n1 = valueNoise(nUV) - 0.5;
|
|
2589
|
+
let n2 = valueNoise(nUV + vec2<f32>(13.7, 7.3)) - 0.5;
|
|
2590
|
+
sampleUV = clamp(
|
|
2591
|
+
input.texCoord + vec2<f32>(n1, n2) * appearance.noiseAmplitude,
|
|
2592
|
+
vec2<f32>(0.001, 0.001),
|
|
2593
|
+
vec2<f32>(0.999, 0.999)
|
|
2594
|
+
);
|
|
2595
|
+
}
|
|
2596
|
+
let texColor = textureSample(particleTexture, particleSampler, sampleUV);
|
|
2143
2597
|
return vec4<f32>(input.color * texColor.rgb, alpha * texColor.a);
|
|
2144
2598
|
} else {
|
|
2145
2599
|
return vec4<f32>(input.color, alpha);
|
|
2146
2600
|
}
|
|
2147
2601
|
}
|
|
2148
|
-
`,
|
|
2602
|
+
`, Si = `
|
|
2149
2603
|
struct BloomUniforms {
|
|
2150
2604
|
direction: vec2<f32>,
|
|
2151
2605
|
resolution: vec2<f32>,
|
|
@@ -2205,7 +2659,7 @@ const j = `
|
|
|
2205
2659
|
|
|
2206
2660
|
return result / totalWeight * 1.1;
|
|
2207
2661
|
}
|
|
2208
|
-
`,
|
|
2662
|
+
`, xi = `
|
|
2209
2663
|
struct BloomIntensityUniforms {
|
|
2210
2664
|
intensity: f32,
|
|
2211
2665
|
color: vec3<f32>,
|
|
@@ -2251,7 +2705,7 @@ const j = `
|
|
|
2251
2705
|
|
|
2252
2706
|
return vec4<f32>(originalColor.rgb + (mappedBloom * bloomUniforms.intensity), originalColor.a);
|
|
2253
2707
|
}
|
|
2254
|
-
`,
|
|
2708
|
+
`, vi = `
|
|
2255
2709
|
struct BloomIntensityUniforms {
|
|
2256
2710
|
intensity: f32,
|
|
2257
2711
|
color: vec3<f32>,
|
|
@@ -2292,7 +2746,39 @@ const j = `
|
|
|
2292
2746
|
fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
2293
2747
|
return textureSample(originalTexture, texSampler, input.texCoord);
|
|
2294
2748
|
}
|
|
2295
|
-
`,
|
|
2749
|
+
`, Pi = `
|
|
2750
|
+
@binding(0) @group(0) var texSampler: sampler;
|
|
2751
|
+
@binding(1) @group(0) var originalTexture: texture_2d<f32>;
|
|
2752
|
+
@binding(2) @group(0) var blurredTexture: texture_2d<f32>;
|
|
2753
|
+
struct BloomIntensityUniforms { intensity: f32, color: vec3<f32> }
|
|
2754
|
+
@binding(3) @group(0) var<uniform> bloomUniforms: BloomIntensityUniforms;
|
|
2755
|
+
|
|
2756
|
+
struct VertexOutput {
|
|
2757
|
+
@builtin(position) position: vec4<f32>,
|
|
2758
|
+
@location(0) texCoord: vec2<f32>,
|
|
2759
|
+
}
|
|
2760
|
+
|
|
2761
|
+
@vertex
|
|
2762
|
+
fn vs_main(@builtin(vertex_index) vertexIndex: u32) -> VertexOutput {
|
|
2763
|
+
var output: VertexOutput;
|
|
2764
|
+
let positions = array<vec2<f32>, 3>(vec2<f32>(-1.0, -1.0), vec2<f32>(3.0, -1.0), vec2<f32>(-1.0, 3.0));
|
|
2765
|
+
let texCoords = array<vec2<f32>, 3>(vec2<f32>(0.0, 1.0), vec2<f32>(2.0, 1.0), vec2<f32>(0.0, -1.0));
|
|
2766
|
+
output.position = vec4<f32>(positions[vertexIndex], 0.0, 1.0);
|
|
2767
|
+
output.texCoord = texCoords[vertexIndex];
|
|
2768
|
+
return output;
|
|
2769
|
+
}
|
|
2770
|
+
|
|
2771
|
+
fn aces(x: vec3<f32>) -> vec3<f32> {
|
|
2772
|
+
let a = 2.51; let b = 0.03; let c = 2.43; let d = 0.59; let e = 0.14;
|
|
2773
|
+
return clamp((x * (a * x + b)) / (x * (c * x + d) + e), vec3<f32>(0.0), vec3<f32>(1.0));
|
|
2774
|
+
}
|
|
2775
|
+
|
|
2776
|
+
@fragment
|
|
2777
|
+
fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
2778
|
+
let c = textureSample(originalTexture, texSampler, input.texCoord);
|
|
2779
|
+
return vec4<f32>(aces(c.rgb), c.a);
|
|
2780
|
+
}
|
|
2781
|
+
`, As = `
|
|
2296
2782
|
struct PhysicsUniforms {
|
|
2297
2783
|
deltaTime: f32,
|
|
2298
2784
|
particleSpeed: f32,
|
|
@@ -2502,7 +2988,7 @@ const j = `
|
|
|
2502
2988
|
particleBuffer[baseIndex + 1u] = newPos.y;
|
|
2503
2989
|
particleBuffer[baseIndex + 2u] = newPos.z;
|
|
2504
2990
|
}
|
|
2505
|
-
`,
|
|
2991
|
+
`, Us = `
|
|
2506
2992
|
@group(0) @binding(0) var<storage, read> restData: array<f32>;
|
|
2507
2993
|
@group(0) @binding(1) var<storage, read> jointWeightsData: array<f32>;
|
|
2508
2994
|
@group(0) @binding(2) var<storage, read> jointIndicesData: array<u32>;
|
|
@@ -2558,15 +3044,16 @@ const j = `
|
|
|
2558
3044
|
outputData[outBase + 6u] = uv_u;
|
|
2559
3045
|
outputData[outBase + 7u] = uv_v;
|
|
2560
3046
|
}
|
|
2561
|
-
`,
|
|
3047
|
+
`, _i = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2562
3048
|
__proto__: null,
|
|
2563
|
-
blurShader:
|
|
2564
|
-
compositeShader:
|
|
2565
|
-
directRenderShader:
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
3049
|
+
blurShader: Si,
|
|
3050
|
+
compositeShader: xi,
|
|
3051
|
+
directRenderShader: vi,
|
|
3052
|
+
finalCompositeShader: Pi,
|
|
3053
|
+
particlePhysicsShader: As,
|
|
3054
|
+
particleShader: bi,
|
|
3055
|
+
skinningComputeShader: Us
|
|
3056
|
+
}, Symbol.toStringTag, { value: "Module" })), Is = `
|
|
2570
3057
|
struct Uniforms {
|
|
2571
3058
|
transform: mat4x4<f32>,
|
|
2572
3059
|
cameraPosition: vec3<f32>,
|
|
@@ -2628,7 +3115,7 @@ const j = `
|
|
|
2628
3115
|
|
|
2629
3116
|
return finalColor;
|
|
2630
3117
|
}
|
|
2631
|
-
`,
|
|
3118
|
+
`, Gs = `
|
|
2632
3119
|
struct Uniforms {
|
|
2633
3120
|
transform: mat4x4<f32>,
|
|
2634
3121
|
cameraPosition: vec3<f32>,
|
|
@@ -2713,9 +3200,14 @@ const j = `
|
|
|
2713
3200
|
|
|
2714
3201
|
// Determine particle color
|
|
2715
3202
|
var finalColor = input.particleColor;
|
|
2716
|
-
if (appearance.colorTransitionEnabled >
|
|
3203
|
+
if (appearance.colorTransitionEnabled > 1.5) {
|
|
3204
|
+
// Random color mode: use per-particle color from instance data
|
|
3205
|
+
finalColor = input.particleColor;
|
|
3206
|
+
} else if (appearance.colorTransitionEnabled > 0.5) {
|
|
3207
|
+
// Color transition mode: interpolate from start to end color over lifetime
|
|
2717
3208
|
finalColor = mix(appearance.startColor, appearance.endColor, lifeRatio);
|
|
2718
3209
|
} else {
|
|
3210
|
+
// Single color mode
|
|
2719
3211
|
finalColor = appearance.singleColor;
|
|
2720
3212
|
}
|
|
2721
3213
|
|
|
@@ -2859,8 +3351,8 @@ const j = `
|
|
|
2859
3351
|
return finalColor;
|
|
2860
3352
|
}
|
|
2861
3353
|
`;
|
|
2862
|
-
function
|
|
2863
|
-
const t =
|
|
3354
|
+
function Ds(r) {
|
|
3355
|
+
const t = r.createBindGroupLayout({
|
|
2864
3356
|
entries: [
|
|
2865
3357
|
{
|
|
2866
3358
|
binding: 0,
|
|
@@ -2883,7 +3375,7 @@ function Se(c) {
|
|
|
2883
3375
|
sampler: {}
|
|
2884
3376
|
}
|
|
2885
3377
|
]
|
|
2886
|
-
}), e =
|
|
3378
|
+
}), e = r.createBindGroupLayout({
|
|
2887
3379
|
entries: [
|
|
2888
3380
|
{
|
|
2889
3381
|
binding: 0,
|
|
@@ -2901,7 +3393,7 @@ function Se(c) {
|
|
|
2901
3393
|
buffer: { type: "uniform" }
|
|
2902
3394
|
}
|
|
2903
3395
|
]
|
|
2904
|
-
}), i =
|
|
3396
|
+
}), i = r.createBindGroupLayout({
|
|
2905
3397
|
entries: [
|
|
2906
3398
|
{
|
|
2907
3399
|
binding: 0,
|
|
@@ -2924,7 +3416,7 @@ function Se(c) {
|
|
|
2924
3416
|
buffer: { type: "uniform" }
|
|
2925
3417
|
}
|
|
2926
3418
|
]
|
|
2927
|
-
}),
|
|
3419
|
+
}), s = r.createBindGroupLayout({
|
|
2928
3420
|
entries: [
|
|
2929
3421
|
{
|
|
2930
3422
|
binding: 0,
|
|
@@ -2942,37 +3434,37 @@ function Se(c) {
|
|
|
2942
3434
|
particleBindGroupLayout: t,
|
|
2943
3435
|
bloomBindGroupLayout: e,
|
|
2944
3436
|
compositeBindGroupLayout: i,
|
|
2945
|
-
object3dBindGroupLayout:
|
|
3437
|
+
object3dBindGroupLayout: s
|
|
2946
3438
|
};
|
|
2947
3439
|
}
|
|
2948
|
-
function
|
|
2949
|
-
const { depthCompare:
|
|
2950
|
-
particleBindGroupLayout:
|
|
2951
|
-
bloomBindGroupLayout:
|
|
2952
|
-
compositeBindGroupLayout:
|
|
3440
|
+
function zs(r, t, e, i = {}) {
|
|
3441
|
+
const { depthCompare: s } = i, n = s || "less", {
|
|
3442
|
+
particleBindGroupLayout: o,
|
|
3443
|
+
bloomBindGroupLayout: a,
|
|
3444
|
+
compositeBindGroupLayout: c,
|
|
2953
3445
|
object3dBindGroupLayout: l
|
|
2954
|
-
} = e, u =
|
|
2955
|
-
bindGroupLayouts: [n]
|
|
2956
|
-
}), d = c.createPipelineLayout({
|
|
3446
|
+
} = e, u = r.createPipelineLayout({
|
|
2957
3447
|
bindGroupLayouts: [o]
|
|
2958
|
-
}), f =
|
|
2959
|
-
bindGroupLayouts: [
|
|
2960
|
-
}), h =
|
|
2961
|
-
|
|
2962
|
-
}),
|
|
2963
|
-
code:
|
|
2964
|
-
}),
|
|
2965
|
-
code:
|
|
2966
|
-
}),
|
|
2967
|
-
code:
|
|
2968
|
-
}),
|
|
2969
|
-
code:
|
|
2970
|
-
}),
|
|
2971
|
-
code:
|
|
2972
|
-
}),
|
|
3448
|
+
}), f = r.createPipelineLayout({
|
|
3449
|
+
bindGroupLayouts: [a]
|
|
3450
|
+
}), h = r.createPipelineLayout({
|
|
3451
|
+
bindGroupLayouts: [c]
|
|
3452
|
+
}), m = r.createShaderModule({
|
|
3453
|
+
code: bi
|
|
3454
|
+
}), S = r.createShaderModule({
|
|
3455
|
+
code: Si
|
|
3456
|
+
}), R = r.createShaderModule({
|
|
3457
|
+
code: xi
|
|
3458
|
+
}), D = r.createShaderModule({
|
|
3459
|
+
code: vi
|
|
3460
|
+
}), C = r.createShaderModule({
|
|
3461
|
+
code: Is
|
|
3462
|
+
}), B = r.createShaderModule({
|
|
3463
|
+
code: Gs
|
|
3464
|
+
}), A = (at) => r.createRenderPipeline({
|
|
2973
3465
|
layout: u,
|
|
2974
3466
|
vertex: {
|
|
2975
|
-
module:
|
|
3467
|
+
module: m,
|
|
2976
3468
|
entryPoint: "vs_main",
|
|
2977
3469
|
buffers: [
|
|
2978
3470
|
{
|
|
@@ -3033,22 +3525,11 @@ function xe(c, t, e, i = {}) {
|
|
|
3033
3525
|
]
|
|
3034
3526
|
},
|
|
3035
3527
|
fragment: {
|
|
3036
|
-
module:
|
|
3528
|
+
module: m,
|
|
3037
3529
|
entryPoint: "fs_main",
|
|
3038
3530
|
targets: [{
|
|
3039
|
-
format:
|
|
3040
|
-
blend:
|
|
3041
|
-
color: {
|
|
3042
|
-
srcFactor: "src-alpha",
|
|
3043
|
-
dstFactor: "one-minus-src-alpha",
|
|
3044
|
-
operation: "add"
|
|
3045
|
-
},
|
|
3046
|
-
alpha: {
|
|
3047
|
-
srcFactor: "one",
|
|
3048
|
-
dstFactor: "one-minus-src-alpha",
|
|
3049
|
-
operation: "add"
|
|
3050
|
-
}
|
|
3051
|
-
}
|
|
3531
|
+
format: le,
|
|
3532
|
+
blend: at
|
|
3052
3533
|
}]
|
|
3053
3534
|
},
|
|
3054
3535
|
primitive: {
|
|
@@ -3057,13 +3538,35 @@ function xe(c, t, e, i = {}) {
|
|
|
3057
3538
|
},
|
|
3058
3539
|
depthStencil: {
|
|
3059
3540
|
depthWriteEnabled: !1,
|
|
3060
|
-
depthCompare:
|
|
3541
|
+
depthCompare: n,
|
|
3061
3542
|
format: "depth24plus"
|
|
3062
3543
|
}
|
|
3063
|
-
}),
|
|
3544
|
+
}), P = A({
|
|
3545
|
+
color: {
|
|
3546
|
+
srcFactor: "src-alpha",
|
|
3547
|
+
dstFactor: "one-minus-src-alpha",
|
|
3548
|
+
operation: "add"
|
|
3549
|
+
},
|
|
3550
|
+
alpha: {
|
|
3551
|
+
srcFactor: "one",
|
|
3552
|
+
dstFactor: "one-minus-src-alpha",
|
|
3553
|
+
operation: "add"
|
|
3554
|
+
}
|
|
3555
|
+
}), _ = A({
|
|
3556
|
+
color: {
|
|
3557
|
+
srcFactor: "src-alpha",
|
|
3558
|
+
dstFactor: "one",
|
|
3559
|
+
operation: "add"
|
|
3560
|
+
},
|
|
3561
|
+
alpha: {
|
|
3562
|
+
srcFactor: "one",
|
|
3563
|
+
dstFactor: "one-minus-src-alpha",
|
|
3564
|
+
operation: "add"
|
|
3565
|
+
}
|
|
3566
|
+
}), T = r.createRenderPipeline({
|
|
3064
3567
|
layout: u,
|
|
3065
3568
|
vertex: {
|
|
3066
|
-
module:
|
|
3569
|
+
module: m,
|
|
3067
3570
|
entryPoint: "vs_main",
|
|
3068
3571
|
buffers: [
|
|
3069
3572
|
{
|
|
@@ -3124,10 +3627,10 @@ function xe(c, t, e, i = {}) {
|
|
|
3124
3627
|
]
|
|
3125
3628
|
},
|
|
3126
3629
|
fragment: {
|
|
3127
|
-
module:
|
|
3630
|
+
module: m,
|
|
3128
3631
|
entryPoint: "fs_main",
|
|
3129
3632
|
targets: [{
|
|
3130
|
-
format:
|
|
3633
|
+
format: le,
|
|
3131
3634
|
writeMask: 0
|
|
3132
3635
|
// No color write — depth only
|
|
3133
3636
|
}]
|
|
@@ -3142,33 +3645,33 @@ function xe(c, t, e, i = {}) {
|
|
|
3142
3645
|
// Always write depth (don't self-occlude)
|
|
3143
3646
|
format: "depth24plus"
|
|
3144
3647
|
}
|
|
3145
|
-
}),
|
|
3146
|
-
layout:
|
|
3648
|
+
}), L = r.createRenderPipeline({
|
|
3649
|
+
layout: f,
|
|
3147
3650
|
vertex: {
|
|
3148
|
-
module:
|
|
3651
|
+
module: S,
|
|
3149
3652
|
entryPoint: "vs_main"
|
|
3150
3653
|
},
|
|
3151
3654
|
fragment: {
|
|
3152
|
-
module:
|
|
3655
|
+
module: S,
|
|
3153
3656
|
entryPoint: "fs_main",
|
|
3154
3657
|
targets: [{
|
|
3155
|
-
format:
|
|
3658
|
+
format: le
|
|
3156
3659
|
}]
|
|
3157
3660
|
},
|
|
3158
3661
|
primitive: {
|
|
3159
3662
|
topology: "triangle-list"
|
|
3160
3663
|
}
|
|
3161
|
-
}),
|
|
3162
|
-
layout:
|
|
3664
|
+
}), N = r.createRenderPipeline({
|
|
3665
|
+
layout: h,
|
|
3163
3666
|
vertex: {
|
|
3164
|
-
module:
|
|
3667
|
+
module: R,
|
|
3165
3668
|
entryPoint: "vs_main"
|
|
3166
3669
|
},
|
|
3167
3670
|
fragment: {
|
|
3168
|
-
module:
|
|
3671
|
+
module: R,
|
|
3169
3672
|
entryPoint: "fs_main",
|
|
3170
3673
|
targets: [{
|
|
3171
|
-
format:
|
|
3674
|
+
format: le,
|
|
3172
3675
|
blend: {
|
|
3173
3676
|
color: {
|
|
3174
3677
|
srcFactor: "one",
|
|
@@ -3186,17 +3689,17 @@ function xe(c, t, e, i = {}) {
|
|
|
3186
3689
|
primitive: {
|
|
3187
3690
|
topology: "triangle-list"
|
|
3188
3691
|
}
|
|
3189
|
-
}),
|
|
3190
|
-
layout:
|
|
3692
|
+
}), k = r.createRenderPipeline({
|
|
3693
|
+
layout: h,
|
|
3191
3694
|
vertex: {
|
|
3192
|
-
module:
|
|
3695
|
+
module: D,
|
|
3193
3696
|
entryPoint: "vs_main"
|
|
3194
3697
|
},
|
|
3195
3698
|
fragment: {
|
|
3196
|
-
module:
|
|
3699
|
+
module: D,
|
|
3197
3700
|
entryPoint: "fs_main",
|
|
3198
3701
|
targets: [{
|
|
3199
|
-
format:
|
|
3702
|
+
format: le,
|
|
3200
3703
|
blend: {
|
|
3201
3704
|
color: {
|
|
3202
3705
|
srcFactor: "one",
|
|
@@ -3214,12 +3717,27 @@ function xe(c, t, e, i = {}) {
|
|
|
3214
3717
|
primitive: {
|
|
3215
3718
|
topology: "triangle-list"
|
|
3216
3719
|
}
|
|
3217
|
-
}),
|
|
3720
|
+
}), X = r.createShaderModule({ code: Pi }), z = r.createRenderPipeline({
|
|
3721
|
+
layout: h,
|
|
3722
|
+
vertex: { module: X, entryPoint: "vs_main" },
|
|
3723
|
+
fragment: {
|
|
3724
|
+
module: X,
|
|
3725
|
+
entryPoint: "fs_main",
|
|
3726
|
+
targets: [{
|
|
3727
|
+
format: t,
|
|
3728
|
+
blend: {
|
|
3729
|
+
color: { srcFactor: "one", dstFactor: "one-minus-src-alpha", operation: "add" },
|
|
3730
|
+
alpha: { srcFactor: "one", dstFactor: "one-minus-src-alpha", operation: "add" }
|
|
3731
|
+
}
|
|
3732
|
+
}]
|
|
3733
|
+
},
|
|
3734
|
+
primitive: { topology: "triangle-list" }
|
|
3735
|
+
}), me = r.createPipelineLayout({
|
|
3218
3736
|
bindGroupLayouts: [l]
|
|
3219
|
-
}),
|
|
3220
|
-
layout:
|
|
3737
|
+
}), De = r.createRenderPipeline({
|
|
3738
|
+
layout: me,
|
|
3221
3739
|
vertex: {
|
|
3222
|
-
module:
|
|
3740
|
+
module: C,
|
|
3223
3741
|
entryPoint: "vs_main",
|
|
3224
3742
|
buffers: [
|
|
3225
3743
|
{
|
|
@@ -3244,10 +3762,10 @@ function xe(c, t, e, i = {}) {
|
|
|
3244
3762
|
]
|
|
3245
3763
|
},
|
|
3246
3764
|
fragment: {
|
|
3247
|
-
module:
|
|
3765
|
+
module: C,
|
|
3248
3766
|
entryPoint: "fs_main",
|
|
3249
3767
|
targets: [{
|
|
3250
|
-
format:
|
|
3768
|
+
format: le,
|
|
3251
3769
|
blend: {
|
|
3252
3770
|
color: {
|
|
3253
3771
|
srcFactor: "src-alpha",
|
|
@@ -3268,13 +3786,13 @@ function xe(c, t, e, i = {}) {
|
|
|
3268
3786
|
},
|
|
3269
3787
|
depthStencil: {
|
|
3270
3788
|
depthWriteEnabled: !0,
|
|
3271
|
-
depthCompare:
|
|
3789
|
+
depthCompare: n,
|
|
3272
3790
|
format: "depth24plus"
|
|
3273
3791
|
}
|
|
3274
|
-
}),
|
|
3792
|
+
}), ze = r.createRenderPipeline({
|
|
3275
3793
|
layout: u,
|
|
3276
3794
|
vertex: {
|
|
3277
|
-
module:
|
|
3795
|
+
module: B,
|
|
3278
3796
|
entryPoint: "vs_main",
|
|
3279
3797
|
buffers: [
|
|
3280
3798
|
{
|
|
@@ -3346,10 +3864,10 @@ function xe(c, t, e, i = {}) {
|
|
|
3346
3864
|
]
|
|
3347
3865
|
},
|
|
3348
3866
|
fragment: {
|
|
3349
|
-
module:
|
|
3867
|
+
module: B,
|
|
3350
3868
|
entryPoint: "fs_main",
|
|
3351
3869
|
targets: [{
|
|
3352
|
-
format:
|
|
3870
|
+
format: le,
|
|
3353
3871
|
blend: {
|
|
3354
3872
|
color: {
|
|
3355
3873
|
srcFactor: "src-alpha",
|
|
@@ -3370,33 +3888,35 @@ function xe(c, t, e, i = {}) {
|
|
|
3370
3888
|
},
|
|
3371
3889
|
depthStencil: {
|
|
3372
3890
|
depthWriteEnabled: !0,
|
|
3373
|
-
depthCompare:
|
|
3891
|
+
depthCompare: n,
|
|
3374
3892
|
format: "depth24plus"
|
|
3375
3893
|
}
|
|
3376
3894
|
});
|
|
3377
3895
|
return {
|
|
3378
3896
|
particlePipeline: P,
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3897
|
+
particleAdditivePipeline: _,
|
|
3898
|
+
particleDepthWritePipeline: T,
|
|
3899
|
+
blurPipeline: L,
|
|
3900
|
+
compositePipeline: N,
|
|
3901
|
+
directRenderPipeline: k,
|
|
3902
|
+
finalCompositePipeline: z,
|
|
3903
|
+
object3dPipeline: De,
|
|
3904
|
+
glbMeshPipeline: ze
|
|
3385
3905
|
};
|
|
3386
3906
|
}
|
|
3387
|
-
function
|
|
3907
|
+
function St(r, t, e, i) {
|
|
3388
3908
|
const {
|
|
3389
|
-
uniformBuffer:
|
|
3390
|
-
appearanceUniformBuffer:
|
|
3391
|
-
horizontalBlurUniformBuffer:
|
|
3392
|
-
verticalBlurUniformBuffer:
|
|
3393
|
-
bloomIntensityBuffer:
|
|
3909
|
+
uniformBuffer: s,
|
|
3910
|
+
appearanceUniformBuffer: n,
|
|
3911
|
+
horizontalBlurUniformBuffer: o,
|
|
3912
|
+
verticalBlurUniformBuffer: a,
|
|
3913
|
+
bloomIntensityBuffer: c
|
|
3394
3914
|
} = e, {
|
|
3395
3915
|
sceneTexture: l,
|
|
3396
3916
|
bloomTexA: u,
|
|
3397
|
-
bloomTexB:
|
|
3398
|
-
} = i,
|
|
3399
|
-
layout:
|
|
3917
|
+
bloomTexB: f
|
|
3918
|
+
} = i, h = r.createBindGroup({
|
|
3919
|
+
layout: r.createBindGroupLayout({
|
|
3400
3920
|
entries: [
|
|
3401
3921
|
{
|
|
3402
3922
|
binding: 0,
|
|
@@ -3413,15 +3933,15 @@ function ve(c, t, e, i) {
|
|
|
3413
3933
|
entries: [
|
|
3414
3934
|
{
|
|
3415
3935
|
binding: 0,
|
|
3416
|
-
resource: { buffer:
|
|
3936
|
+
resource: { buffer: s }
|
|
3417
3937
|
},
|
|
3418
3938
|
{
|
|
3419
3939
|
binding: 1,
|
|
3420
|
-
resource: { buffer:
|
|
3940
|
+
resource: { buffer: n }
|
|
3421
3941
|
}
|
|
3422
3942
|
]
|
|
3423
|
-
}),
|
|
3424
|
-
layout:
|
|
3943
|
+
}), m = r.createBindGroup({
|
|
3944
|
+
layout: r.createBindGroupLayout({
|
|
3425
3945
|
entries: [
|
|
3426
3946
|
{
|
|
3427
3947
|
binding: 0,
|
|
@@ -3451,11 +3971,11 @@ function ve(c, t, e, i) {
|
|
|
3451
3971
|
},
|
|
3452
3972
|
{
|
|
3453
3973
|
binding: 2,
|
|
3454
|
-
resource: { buffer:
|
|
3974
|
+
resource: { buffer: o }
|
|
3455
3975
|
}
|
|
3456
3976
|
]
|
|
3457
|
-
}),
|
|
3458
|
-
layout:
|
|
3977
|
+
}), S = r.createBindGroup({
|
|
3978
|
+
layout: r.createBindGroupLayout({
|
|
3459
3979
|
entries: [
|
|
3460
3980
|
{
|
|
3461
3981
|
binding: 0,
|
|
@@ -3485,11 +4005,11 @@ function ve(c, t, e, i) {
|
|
|
3485
4005
|
},
|
|
3486
4006
|
{
|
|
3487
4007
|
binding: 2,
|
|
3488
|
-
resource: { buffer:
|
|
4008
|
+
resource: { buffer: a }
|
|
3489
4009
|
}
|
|
3490
4010
|
]
|
|
3491
|
-
}),
|
|
3492
|
-
layout:
|
|
4011
|
+
}), R = r.createBindGroup({
|
|
4012
|
+
layout: r.createBindGroupLayout({
|
|
3493
4013
|
entries: [
|
|
3494
4014
|
{
|
|
3495
4015
|
binding: 0,
|
|
@@ -3524,15 +4044,15 @@ function ve(c, t, e, i) {
|
|
|
3524
4044
|
},
|
|
3525
4045
|
{
|
|
3526
4046
|
binding: 2,
|
|
3527
|
-
resource:
|
|
4047
|
+
resource: f.createView()
|
|
3528
4048
|
},
|
|
3529
4049
|
{
|
|
3530
4050
|
binding: 3,
|
|
3531
|
-
resource: { buffer:
|
|
4051
|
+
resource: { buffer: c }
|
|
3532
4052
|
}
|
|
3533
4053
|
]
|
|
3534
|
-
}),
|
|
3535
|
-
layout:
|
|
4054
|
+
}), D = r.createBindGroup({
|
|
4055
|
+
layout: r.createBindGroupLayout({
|
|
3536
4056
|
entries: [
|
|
3537
4057
|
{
|
|
3538
4058
|
binding: 0,
|
|
@@ -3567,24 +4087,24 @@ function ve(c, t, e, i) {
|
|
|
3567
4087
|
},
|
|
3568
4088
|
{
|
|
3569
4089
|
binding: 2,
|
|
3570
|
-
resource:
|
|
4090
|
+
resource: f.createView()
|
|
3571
4091
|
},
|
|
3572
4092
|
{
|
|
3573
4093
|
binding: 3,
|
|
3574
|
-
resource: { buffer:
|
|
4094
|
+
resource: { buffer: c }
|
|
3575
4095
|
}
|
|
3576
4096
|
]
|
|
3577
4097
|
});
|
|
3578
4098
|
return {
|
|
3579
|
-
particleBindGroup:
|
|
3580
|
-
horizontalBlurBindGroup:
|
|
3581
|
-
verticalBlurBindGroup:
|
|
3582
|
-
compositeBindGroup:
|
|
3583
|
-
directRenderBindGroup:
|
|
4099
|
+
particleBindGroup: h,
|
|
4100
|
+
horizontalBlurBindGroup: m,
|
|
4101
|
+
verticalBlurBindGroup: S,
|
|
4102
|
+
compositeBindGroup: R,
|
|
4103
|
+
directRenderBindGroup: D
|
|
3584
4104
|
};
|
|
3585
4105
|
}
|
|
3586
|
-
function
|
|
3587
|
-
return
|
|
4106
|
+
function Vs(r) {
|
|
4107
|
+
return r.createSampler({
|
|
3588
4108
|
magFilter: "linear",
|
|
3589
4109
|
minFilter: "linear",
|
|
3590
4110
|
mipmapFilter: "linear",
|
|
@@ -3593,8 +4113,8 @@ function Pe(c) {
|
|
|
3593
4113
|
maxAnisotropy: 16
|
|
3594
4114
|
});
|
|
3595
4115
|
}
|
|
3596
|
-
function
|
|
3597
|
-
const
|
|
4116
|
+
function Fs() {
|
|
4117
|
+
const r = new Float32Array([
|
|
3598
4118
|
// Front face (z = 0.5)
|
|
3599
4119
|
-0.5,
|
|
3600
4120
|
-0.5,
|
|
@@ -3789,38 +4309,38 @@ function de() {
|
|
|
3789
4309
|
23
|
|
3790
4310
|
// left
|
|
3791
4311
|
]);
|
|
3792
|
-
return { vertices:
|
|
4312
|
+
return { vertices: r, indices: t };
|
|
3793
4313
|
}
|
|
3794
|
-
function
|
|
4314
|
+
function Os(r = 16, t = 16) {
|
|
3795
4315
|
const e = [], i = [];
|
|
3796
|
-
for (let
|
|
3797
|
-
const
|
|
3798
|
-
for (let
|
|
3799
|
-
const l =
|
|
3800
|
-
e.push(
|
|
4316
|
+
for (let s = 0; s <= r; s++) {
|
|
4317
|
+
const n = s * Math.PI / r, o = Math.sin(n), a = Math.cos(n);
|
|
4318
|
+
for (let c = 0; c <= t; c++) {
|
|
4319
|
+
const l = c * 2 * Math.PI / t, u = Math.sin(l), h = Math.cos(l) * o, m = a, S = u * o;
|
|
4320
|
+
e.push(h * 0.5, m * 0.5, S * 0.5), e.push(h, m, S);
|
|
3801
4321
|
}
|
|
3802
4322
|
}
|
|
3803
|
-
for (let
|
|
3804
|
-
for (let
|
|
3805
|
-
const
|
|
3806
|
-
i.push(
|
|
4323
|
+
for (let s = 0; s < r; s++)
|
|
4324
|
+
for (let n = 0; n < t; n++) {
|
|
4325
|
+
const o = s * (t + 1) + n, a = o + t + 1;
|
|
4326
|
+
i.push(o), i.push(a), i.push(o + 1), i.push(a), i.push(a + 1), i.push(o + 1);
|
|
3807
4327
|
}
|
|
3808
4328
|
return {
|
|
3809
4329
|
vertices: new Float32Array(e),
|
|
3810
4330
|
indices: new Uint16Array(i)
|
|
3811
4331
|
};
|
|
3812
4332
|
}
|
|
3813
|
-
class
|
|
3814
|
-
constructor(t, e, i,
|
|
3815
|
-
this.id = t, this.type = e, this.position = i, this.scale =
|
|
4333
|
+
class Ls {
|
|
4334
|
+
constructor(t, e, i, s, n) {
|
|
4335
|
+
this.id = t, this.type = e, this.position = i, this.scale = s, this.color = n, this.rotation = [0, 0, 0];
|
|
3816
4336
|
}
|
|
3817
4337
|
/**
|
|
3818
4338
|
* Get the model matrix for this object
|
|
3819
4339
|
*/
|
|
3820
4340
|
getModelMatrix() {
|
|
3821
|
-
const { position: t, scale: e, rotation: i } = this,
|
|
3822
|
-
let l =
|
|
3823
|
-
return l = this.multiplyMatrices(l,
|
|
4341
|
+
const { position: t, scale: e, rotation: i } = this, s = this.createTranslationMatrix(t), n = this.createRotationMatrixX(i[0]), o = this.createRotationMatrixY(i[1]), a = this.createRotationMatrixZ(i[2]), c = this.createScaleMatrix(e);
|
|
4342
|
+
let l = s;
|
|
4343
|
+
return l = this.multiplyMatrices(l, a), l = this.multiplyMatrices(l, o), l = this.multiplyMatrices(l, n), l = this.multiplyMatrices(l, c), l;
|
|
3824
4344
|
}
|
|
3825
4345
|
/**
|
|
3826
4346
|
* Get the normal matrix (inverse transpose of model matrix)
|
|
@@ -3934,17 +4454,17 @@ class he {
|
|
|
3934
4454
|
}
|
|
3935
4455
|
multiplyMatrices(t, e) {
|
|
3936
4456
|
const i = new Float32Array(16);
|
|
3937
|
-
for (let
|
|
3938
|
-
for (let
|
|
3939
|
-
let
|
|
3940
|
-
for (let
|
|
3941
|
-
|
|
3942
|
-
i[
|
|
4457
|
+
for (let s = 0; s < 4; s++)
|
|
4458
|
+
for (let n = 0; n < 4; n++) {
|
|
4459
|
+
let o = 0;
|
|
4460
|
+
for (let a = 0; a < 4; a++)
|
|
4461
|
+
o += t[s * 4 + a] * e[a * 4 + n];
|
|
4462
|
+
i[s * 4 + n] = o;
|
|
3943
4463
|
}
|
|
3944
4464
|
return i;
|
|
3945
4465
|
}
|
|
3946
4466
|
}
|
|
3947
|
-
class
|
|
4467
|
+
class Zs {
|
|
3948
4468
|
constructor(t) {
|
|
3949
4469
|
this.device = t, this.objects = [], this.nextId = 0, this.initializeGeometry(), this.onObjectAdded = null, this.onObjectRemoved = null, this.onObjectUpdated = null;
|
|
3950
4470
|
}
|
|
@@ -3952,20 +4472,20 @@ class Me {
|
|
|
3952
4472
|
* Initialize geometry buffers for cube and sphere
|
|
3953
4473
|
*/
|
|
3954
4474
|
initializeGeometry() {
|
|
3955
|
-
const t =
|
|
3956
|
-
this.cubeVertexBuffer =
|
|
4475
|
+
const t = Fs(), e = Os(16, 16);
|
|
4476
|
+
this.cubeVertexBuffer = Ge(
|
|
3957
4477
|
this.device,
|
|
3958
4478
|
t.vertices,
|
|
3959
4479
|
GPUBufferUsage.VERTEX
|
|
3960
|
-
), this.cubeIndexBuffer =
|
|
4480
|
+
), this.cubeIndexBuffer = Ge(
|
|
3961
4481
|
this.device,
|
|
3962
4482
|
t.indices,
|
|
3963
4483
|
GPUBufferUsage.INDEX
|
|
3964
|
-
), this.cubeIndexCount = t.indices.length, this.sphereVertexBuffer =
|
|
4484
|
+
), this.cubeIndexCount = t.indices.length, this.sphereVertexBuffer = Ge(
|
|
3965
4485
|
this.device,
|
|
3966
4486
|
e.vertices,
|
|
3967
4487
|
GPUBufferUsage.VERTEX
|
|
3968
|
-
), this.sphereIndexBuffer =
|
|
4488
|
+
), this.sphereIndexBuffer = Ge(
|
|
3969
4489
|
this.device,
|
|
3970
4490
|
e.indices,
|
|
3971
4491
|
GPUBufferUsage.INDEX
|
|
@@ -3979,13 +4499,13 @@ class Me {
|
|
|
3979
4499
|
* @param {Array} color - [r, g, b, a] (optional, defaults to white)
|
|
3980
4500
|
* @returns {Object3D} The created object
|
|
3981
4501
|
*/
|
|
3982
|
-
addObject(t, e = [0, 0, 0], i = [1, 1, 1],
|
|
3983
|
-
const
|
|
3984
|
-
return
|
|
4502
|
+
addObject(t, e = [0, 0, 0], i = [1, 1, 1], s = [1, 1, 1, 1]) {
|
|
4503
|
+
const n = new Ls(this.nextId++, t, e, i, s);
|
|
4504
|
+
return n.uniformBuffer = this.device.createBuffer({
|
|
3985
4505
|
size: 192,
|
|
3986
4506
|
// modelMatrix (64) + normalMatrix (64) + color (16) + padding (48)
|
|
3987
4507
|
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
3988
|
-
}), this.objects.push(
|
|
4508
|
+
}), this.objects.push(n), this.onObjectAdded && this.onObjectAdded(n), n;
|
|
3989
4509
|
}
|
|
3990
4510
|
/**
|
|
3991
4511
|
* Remove an object by ID
|
|
@@ -4001,7 +4521,7 @@ class Me {
|
|
|
4001
4521
|
* @param {Array} position - [x, y, z]
|
|
4002
4522
|
*/
|
|
4003
4523
|
updateObjectPosition(t, e) {
|
|
4004
|
-
const i = this.objects.find((
|
|
4524
|
+
const i = this.objects.find((s) => s.id === t);
|
|
4005
4525
|
i && (i.position = e, this.onObjectUpdated && this.onObjectUpdated(i));
|
|
4006
4526
|
}
|
|
4007
4527
|
/**
|
|
@@ -4010,7 +4530,7 @@ class Me {
|
|
|
4010
4530
|
* @param {Array} scale - [sx, sy, sz]
|
|
4011
4531
|
*/
|
|
4012
4532
|
updateObjectScale(t, e) {
|
|
4013
|
-
const i = this.objects.find((
|
|
4533
|
+
const i = this.objects.find((s) => s.id === t);
|
|
4014
4534
|
i && (i.scale = e, this.onObjectUpdated && this.onObjectUpdated(i));
|
|
4015
4535
|
}
|
|
4016
4536
|
/**
|
|
@@ -4019,7 +4539,7 @@ class Me {
|
|
|
4019
4539
|
* @param {Array} color - [r, g, b, a]
|
|
4020
4540
|
*/
|
|
4021
4541
|
updateObjectColor(t, e) {
|
|
4022
|
-
const i = this.objects.find((
|
|
4542
|
+
const i = this.objects.find((s) => s.id === t);
|
|
4023
4543
|
i && (i.color = e, this.onObjectUpdated && this.onObjectUpdated(i));
|
|
4024
4544
|
}
|
|
4025
4545
|
/**
|
|
@@ -4040,78 +4560,78 @@ class Me {
|
|
|
4040
4560
|
* @param {Object3D} object
|
|
4041
4561
|
*/
|
|
4042
4562
|
updateObjectUniforms(t) {
|
|
4043
|
-
const e = t.getModelMatrix(), i = t.getNormalMatrix(),
|
|
4044
|
-
this.device.queue.writeBuffer(t.uniformBuffer, 0, e), this.device.queue.writeBuffer(t.uniformBuffer, 64, i), this.device.queue.writeBuffer(t.uniformBuffer, 128,
|
|
4563
|
+
const e = t.getModelMatrix(), i = t.getNormalMatrix(), s = new Float32Array(t.color);
|
|
4564
|
+
this.device.queue.writeBuffer(t.uniformBuffer, 0, e), this.device.queue.writeBuffer(t.uniformBuffer, 64, i), this.device.queue.writeBuffer(t.uniformBuffer, 128, s);
|
|
4045
4565
|
}
|
|
4046
4566
|
/**
|
|
4047
4567
|
* Render all objects
|
|
4048
4568
|
* @param {GPURenderPassEncoder} passEncoder
|
|
4049
4569
|
* @param {GPUBindGroup} cameraBindGroup - Bind group with camera uniforms
|
|
4050
4570
|
*/
|
|
4051
|
-
renderObjects(t, e, i,
|
|
4052
|
-
for (const
|
|
4053
|
-
this.updateObjectUniforms(
|
|
4054
|
-
const
|
|
4571
|
+
renderObjects(t, e, i, s) {
|
|
4572
|
+
for (const n of this.objects) {
|
|
4573
|
+
this.updateObjectUniforms(n);
|
|
4574
|
+
const o = this.device.createBindGroup({
|
|
4055
4575
|
layout: i,
|
|
4056
4576
|
entries: [
|
|
4057
|
-
{ binding: 0, resource: { buffer:
|
|
4058
|
-
{ binding: 1, resource: { buffer:
|
|
4577
|
+
{ binding: 0, resource: { buffer: s } },
|
|
4578
|
+
{ binding: 1, resource: { buffer: n.uniformBuffer } }
|
|
4059
4579
|
]
|
|
4060
4580
|
});
|
|
4061
|
-
let
|
|
4062
|
-
if (
|
|
4063
|
-
|
|
4064
|
-
else if (
|
|
4065
|
-
|
|
4581
|
+
let a, c, l;
|
|
4582
|
+
if (n.type === "cube")
|
|
4583
|
+
a = this.cubeVertexBuffer, c = this.cubeIndexBuffer, l = this.cubeIndexCount;
|
|
4584
|
+
else if (n.type === "sphere")
|
|
4585
|
+
a = this.sphereVertexBuffer, c = this.sphereIndexBuffer, l = this.sphereIndexCount;
|
|
4066
4586
|
else
|
|
4067
4587
|
continue;
|
|
4068
|
-
t.setPipeline(e), t.setBindGroup(0,
|
|
4588
|
+
t.setPipeline(e), t.setBindGroup(0, o), t.setVertexBuffer(0, a), t.setIndexBuffer(c, "uint16"), t.drawIndexed(l);
|
|
4069
4589
|
}
|
|
4070
4590
|
}
|
|
4071
4591
|
}
|
|
4072
|
-
function
|
|
4073
|
-
const t = parseInt(
|
|
4592
|
+
function $s(r) {
|
|
4593
|
+
const t = parseInt(r.slice(1, 3), 16) / 255, e = parseInt(r.slice(3, 5), 16) / 255, i = parseInt(r.slice(5, 7), 16) / 255;
|
|
4074
4594
|
return [t, e, i];
|
|
4075
4595
|
}
|
|
4076
|
-
function
|
|
4077
|
-
if (!
|
|
4078
|
-
const t = Math.round(
|
|
4596
|
+
function Ws(r) {
|
|
4597
|
+
if (!r) return "#ffffff";
|
|
4598
|
+
const t = Math.round(r[0] * 255).toString(16).padStart(2, "0"), e = Math.round(r[1] * 255).toString(16).padStart(2, "0"), i = Math.round(r[2] * 255).toString(16).padStart(2, "0");
|
|
4079
4599
|
return `#${t}${e}${i}`;
|
|
4080
4600
|
}
|
|
4081
|
-
function
|
|
4082
|
-
const i =
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
]),
|
|
4601
|
+
function Js(r, t, e) {
|
|
4602
|
+
const i = fi([
|
|
4603
|
+
r[0] - t[0],
|
|
4604
|
+
r[1] - t[1],
|
|
4605
|
+
r[2] - t[2]
|
|
4606
|
+
]), s = fi(pi(e, i)), n = pi(i, s);
|
|
4087
4607
|
return new Float32Array([
|
|
4088
|
-
|
|
4089
|
-
|
|
4608
|
+
s[0],
|
|
4609
|
+
n[0],
|
|
4090
4610
|
i[0],
|
|
4091
4611
|
0,
|
|
4092
|
-
|
|
4093
|
-
|
|
4612
|
+
s[1],
|
|
4613
|
+
n[1],
|
|
4094
4614
|
i[1],
|
|
4095
4615
|
0,
|
|
4096
|
-
|
|
4097
|
-
|
|
4616
|
+
s[2],
|
|
4617
|
+
n[2],
|
|
4098
4618
|
i[2],
|
|
4099
4619
|
0,
|
|
4100
|
-
-
|
|
4101
|
-
-
|
|
4102
|
-
-
|
|
4620
|
+
-xt(s, r),
|
|
4621
|
+
-xt(n, r),
|
|
4622
|
+
-xt(i, r),
|
|
4103
4623
|
1
|
|
4104
4624
|
]);
|
|
4105
4625
|
}
|
|
4106
|
-
function
|
|
4107
|
-
const
|
|
4626
|
+
function Ks(r, t = Math.PI / 4) {
|
|
4627
|
+
const s = 1 / Math.tan(t / 2);
|
|
4108
4628
|
return new Float32Array([
|
|
4109
|
-
|
|
4629
|
+
s * r,
|
|
4110
4630
|
0,
|
|
4111
4631
|
0,
|
|
4112
4632
|
0,
|
|
4113
4633
|
0,
|
|
4114
|
-
|
|
4634
|
+
s,
|
|
4115
4635
|
0,
|
|
4116
4636
|
0,
|
|
4117
4637
|
0,
|
|
@@ -4124,264 +4644,1032 @@ function Te(c, t = Math.PI / 4) {
|
|
|
4124
4644
|
0
|
|
4125
4645
|
]);
|
|
4126
4646
|
}
|
|
4127
|
-
function
|
|
4128
|
-
const t = Math.sqrt(
|
|
4129
|
-
return [
|
|
4647
|
+
function fi(r) {
|
|
4648
|
+
const t = Math.sqrt(r[0] * r[0] + r[1] * r[1] + r[2] * r[2]);
|
|
4649
|
+
return [r[0] / t, r[1] / t, r[2] / t];
|
|
4130
4650
|
}
|
|
4131
|
-
function
|
|
4651
|
+
function pi(r, t) {
|
|
4132
4652
|
return [
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4653
|
+
r[1] * t[2] - r[2] * t[1],
|
|
4654
|
+
r[2] * t[0] - r[0] * t[2],
|
|
4655
|
+
r[0] * t[1] - r[1] * t[0]
|
|
4136
4656
|
];
|
|
4137
4657
|
}
|
|
4138
|
-
function
|
|
4139
|
-
return
|
|
4658
|
+
function xt(r, t) {
|
|
4659
|
+
return r[0] * t[0] + r[1] * t[1] + r[2] * t[2];
|
|
4140
4660
|
}
|
|
4141
|
-
function
|
|
4661
|
+
function Ns(r, t) {
|
|
4142
4662
|
const e = new Float32Array(16);
|
|
4143
4663
|
for (let i = 0; i < 4; i++)
|
|
4144
|
-
for (let
|
|
4145
|
-
let
|
|
4146
|
-
for (let
|
|
4147
|
-
|
|
4148
|
-
e[i +
|
|
4664
|
+
for (let s = 0; s < 4; s++) {
|
|
4665
|
+
let n = 0;
|
|
4666
|
+
for (let o = 0; o < 4; o++)
|
|
4667
|
+
n += r[i + o * 4] * t[o + s * 4];
|
|
4668
|
+
e[i + s * 4] = n;
|
|
4149
4669
|
}
|
|
4150
4670
|
return e;
|
|
4151
4671
|
}
|
|
4152
|
-
function
|
|
4153
|
-
|
|
4672
|
+
const Pt = 1481005640, wi = 1, Bi = 1313821514, Ri = 5130562, He = "$hzfxAsset", Mi = (r) => typeof atob == "function" ? Uint8Array.from(atob(r), (t) => t.charCodeAt(0)) : new Uint8Array(Buffer.from(r, "base64")), hi = (r) => {
|
|
4673
|
+
if (typeof btoa == "function") {
|
|
4674
|
+
let t = "";
|
|
4675
|
+
for (let e = 0; e < r.length; e++) t += String.fromCharCode(r[e]);
|
|
4676
|
+
return btoa(t);
|
|
4677
|
+
}
|
|
4678
|
+
return Buffer.from(r).toString("base64");
|
|
4679
|
+
};
|
|
4680
|
+
function Xs(r) {
|
|
4681
|
+
const t = r.indexOf(","), e = r.slice(5, t), i = e.split(";")[0] || "application/octet-stream", s = r.slice(t + 1), o = /;base64/i.test(e) ? Mi(s) : new TextEncoder().encode(decodeURIComponent(s));
|
|
4682
|
+
return { mime: i, bytes: o };
|
|
4683
|
+
}
|
|
4684
|
+
function mi(r) {
|
|
4685
|
+
return (4 - r % 4) % 4;
|
|
4686
|
+
}
|
|
4687
|
+
async function ks(r, t = {}) {
|
|
4688
|
+
const { textureFormat: e = "keep", quality: i = 0.85 } = t, s = [], n = [];
|
|
4689
|
+
let o = 0;
|
|
4690
|
+
const a = (_, T, L) => {
|
|
4691
|
+
const N = o, k = _.length;
|
|
4692
|
+
s.push({ offset: N, length: k, mime: T, kind: L }), n.push(_), o += k;
|
|
4693
|
+
const X = mi(k);
|
|
4694
|
+
return X && (n.push(new Uint8Array(X)), o += X), s.length - 1;
|
|
4695
|
+
}, c = e === "webp" && typeof OffscreenCanvas < "u" && typeof createImageBitmap == "function", l = [];
|
|
4696
|
+
for (const _ of r.systems || []) {
|
|
4697
|
+
const T = { ..._ };
|
|
4698
|
+
if (typeof T.textureImageData == "string" && T.textureImageData.startsWith("data:")) {
|
|
4699
|
+
let { mime: L, bytes: N } = Xs(T.textureImageData);
|
|
4700
|
+
if (c && L !== "image/webp")
|
|
4701
|
+
try {
|
|
4702
|
+
const k = await createImageBitmap(new Blob([N], { type: L })), X = new OffscreenCanvas(k.width, k.height);
|
|
4703
|
+
X.getContext("2d").drawImage(k, 0, 0);
|
|
4704
|
+
const z = await X.convertToBlob({ type: "image/webp", quality: i }), me = new Uint8Array(await z.arrayBuffer());
|
|
4705
|
+
me.length < N.length && (N = me, L = "image/webp");
|
|
4706
|
+
} catch {
|
|
4707
|
+
}
|
|
4708
|
+
T.textureImageData = { [He]: a(N, L, "texture") };
|
|
4709
|
+
}
|
|
4710
|
+
if (typeof T.glbModelData == "string" && T.glbModelData.length > 0) {
|
|
4711
|
+
const L = Mi(T.glbModelData);
|
|
4712
|
+
T.glbModelData = { [He]: a(L, "model/gltf-binary", "glb") };
|
|
4713
|
+
}
|
|
4714
|
+
l.push(T);
|
|
4715
|
+
}
|
|
4716
|
+
const u = { ...r, systems: l, assets: s }, f = new TextEncoder().encode(JSON.stringify(u)), h = mi(f.length), m = new Uint8Array(o);
|
|
4717
|
+
let S = 0;
|
|
4718
|
+
for (const _ of n)
|
|
4719
|
+
m.set(_, S), S += _.length;
|
|
4720
|
+
const R = f.length + h, D = 20 + R + 8 + o, C = new ArrayBuffer(D), B = new DataView(C), A = new Uint8Array(C);
|
|
4721
|
+
let P = 0;
|
|
4722
|
+
B.setUint32(P, Pt, !0), P += 4, B.setUint32(P, wi, !0), P += 4, B.setUint32(P, D, !0), P += 4, B.setUint32(P, R, !0), P += 4, B.setUint32(P, Bi, !0), P += 4, A.set(f, P), P += f.length;
|
|
4723
|
+
for (let _ = 0; _ < h; _++) A[P++] = 32;
|
|
4724
|
+
return B.setUint32(P, o, !0), P += 4, B.setUint32(P, Ri, !0), P += 4, A.set(m, P), P += o, C;
|
|
4725
|
+
}
|
|
4726
|
+
function Ti(r) {
|
|
4727
|
+
return !r || r.byteLength < 12 ? !1 : new DataView(r).getUint32(0, !0) === Pt;
|
|
4728
|
+
}
|
|
4729
|
+
function Ei(r) {
|
|
4730
|
+
const t = new DataView(r);
|
|
4731
|
+
if (t.getUint32(0, !0) !== Pt) throw new Error("[unpackHZFX] bad magic — not an .hzfx file");
|
|
4732
|
+
const e = t.getUint32(4, !0);
|
|
4733
|
+
if (e !== wi) throw new Error(`[unpackHZFX] unsupported version ${e}`);
|
|
4734
|
+
let i = 12, s = null, n = -1;
|
|
4735
|
+
const o = new Uint8Array(r);
|
|
4736
|
+
for (; i + 8 <= r.byteLength; ) {
|
|
4737
|
+
const h = t.getUint32(i, !0);
|
|
4738
|
+
i += 4;
|
|
4739
|
+
const m = t.getUint32(i, !0);
|
|
4740
|
+
i += 4, m === Bi ? s = JSON.parse(new TextDecoder().decode(o.subarray(i, i + h))) : m === Ri && (n = i), i += h;
|
|
4741
|
+
}
|
|
4742
|
+
if (!s) throw new Error("[unpackHZFX] missing JSON chunk");
|
|
4743
|
+
const a = s.assets || [], c = (h) => {
|
|
4744
|
+
const m = a[h];
|
|
4745
|
+
return !m || n < 0 ? null : { ...m, bytes: o.subarray(n + m.offset, n + m.offset + m.length) };
|
|
4746
|
+
}, l = (h) => h && typeof h == "object" && typeof h[He] == "number", u = (s.systems || []).map((h) => {
|
|
4747
|
+
const m = { ...h };
|
|
4748
|
+
if (l(m.textureImageData)) {
|
|
4749
|
+
const S = c(m.textureImageData[He]);
|
|
4750
|
+
m.textureImageData = S ? `data:${S.mime};base64,${hi(S.bytes)}` : void 0;
|
|
4751
|
+
}
|
|
4752
|
+
if (l(m.glbModelData)) {
|
|
4753
|
+
const S = c(m.glbModelData[He]);
|
|
4754
|
+
m.glbModelData = S ? hi(S.bytes) : void 0;
|
|
4755
|
+
}
|
|
4756
|
+
return m;
|
|
4757
|
+
}), f = { ...s, systems: u };
|
|
4758
|
+
return delete f.assets, f;
|
|
4759
|
+
}
|
|
4760
|
+
function js(r) {
|
|
4761
|
+
const t = new Uint8Array(r);
|
|
4154
4762
|
let e = "";
|
|
4155
4763
|
for (let i = 0; i < t.byteLength; i++)
|
|
4156
4764
|
e += String.fromCharCode(t[i]);
|
|
4157
4765
|
return btoa(e);
|
|
4158
4766
|
}
|
|
4159
|
-
function
|
|
4160
|
-
|
|
4767
|
+
function Ys(r) {
|
|
4768
|
+
return {
|
|
4769
|
+
name: r.name,
|
|
4770
|
+
id: r.id,
|
|
4771
|
+
particleCount: r.particleCount,
|
|
4772
|
+
lifetime: r.lifetime,
|
|
4773
|
+
emissionRate: r.emissionRate,
|
|
4774
|
+
emissionDuration: r.emissionDuration,
|
|
4775
|
+
emissionDurationInfinite: r.emissionDurationInfinite || !1,
|
|
4776
|
+
particleSize: r.particleSize,
|
|
4777
|
+
particleSpeed: r.particleSpeed,
|
|
4778
|
+
emissionShape: r.emissionShape,
|
|
4779
|
+
outerLength: r.outerLength ?? r.cubeLength,
|
|
4780
|
+
// cubeLength = legacy alias; migrate to outerLength
|
|
4781
|
+
innerLength: r.innerLength,
|
|
4782
|
+
outerRadius: r.outerRadius,
|
|
4783
|
+
innerRadius: r.innerRadius,
|
|
4784
|
+
squareSize: r.squareSize,
|
|
4785
|
+
squareInnerSize: r.squareInnerSize,
|
|
4786
|
+
circleInnerRadius: r.circleInnerRadius,
|
|
4787
|
+
circleOuterRadius: r.circleOuterRadius,
|
|
4788
|
+
fadeEnabled: r.fadeEnabled,
|
|
4789
|
+
colorTransitionEnabled: r.colorTransitionEnabled,
|
|
4790
|
+
particleColor: r.particleColor,
|
|
4791
|
+
startColor: r.startColor,
|
|
4792
|
+
endColor: r.endColor,
|
|
4793
|
+
randomColorEnabled: r.randomColorEnabled || !1,
|
|
4794
|
+
randomColors: r.randomColors || [],
|
|
4795
|
+
particleShape: r.particleShape || "square",
|
|
4796
|
+
particleShapeRotationX: r.particleShapeRotationX || 0,
|
|
4797
|
+
particleShapeRotationY: r.particleShapeRotationY || 0,
|
|
4798
|
+
particleShapeRotationZ: r.particleShapeRotationZ || 0,
|
|
4799
|
+
pulseEnabled: r.pulseEnabled || !1,
|
|
4800
|
+
pulseAmplitude: r.pulseAmplitude ?? 0.5,
|
|
4801
|
+
pulseFrequency: r.pulseFrequency ?? 1,
|
|
4802
|
+
pulsePhaseRandom: r.pulsePhaseRandom ?? 0,
|
|
4803
|
+
pulseOpacity: r.pulseOpacity || !1,
|
|
4804
|
+
bloomEnabled: r.bloomEnabled,
|
|
4805
|
+
bloomIntensity: r.bloomIntensity,
|
|
4806
|
+
bloomColor: r.bloomColor,
|
|
4807
|
+
depthWriteEnabled: r.depthWriteEnabled || !1,
|
|
4808
|
+
burstMode: r.burstMode,
|
|
4809
|
+
gravityEnabled: r.gravityEnabled,
|
|
4810
|
+
gravityStrength: r.gravityStrength,
|
|
4811
|
+
dampingEnabled: r.dampingEnabled,
|
|
4812
|
+
dampingStrength: r.dampingStrength,
|
|
4813
|
+
attractorEnabled: r.attractorEnabled,
|
|
4814
|
+
attractorStrength: r.attractorStrength,
|
|
4815
|
+
attractorPosition: r.attractorPosition,
|
|
4816
|
+
emissionRotationX: r.emissionRotationX,
|
|
4817
|
+
emissionRotationY: r.emissionRotationY,
|
|
4818
|
+
emissionRotationZ: r.emissionRotationZ,
|
|
4819
|
+
orientToDirection: r.orientToDirection ?? !1,
|
|
4820
|
+
emissionPositionX: r.emissionPositionX,
|
|
4821
|
+
emissionPositionY: r.emissionPositionY,
|
|
4822
|
+
emissionPositionZ: r.emissionPositionZ,
|
|
4823
|
+
rotation: r.rotation,
|
|
4824
|
+
rotationMode: r.rotationMode,
|
|
4825
|
+
minRotation: r.minRotation,
|
|
4826
|
+
maxRotation: r.maxRotation,
|
|
4827
|
+
overrideXVelocity: r.overrideXVelocity,
|
|
4828
|
+
overrideYVelocity: r.overrideYVelocity,
|
|
4829
|
+
overrideZVelocity: r.overrideZVelocity,
|
|
4830
|
+
xVelocity: r.xVelocity,
|
|
4831
|
+
yVelocity: r.yVelocity,
|
|
4832
|
+
zVelocity: r.zVelocity,
|
|
4833
|
+
circleVelocityDirection: r.circleVelocityDirection,
|
|
4834
|
+
cylinderVelocityDirection: r.cylinderVelocityDirection,
|
|
4835
|
+
cylinderInnerRadius: r.cylinderInnerRadius,
|
|
4836
|
+
cylinderOuterRadius: r.cylinderOuterRadius,
|
|
4837
|
+
cylinderHeight: r.cylinderHeight,
|
|
4838
|
+
planeWidth: r.planeWidth,
|
|
4839
|
+
planeDepth: r.planeDepth,
|
|
4840
|
+
rectangleWidth: r.rectangleWidth,
|
|
4841
|
+
rectangleHeight: r.rectangleHeight,
|
|
4842
|
+
coneOuterRadius: r.coneOuterRadius,
|
|
4843
|
+
coneInnerRadius: r.coneInnerRadius,
|
|
4844
|
+
coneHeight: r.coneHeight,
|
|
4845
|
+
torusMajorRadius: r.torusMajorRadius,
|
|
4846
|
+
torusMinorRadius: r.torusMinorRadius,
|
|
4847
|
+
lineLength: r.lineLength,
|
|
4848
|
+
hemisphereOuterRadius: r.hemisphereOuterRadius,
|
|
4849
|
+
hemisphereInnerRadius: r.hemisphereInnerRadius,
|
|
4850
|
+
discRadius: r.discRadius,
|
|
4851
|
+
annulusInnerRadius: r.annulusInnerRadius,
|
|
4852
|
+
annulusOuterRadius: r.annulusOuterRadius,
|
|
4853
|
+
capsuleRadius: r.capsuleRadius,
|
|
4854
|
+
capsuleHeight: r.capsuleHeight,
|
|
4855
|
+
arcStartAngle: r.arcStartAngle,
|
|
4856
|
+
arcEndAngle: r.arcEndAngle,
|
|
4857
|
+
arcInnerRadius: r.arcInnerRadius,
|
|
4858
|
+
arcOuterRadius: r.arcOuterRadius,
|
|
4859
|
+
spiralTurns: r.spiralTurns,
|
|
4860
|
+
spiralRadiusStart: r.spiralRadiusStart,
|
|
4861
|
+
spiralRadiusEnd: r.spiralRadiusEnd,
|
|
4862
|
+
spiralHeight: r.spiralHeight,
|
|
4863
|
+
frustumRadiusNear: r.frustumRadiusNear,
|
|
4864
|
+
frustumRadiusFar: r.frustumRadiusFar,
|
|
4865
|
+
frustumHeight: r.frustumHeight,
|
|
4866
|
+
cubeSurfaceSize: r.cubeSurfaceSize,
|
|
4867
|
+
sphereSurfaceRadius: r.sphereSurfaceRadius,
|
|
4868
|
+
boxFrameSize: r.boxFrameSize,
|
|
4869
|
+
polygonSides: r.polygonSides,
|
|
4870
|
+
polygonRadius: r.polygonRadius,
|
|
4871
|
+
aspectRatio: r.aspectRatio,
|
|
4872
|
+
randomSize: r.randomSize,
|
|
4873
|
+
minSize: r.minSize,
|
|
4874
|
+
maxSize: r.maxSize,
|
|
4875
|
+
fadeSizeEnabled: r.fadeSizeEnabled,
|
|
4876
|
+
increaseSizeEnabled: r.increaseSizeEnabled,
|
|
4877
|
+
sizeLifetimeSpeed: r.sizeLifetimeSpeed,
|
|
4878
|
+
opacity: r.opacity,
|
|
4879
|
+
randomSpeed: r.randomSpeed,
|
|
4880
|
+
minSpeed: r.minSpeed,
|
|
4881
|
+
maxSpeed: r.maxSpeed,
|
|
4882
|
+
oneOnlyMode: r.oneOnlyMode,
|
|
4883
|
+
confinementEnabled: r.confinementEnabled || !1,
|
|
4884
|
+
confinementShape: r.confinementShape || "box",
|
|
4885
|
+
confinementMode: r.confinementMode || "bounce",
|
|
4886
|
+
confinementSpace: r.confinementSpace || "world",
|
|
4887
|
+
confinementBoxHalfSize: r.confinementBoxHalfSize || [2, 2, 2],
|
|
4888
|
+
confinementSphereRadius: r.confinementSphereRadius ?? 3,
|
|
4889
|
+
confinementRestitution: r.confinementRestitution ?? 0.8,
|
|
4890
|
+
confinementFriction: r.confinementFriction ?? 0.1,
|
|
4891
|
+
confinementCenter: r.confinementCenter,
|
|
4892
|
+
softBoundaryEnabled: r.softBoundaryEnabled || !1,
|
|
4893
|
+
softBoundaryStrength: r.softBoundaryStrength ?? 5,
|
|
4894
|
+
softBoundaryFalloff: r.softBoundaryFalloff ?? 0.5,
|
|
4895
|
+
followSystemId: r.followSystemId || null,
|
|
4896
|
+
followSystemTranslation: r.followSystemTranslation ?? !0,
|
|
4897
|
+
hidden: r.hidden || !1,
|
|
4898
|
+
emissionTrailEnabled: r.emissionTrailEnabled || !1,
|
|
4899
|
+
emissionTrailDuration: r.emissionTrailDuration ?? 1,
|
|
4900
|
+
emissionTrailWidth: r.emissionTrailWidth ?? 0.5,
|
|
4901
|
+
emissionTrailMinDistance: r.emissionTrailMinDistance ?? 0.05,
|
|
4902
|
+
emissionTrailMaxPoints: r.emissionTrailMaxPoints ?? 100,
|
|
4903
|
+
emissionTrailSegments: r.emissionTrailSegments ?? 8,
|
|
4904
|
+
emissionTrailMode: r.emissionTrailMode ?? "ribbon",
|
|
4905
|
+
emissionTrailShape: r.emissionTrailShape ?? "straight",
|
|
4906
|
+
emissionTrailShapeAmplitude: r.emissionTrailShapeAmplitude ?? 0.1,
|
|
4907
|
+
emissionTrailShapeFrequency: r.emissionTrailShapeFrequency ?? 4,
|
|
4908
|
+
emissionTrailShapeSpeed: r.emissionTrailShapeSpeed ?? 0,
|
|
4909
|
+
shapeDisplay: r.shapeDisplay ?? !0,
|
|
4910
|
+
blendMode: r.blendMode ?? "normal",
|
|
4911
|
+
noiseDistortEnabled: r.noiseDistortEnabled || !1,
|
|
4912
|
+
noiseTilingX: r.noiseTilingX ?? 3,
|
|
4913
|
+
noiseTilingY: r.noiseTilingY ?? 3,
|
|
4914
|
+
noiseSpeed: r.noiseSpeed ?? -1.5,
|
|
4915
|
+
noiseAmplitude: r.noiseAmplitude ?? 0.08,
|
|
4916
|
+
velocityStretchEnabled: r.velocityStretchEnabled || !1,
|
|
4917
|
+
velocityStretchFactor: r.velocityStretchFactor ?? 1,
|
|
4918
|
+
// Texture / GLB metadata (the binary payloads — textureImageData / glbModelData — are
|
|
4919
|
+
// added by the caller since their encoding differs per export target)
|
|
4920
|
+
textureEnabled: r.textureEnabled || !1,
|
|
4921
|
+
textureType: r.textureType,
|
|
4922
|
+
textureFileName: r.textureFileName,
|
|
4923
|
+
imageDescription: r.imageDescription,
|
|
4924
|
+
glbModelEnabled: r.glbModelEnabled || !1,
|
|
4925
|
+
glbFileName: r.glbFileName,
|
|
4926
|
+
glbHasTexture: r.glbHasTexture || !1,
|
|
4927
|
+
useGlbTexture: r.useGlbTexture || !1,
|
|
4928
|
+
glbAnimated: r.glbAnimated || !1,
|
|
4929
|
+
animationIndex: r.animationIndex,
|
|
4930
|
+
animationSpeed: r.animationSpeed,
|
|
4931
|
+
animationLoop: r.animationLoop,
|
|
4932
|
+
glbDescription: r.glbDescription,
|
|
4933
|
+
script: r.script || void 0,
|
|
4934
|
+
displayUnit: r.displayUnit || "m"
|
|
4935
|
+
};
|
|
4936
|
+
}
|
|
4937
|
+
async function Qs(r, t, e = "hzfx") {
|
|
4938
|
+
if (!r || !r.particleSystems || r.particleSystems.length === 0) {
|
|
4161
4939
|
alert("No particle systems to save.");
|
|
4162
4940
|
return;
|
|
4163
4941
|
}
|
|
4164
4942
|
try {
|
|
4165
|
-
const
|
|
4943
|
+
const i = {
|
|
4166
4944
|
version: "1.0",
|
|
4167
4945
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4168
|
-
systems:
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
emissionRate: s.emissionRate,
|
|
4175
|
-
emissionDuration: s.emissionDuration,
|
|
4176
|
-
particleSize: s.particleSize,
|
|
4177
|
-
particleSpeed: s.particleSpeed,
|
|
4178
|
-
emissionShape: s.emissionShape,
|
|
4179
|
-
cubeLength: s.outerLength || s.cubeLength,
|
|
4180
|
-
// Always use outerLength if available
|
|
4181
|
-
outerLength: s.outerLength || s.cubeLength,
|
|
4182
|
-
// Keep them synchronized
|
|
4183
|
-
innerLength: s.innerLength,
|
|
4184
|
-
outerRadius: s.outerRadius,
|
|
4185
|
-
innerRadius: s.innerRadius,
|
|
4186
|
-
squareSize: s.squareSize,
|
|
4187
|
-
squareInnerSize: s.squareInnerSize,
|
|
4188
|
-
circleInnerRadius: s.circleInnerRadius,
|
|
4189
|
-
circleOuterRadius: s.circleOuterRadius,
|
|
4190
|
-
fadeEnabled: s.fadeEnabled,
|
|
4191
|
-
colorTransitionEnabled: s.colorTransitionEnabled,
|
|
4192
|
-
particleColor: s.particleColor,
|
|
4193
|
-
startColor: s.startColor,
|
|
4194
|
-
endColor: s.endColor,
|
|
4195
|
-
randomColorEnabled: s.randomColorEnabled || !1,
|
|
4196
|
-
randomColors: s.randomColors || [],
|
|
4197
|
-
particleShape: s.particleShape || "square",
|
|
4198
|
-
particleShapeRotation: s.particleShapeRotation || 0,
|
|
4199
|
-
particleShapeRotationX: s.particleShapeRotationX || 0,
|
|
4200
|
-
particleShapeRotationY: s.particleShapeRotationY || 0,
|
|
4201
|
-
particleShapeRotationZ: s.particleShapeRotationZ || 0,
|
|
4202
|
-
pulseEnabled: s.pulseEnabled || !1,
|
|
4203
|
-
pulseAmplitude: s.pulseAmplitude ?? 0.5,
|
|
4204
|
-
pulseFrequency: s.pulseFrequency ?? 1,
|
|
4205
|
-
pulsePhaseRandom: s.pulsePhaseRandom ?? 0,
|
|
4206
|
-
pulseOpacity: s.pulseOpacity || !1,
|
|
4207
|
-
bloomEnabled: s.bloomEnabled,
|
|
4208
|
-
bloomIntensity: s.bloomIntensity,
|
|
4209
|
-
burstMode: s.burstMode,
|
|
4210
|
-
gravityEnabled: s.gravityEnabled,
|
|
4211
|
-
gravityStrength: s.gravityStrength,
|
|
4212
|
-
dampingEnabled: s.dampingEnabled,
|
|
4213
|
-
dampingStrength: s.dampingStrength,
|
|
4214
|
-
attractorEnabled: s.attractorEnabled,
|
|
4215
|
-
attractorStrength: s.attractorStrength,
|
|
4216
|
-
attractorPosition: s.attractorPosition,
|
|
4217
|
-
shapeRotationX: s.shapeRotationX,
|
|
4218
|
-
shapeRotationY: s.shapeRotationY,
|
|
4219
|
-
shapeRotationZ: s.shapeRotationZ,
|
|
4220
|
-
shapeTranslationX: s.shapeTranslationX,
|
|
4221
|
-
shapeTranslationY: s.shapeTranslationY,
|
|
4222
|
-
shapeTranslationZ: s.shapeTranslationZ,
|
|
4223
|
-
rotation: s.rotation,
|
|
4224
|
-
rotationMode: s.rotationMode,
|
|
4225
|
-
minRotation: s.minRotation,
|
|
4226
|
-
maxRotation: s.maxRotation,
|
|
4227
|
-
overrideXVelocity: s.overrideXVelocity,
|
|
4228
|
-
overrideYVelocity: s.overrideYVelocity,
|
|
4229
|
-
overrideZVelocity: s.overrideZVelocity,
|
|
4230
|
-
xVelocity: s.xVelocity,
|
|
4231
|
-
yVelocity: s.yVelocity,
|
|
4232
|
-
zVelocity: s.zVelocity,
|
|
4233
|
-
circleVelocityDirection: s.circleVelocityDirection,
|
|
4234
|
-
cylinderVelocityDirection: s.cylinderVelocityDirection,
|
|
4235
|
-
cylinderInnerRadius: s.cylinderInnerRadius,
|
|
4236
|
-
cylinderOuterRadius: s.cylinderOuterRadius,
|
|
4237
|
-
cylinderHeight: s.cylinderHeight,
|
|
4238
|
-
aspectRatio: s.aspectRatio,
|
|
4239
|
-
randomSize: s.randomSize,
|
|
4240
|
-
minSize: s.minSize,
|
|
4241
|
-
maxSize: s.maxSize,
|
|
4242
|
-
fadeSizeEnabled: s.fadeSizeEnabled,
|
|
4243
|
-
increaseSizeEnabled: s.increaseSizeEnabled,
|
|
4244
|
-
sizeLifetimeSpeed: s.sizeLifetimeSpeed,
|
|
4245
|
-
opacity: s.opacity,
|
|
4246
|
-
randomSpeed: s.randomSpeed,
|
|
4247
|
-
minSpeed: s.minSpeed,
|
|
4248
|
-
maxSpeed: s.maxSpeed,
|
|
4249
|
-
textureEnabled: s.textureEnabled,
|
|
4250
|
-
textureType: s.textureType,
|
|
4251
|
-
glbModelEnabled: s.glbModelEnabled,
|
|
4252
|
-
glbFileName: s.glbFileName,
|
|
4253
|
-
glbAnimated: s.glbAnimated,
|
|
4254
|
-
animationIndex: s.animationIndex,
|
|
4255
|
-
animationSpeed: s.animationSpeed,
|
|
4256
|
-
animationLoop: s.animationLoop,
|
|
4257
|
-
useGlbTexture: s.useGlbTexture,
|
|
4258
|
-
oneOnlyMode: s.oneOnlyMode,
|
|
4259
|
-
confinementEnabled: s.confinementEnabled || !1,
|
|
4260
|
-
confinementShape: s.confinementShape || "box",
|
|
4261
|
-
confinementMode: s.confinementMode || "bounce",
|
|
4262
|
-
confinementSpace: s.confinementSpace || "world",
|
|
4263
|
-
confinementBoxHalfSize: s.confinementBoxHalfSize || [2, 2, 2],
|
|
4264
|
-
confinementSphereRadius: s.confinementSphereRadius ?? 3,
|
|
4265
|
-
confinementRestitution: s.confinementRestitution ?? 0.8,
|
|
4266
|
-
confinementFriction: s.confinementFriction ?? 0.1,
|
|
4267
|
-
softBoundaryEnabled: s.softBoundaryEnabled || !1,
|
|
4268
|
-
softBoundaryStrength: s.softBoundaryStrength ?? 5,
|
|
4269
|
-
softBoundaryFalloff: s.softBoundaryFalloff ?? 0.5,
|
|
4270
|
-
followSystemId: s.followSystemId || null,
|
|
4271
|
-
hidden: s.hidden || !1,
|
|
4272
|
-
emissionTrailEnabled: s.emissionTrailEnabled || !1,
|
|
4273
|
-
emissionTrailDuration: s.emissionTrailDuration ?? 1,
|
|
4274
|
-
emissionTrailWidth: s.emissionTrailWidth ?? 0.5,
|
|
4275
|
-
emissionTrailMinDistance: s.emissionTrailMinDistance ?? 0.05,
|
|
4276
|
-
emissionTrailMaxPoints: s.emissionTrailMaxPoints ?? 100,
|
|
4277
|
-
emissionTrailSegments: s.emissionTrailSegments ?? 8,
|
|
4278
|
-
emissionTrailShape: s.emissionTrailShape ?? "straight",
|
|
4279
|
-
emissionTrailShapeAmplitude: s.emissionTrailShapeAmplitude ?? 0.1,
|
|
4280
|
-
emissionTrailShapeFrequency: s.emissionTrailShapeFrequency ?? 4,
|
|
4281
|
-
emissionTrailShapeSpeed: s.emissionTrailShapeSpeed ?? 0,
|
|
4282
|
-
shapeDisplay: s.shapeDisplay ?? !0,
|
|
4283
|
-
followSystemTranslation: s.followSystemTranslation ?? !0,
|
|
4284
|
-
textureImageData: s.textureEnabled && !s.glbModelEnabled && s.textureImageData ? s.textureImageData : void 0,
|
|
4285
|
-
glbModelData: s.glbModelEnabled && l.glbRawArrayBuffer ? pe(l.glbRawArrayBuffer) : void 0
|
|
4946
|
+
systems: r.particleSystems.map(({ config: u, system: f }) => ({
|
|
4947
|
+
...Ys(u),
|
|
4948
|
+
// single source of truth for config fields
|
|
4949
|
+
// Binary assets embedded so replaceSystems() can restore them
|
|
4950
|
+
textureImageData: u.textureEnabled && !u.glbModelEnabled && u.textureImageData ? u.textureImageData : void 0,
|
|
4951
|
+
glbModelData: u.glbModelEnabled && f.glbRawArrayBuffer ? js(f.glbRawArrayBuffer) : void 0
|
|
4286
4952
|
})),
|
|
4287
|
-
activeSystemIndex:
|
|
4288
|
-
|
|
4289
|
-
|
|
4953
|
+
activeSystemIndex: r.activeSystemIndex,
|
|
4954
|
+
loop: r.loop || !1
|
|
4955
|
+
// group-level auto-restart
|
|
4956
|
+
}, s = e === "json" ? "json" : "hzfx";
|
|
4957
|
+
let n;
|
|
4958
|
+
if (s === "hzfx") {
|
|
4959
|
+
const u = await ks(i, { textureFormat: "webp" });
|
|
4960
|
+
n = new Blob([u], { type: "application/octet-stream" });
|
|
4961
|
+
} else
|
|
4962
|
+
n = new Blob([JSON.stringify(i, null, 2)], { type: "application/json" });
|
|
4963
|
+
let o;
|
|
4290
4964
|
if (t)
|
|
4291
|
-
|
|
4965
|
+
o = t;
|
|
4292
4966
|
else {
|
|
4293
|
-
const
|
|
4294
|
-
|
|
4967
|
+
const u = /* @__PURE__ */ new Date();
|
|
4968
|
+
o = `particle-scene_${`${u.getFullYear()}-${(u.getMonth() + 1).toString().padStart(2, "0")}-${u.getDate().toString().padStart(2, "0")}_${u.getHours().toString().padStart(2, "0")}${u.getMinutes().toString().padStart(2, "0")}`}`;
|
|
4295
4969
|
}
|
|
4296
|
-
const
|
|
4297
|
-
|
|
4298
|
-
} catch (
|
|
4299
|
-
console.error("Error saving scene:",
|
|
4970
|
+
const a = `${o}.${s}`, c = URL.createObjectURL(n), l = document.createElement("a");
|
|
4971
|
+
l.href = c, l.download = a, document.body.appendChild(l), l.click(), document.body.removeChild(l), URL.revokeObjectURL(c);
|
|
4972
|
+
} catch (i) {
|
|
4973
|
+
console.error("Error saving scene:", i), alert("Error saving scene. See console for details.");
|
|
4300
4974
|
}
|
|
4301
4975
|
}
|
|
4302
|
-
function
|
|
4976
|
+
function er(r) {
|
|
4303
4977
|
return new Promise((t, e) => {
|
|
4304
4978
|
try {
|
|
4305
|
-
const i =
|
|
4979
|
+
const i = r.target.files[0];
|
|
4306
4980
|
if (!i) {
|
|
4307
4981
|
e(new Error("No file selected"));
|
|
4308
4982
|
return;
|
|
4309
4983
|
}
|
|
4310
|
-
const
|
|
4311
|
-
|
|
4984
|
+
const s = new FileReader();
|
|
4985
|
+
s.onload = (n) => {
|
|
4312
4986
|
try {
|
|
4313
|
-
const
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
if (!Array.isArray(n.systems) || n.systems.length === 0)
|
|
4987
|
+
const o = n.target.result;
|
|
4988
|
+
let a;
|
|
4989
|
+
if (Ti(o) ? a = Ei(o) : a = JSON.parse(new TextDecoder().decode(o)), !Array.isArray(a.systems) || a.systems.length === 0)
|
|
4317
4990
|
throw new Error("No valid particle systems found in the file");
|
|
4318
|
-
const o = [];
|
|
4319
|
-
for (const s of n.systems)
|
|
4320
|
-
o.push(s);
|
|
4321
4991
|
t({
|
|
4322
|
-
systems:
|
|
4323
|
-
activeSystemIndex:
|
|
4992
|
+
systems: a.systems.slice(),
|
|
4993
|
+
activeSystemIndex: a.activeSystemIndex || 0
|
|
4324
4994
|
});
|
|
4325
|
-
} catch (
|
|
4326
|
-
console.error("Error loading scene:",
|
|
4995
|
+
} catch (o) {
|
|
4996
|
+
console.error("Error loading scene:", o), alert("Error loading scene: " + o.message), e(o);
|
|
4327
4997
|
}
|
|
4328
|
-
|
|
4329
|
-
},
|
|
4330
|
-
alert("Failed to read the file"), e(new Error("Failed to read the file")),
|
|
4331
|
-
},
|
|
4998
|
+
r.target.value = "";
|
|
4999
|
+
}, s.onerror = () => {
|
|
5000
|
+
alert("Failed to read the file"), e(new Error("Failed to read the file")), r.target.value = "";
|
|
5001
|
+
}, s.readAsArrayBuffer(i);
|
|
4332
5002
|
} catch (i) {
|
|
4333
5003
|
console.error("Error in loadScene:", i), e(i);
|
|
4334
5004
|
}
|
|
4335
5005
|
});
|
|
4336
5006
|
}
|
|
4337
|
-
async function
|
|
4338
|
-
if (!
|
|
5007
|
+
async function tr(r) {
|
|
5008
|
+
if (!r || typeof r != "string")
|
|
4339
5009
|
throw new Error("[fetchPreset] url must be a non-empty string");
|
|
4340
|
-
const t = await fetch(
|
|
5010
|
+
const t = await fetch(r);
|
|
4341
5011
|
if (!t.ok)
|
|
4342
5012
|
throw new Error(`[fetchPreset] HTTP ${t.status}: ${t.statusText}`);
|
|
4343
|
-
const e = await t.
|
|
4344
|
-
|
|
5013
|
+
const e = await t.arrayBuffer();
|
|
5014
|
+
let i;
|
|
5015
|
+
if (Ti(e) ? i = Ei(e) : i = JSON.parse(new TextDecoder().decode(e)), !Array.isArray(i.systems) || i.systems.length === 0)
|
|
4345
5016
|
throw new Error('[fetchPreset] Invalid preset: "systems" must be a non-empty array');
|
|
4346
5017
|
return {
|
|
4347
|
-
version:
|
|
4348
|
-
systems:
|
|
4349
|
-
activeSystemIndex:
|
|
5018
|
+
version: i.version,
|
|
5019
|
+
systems: i.systems,
|
|
5020
|
+
activeSystemIndex: i.activeSystemIndex ?? 0
|
|
5021
|
+
};
|
|
5022
|
+
}
|
|
5023
|
+
const qs = (r) => `
|
|
5024
|
+
@vertex fn vs(@builtin(vertex_index) i: u32) -> @builtin(position) vec4f {
|
|
5025
|
+
var p = array<vec2f, 3>(vec2f(-1.0, -3.0), vec2f(-1.0, 1.0), vec2f(3.0, 1.0));
|
|
5026
|
+
return vec4f(p[i], 0.0, 1.0);
|
|
5027
|
+
}
|
|
5028
|
+
@group(0) @binding(0) var src: ${r ? "texture_depth_multisampled_2d" : "texture_depth_2d"};
|
|
5029
|
+
@fragment fn fs(@builtin(position) pos: vec4f) -> @builtin(frag_depth) f32 {
|
|
5030
|
+
return textureLoad(src, vec2i(pos.xy), 0);
|
|
5031
|
+
}
|
|
5032
|
+
`;
|
|
5033
|
+
async function ir(r, t = {}) {
|
|
5034
|
+
const { getSceneDepth: e = null, autoRespawn: i = !0, respectEffectLoop: s = !0 } = t;
|
|
5035
|
+
let n, o, a;
|
|
5036
|
+
const c = !!(r && r.device && r.context);
|
|
5037
|
+
c ? ({ device: n, context: o, canvas: a } = r, a || (a = o.canvas)) : (a = r, { device: n, context: o } = await Cs(a));
|
|
5038
|
+
const l = navigator.gpu.getPreferredCanvasFormat(), u = t.manager || new Es(n), f = { layouts: {}, pipelines: {} };
|
|
5039
|
+
function h(d) {
|
|
5040
|
+
const p = d ? "ms" : "ss";
|
|
5041
|
+
if (!f.pipelines[p]) {
|
|
5042
|
+
const b = n.createShaderModule({ code: qs(d) }), y = n.createBindGroupLayout({
|
|
5043
|
+
entries: [{ binding: 0, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: "depth", multisampled: d } }]
|
|
5044
|
+
});
|
|
5045
|
+
f.layouts[p] = y, f.pipelines[p] = n.createRenderPipeline({
|
|
5046
|
+
layout: n.createPipelineLayout({ bindGroupLayouts: [y] }),
|
|
5047
|
+
vertex: { module: b, entryPoint: "vs" },
|
|
5048
|
+
fragment: { module: b, entryPoint: "fs", targets: [] },
|
|
5049
|
+
primitive: { topology: "triangle-list" },
|
|
5050
|
+
depthStencil: { format: "depth24plus", depthWriteEnabled: !0, depthCompare: "always" }
|
|
5051
|
+
});
|
|
5052
|
+
}
|
|
5053
|
+
return { pipeline: f.pipelines[p], layout: f.layouts[p] };
|
|
5054
|
+
}
|
|
5055
|
+
const m = {
|
|
5056
|
+
bloomSourceTextures: {},
|
|
5057
|
+
bloomCompositeTextures: {},
|
|
5058
|
+
combinedTexture: null,
|
|
5059
|
+
getBloomSourceTexture(d, p, b) {
|
|
5060
|
+
return this.bloomSourceTextures[d] || (this.bloomSourceTextures[d] = n.createTexture({
|
|
5061
|
+
size: [p, b],
|
|
5062
|
+
format: "rgba16float",
|
|
5063
|
+
// HDR chain (see webgpu.js HDR_FORMAT) — avoids additive clip
|
|
5064
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING
|
|
5065
|
+
})), this.bloomSourceTextures[d];
|
|
5066
|
+
},
|
|
5067
|
+
getBloomCompositeTexture(d, p, b) {
|
|
5068
|
+
return this.bloomCompositeTextures[d] || (this.bloomCompositeTextures[d] = n.createTexture({
|
|
5069
|
+
size: [p, b],
|
|
5070
|
+
format: "rgba16float",
|
|
5071
|
+
// HDR chain
|
|
5072
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING
|
|
5073
|
+
})), this.bloomCompositeTextures[d];
|
|
5074
|
+
},
|
|
5075
|
+
getCombinedTexture(d, p) {
|
|
5076
|
+
return this.combinedTexture || (this.combinedTexture = n.createTexture({
|
|
5077
|
+
size: [d, p],
|
|
5078
|
+
format: "rgba16float",
|
|
5079
|
+
// HDR chain — tonemapped to canvas in the final pass
|
|
5080
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING
|
|
5081
|
+
})), this.combinedTexture;
|
|
5082
|
+
},
|
|
5083
|
+
resizeTextures() {
|
|
5084
|
+
Object.values(this.bloomSourceTextures).forEach((d) => d == null ? void 0 : d.destroy()), Object.values(this.bloomCompositeTextures).forEach((d) => d == null ? void 0 : d.destroy()), this.combinedTexture && this.combinedTexture.destroy(), this.bloomSourceTextures = {}, this.bloomCompositeTextures = {}, this.combinedTexture = null;
|
|
5085
|
+
}
|
|
5086
|
+
}, S = {
|
|
5087
|
+
systemBindGroups: {},
|
|
5088
|
+
systemBloomHorizontalBindGroups: {},
|
|
5089
|
+
secondHorizontalBindGroups: {},
|
|
5090
|
+
finalBindGroup: null,
|
|
5091
|
+
textureStates: {},
|
|
5092
|
+
textureRefs: {},
|
|
5093
|
+
clear() {
|
|
5094
|
+
this.systemBindGroups = {}, this.systemBloomHorizontalBindGroups = {}, this.secondHorizontalBindGroups = {}, this.finalBindGroup = null, this.textureStates = {}, this.textureRefs = {};
|
|
5095
|
+
}
|
|
5096
|
+
}, R = n.createBuffer({ size: 96, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST }), D = n.createBuffer({ size: 208, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST }), C = n.createBuffer({ size: 32, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST }), B = n.createBuffer({ size: 32, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST }), A = n.createBuffer({ size: 64, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST }), P = Ge(n, new Uint16Array([0, 1, 2, 0, 2, 3]), GPUBufferUsage.INDEX), _ = {}, T = () => Ge(n, new Float32Array([-0.5, -0.5, 0, 0.5, -0.5, 0, 0.5, 0.5, 0, -0.5, 0.5, 0]), GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST);
|
|
5097
|
+
u.onSystemCreated = (d) => {
|
|
5098
|
+
_[d] || (_[d] = T());
|
|
5099
|
+
};
|
|
5100
|
+
const L = 4e4, N = new Float32Array(L * 8), k = new Float32Array(L * 4), X = new Float32Array(L * 4), z = n.createBuffer({ size: L * 8 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST }), me = n.createBuffer({ size: L * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST }), De = n.createBuffer({ size: L * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST }), ze = /* @__PURE__ */ new Map(), at = 8, Q = [];
|
|
5101
|
+
function _t(d) {
|
|
5102
|
+
for (const p of Q) if (p.ids.has(d)) return p;
|
|
5103
|
+
return null;
|
|
5104
|
+
}
|
|
5105
|
+
function Ci(d, p) {
|
|
5106
|
+
if (!d.pos) return;
|
|
5107
|
+
d.hist.push({ t: p, x: d.pos[0], y: d.pos[1], z: d.pos[2] });
|
|
5108
|
+
const b = p - at;
|
|
5109
|
+
for (; d.hist.length > 2 && d.hist[0].t < b; ) d.hist.shift();
|
|
5110
|
+
}
|
|
5111
|
+
function wt(d, p) {
|
|
5112
|
+
const b = d.hist;
|
|
5113
|
+
if (b.length === 0) return d.pos;
|
|
5114
|
+
if (p >= b[b.length - 1].t) {
|
|
5115
|
+
const y = b[b.length - 1];
|
|
5116
|
+
return [y.x, y.y, y.z];
|
|
5117
|
+
}
|
|
5118
|
+
if (p <= b[0].t) return [b[0].x, b[0].y, b[0].z];
|
|
5119
|
+
for (let y = b.length - 1; y > 0; y--)
|
|
5120
|
+
if (b[y - 1].t <= p) {
|
|
5121
|
+
const x = b[y - 1], Y = b[y], Z = (p - x.t) / Math.max(1e-6, Y.t - x.t);
|
|
5122
|
+
return [x.x + (Y.x - x.x) * Z, x.y + (Y.y - x.y) * Z, x.z + (Y.z - x.z) * Z];
|
|
5123
|
+
}
|
|
5124
|
+
return [b[0].x, b[0].y, b[0].z];
|
|
5125
|
+
}
|
|
5126
|
+
const Ai = 0.41421356;
|
|
5127
|
+
function Ui() {
|
|
5128
|
+
ze.clear();
|
|
5129
|
+
let d = 0, p = 0;
|
|
5130
|
+
U.position[0], U.position[1], U.position[2];
|
|
5131
|
+
for (const { system: b, config: y } of u.particleSystems) {
|
|
5132
|
+
if (!y.emissionTrailEnabled || y.hidden || y.glbModelEnabled) continue;
|
|
5133
|
+
b.readbackAndProcessParticles();
|
|
5134
|
+
const x = b.particleData, Y = b.particleVelocities, Z = b.activeParticles;
|
|
5135
|
+
if (!x || !Y || Z <= 0) continue;
|
|
5136
|
+
const $ = y.emissionTrailMode === "particles", W = d, g = y.emissionTrailDuration ?? 1, w = y.opacity ?? 1, G = y.particleSize ?? 0.5, q = y.bloomIntensity || 1, M = Math.max(1, Math.min(64, y.emissionTrailSegments ?? 8)), J = y.emissionTrailShape || "straight", ee = y.followSystemTranslation ?? !0, fe = b._simPosition, O = ee && fe ? fe[0] : 0, Qe = ee && fe ? fe[1] : 0, Vt = ee && fe ? fe[2] : 0, Ae = b._simVelocity, Ft = Ae ? Ae[0] : 0, Ki = Ae ? Ae[1] : 0, Ot = Ae ? Ae[2] : 0, Fe = _t(y.id), Lt = !!(ee && Fe && Fe.hist && Fe.hist.length > 1);
|
|
5137
|
+
for (let et = 0; et < Z; et++) {
|
|
5138
|
+
const ge = et * 8, tt = x[ge], ft = x[ge + 1], it = x[ge + 2], Qi = tt + O, es = ft + Qe, ts = it + Vt;
|
|
5139
|
+
let Oe = x[ge + 3], Le = x[ge + 4], Ne = x[ge + 5];
|
|
5140
|
+
const Xe = x[ge + 6], Ue = x[ge + 7];
|
|
5141
|
+
if (Xe >= Ue || Ue <= 0) continue;
|
|
5142
|
+
const be = Xe / Ue;
|
|
5143
|
+
if (y.colorTransitionEnabled) {
|
|
5144
|
+
const v = y.startColor ?? [1, 0, 0], I = y.endColor ?? [0, 0, 1];
|
|
5145
|
+
Oe = v[0] + (I[0] - v[0]) * be, Le = v[1] + (I[1] - v[1]) * be, Ne = v[2] + (I[2] - v[2]) * be;
|
|
5146
|
+
}
|
|
5147
|
+
Oe = Math.min(1, Oe * q), Le = Math.min(1, Le * q), Ne = Math.min(1, Ne * q);
|
|
5148
|
+
let ke = G;
|
|
5149
|
+
if (y.randomSize) {
|
|
5150
|
+
const v = Math.sin(Ue * 54321.67) * 43758.5453 % 1, I = v < 0 ? v + 1 : v;
|
|
5151
|
+
ke = (y.minSize ?? 0.1) + ((y.maxSize ?? 0.5) - (y.minSize ?? 0.1)) * I;
|
|
5152
|
+
}
|
|
5153
|
+
if (y.fadeSizeEnabled) {
|
|
5154
|
+
const v = Math.max(0.01, Math.min(10, y.sizeLifetimeSpeed ?? 1));
|
|
5155
|
+
ke *= 1 - Math.pow(be, 1 / v);
|
|
5156
|
+
}
|
|
5157
|
+
if (y.increaseSizeEnabled) {
|
|
5158
|
+
const v = Math.max(0.01, Math.min(10, y.sizeLifetimeSpeed ?? 1));
|
|
5159
|
+
ke *= 1 + Math.pow(be, 1 / v);
|
|
5160
|
+
}
|
|
5161
|
+
if (ke <= 0 || be > 0.9) continue;
|
|
5162
|
+
const Nt = Math.min((0.9 - be) * (1 / 0.2), 1), Xt = 0.75 * ke * Ai * Nt;
|
|
5163
|
+
let je = w;
|
|
5164
|
+
if (y.fadeEnabled && (je *= Math.max(0, 1 - be)), je *= Nt, je < 0.01) continue;
|
|
5165
|
+
const pt = et * 4, kt = Y[pt], jt = Y[pt + 1], Yt = Y[pt + 2], st = kt + Ft, rt = jt + Ki, nt = Yt + Ot, qt = Math.sqrt(st * st + rt * rt + nt * nt);
|
|
5166
|
+
if (qt < 1e-3) continue;
|
|
5167
|
+
const ht = 1 / qt, _e = st * ht, we = rt * ht, Se = nt * ht, Ht = U.right[0], Zt = U.right[1], $t = U.right[2];
|
|
5168
|
+
let mt = Ht * _e + Zt * we + $t * Se, ne = Ht - mt * _e, ae = Zt - mt * we, oe = $t - mt * Se, Ye = Math.sqrt(ne * ne + ae * ae + oe * oe);
|
|
5169
|
+
if (Ye < 0.2) {
|
|
5170
|
+
const v = U.up[0], I = U.up[1], H = U.up[2], V = v * _e + I * we + H * Se;
|
|
5171
|
+
ne = v - V * _e, ae = I - V * we, oe = H - V * Se, Ye = Math.sqrt(ne * ne + ae * ae + oe * oe) || 1;
|
|
5172
|
+
}
|
|
5173
|
+
ne /= Ye, ae /= Ye, oe /= Ye;
|
|
5174
|
+
const qe = Math.min(g, Xe);
|
|
5175
|
+
if (qe < 1e-3) continue;
|
|
5176
|
+
const Wt = y.gravityEnabled && y.gravityStrength || 0, Be = new Array(M + 1), Re = new Array(M + 1), Me = new Array(M + 1);
|
|
5177
|
+
if (y.orientToDirection && y.burstMode && Lt) {
|
|
5178
|
+
const v = b._emitSimRotY || 0, I = new Array(M + 1), H = new Array(M + 1), V = new Array(M + 1);
|
|
5179
|
+
for (let E = 0; E <= M; E++) {
|
|
5180
|
+
const F = wt(Fe, ye - E / M * qe);
|
|
5181
|
+
I[E] = F[0], H[E] = F[1], V[E] = F[2];
|
|
5182
|
+
}
|
|
5183
|
+
for (let E = 0; E <= M; E++) {
|
|
5184
|
+
const F = E > 0 ? E - 1 : 0, j = E < M ? E + 1 : M;
|
|
5185
|
+
let Te = I[F] - I[j], Ee = V[F] - V[j];
|
|
5186
|
+
const xe = (Math.hypot(Te, Ee) > 1e-5 ? Math.atan2(Te, Ee) : Math.atan2(Ft, Ot)) - v, se = Math.cos(xe), re = Math.sin(xe), he = E / M * qe, yt = -0.5 * Wt * he * he;
|
|
5187
|
+
Be[E] = se * tt + re * it + I[E], Re[E] = ft + yt + H[E], Me[E] = -re * tt + se * it + V[E];
|
|
5188
|
+
}
|
|
5189
|
+
} else for (let v = 0; v <= M; v++) {
|
|
5190
|
+
const I = v / M * qe, H = -0.5 * Wt * I * I;
|
|
5191
|
+
if (Lt) {
|
|
5192
|
+
const V = wt(Fe, ye - I);
|
|
5193
|
+
Be[v] = tt - kt * I + V[0], Re[v] = ft - jt * I + H + V[1], Me[v] = it - Yt * I + V[2];
|
|
5194
|
+
} else
|
|
5195
|
+
Be[v] = Qi - st * I, Re[v] = es - rt * I + H, Me[v] = ts - nt * I;
|
|
5196
|
+
}
|
|
5197
|
+
if (J !== "straight") {
|
|
5198
|
+
const v = y.emissionTrailShapeAmplitude ?? 0.1, I = y.emissionTrailShapeFrequency ?? 4, H = y.emissionTrailShapeSpeed ?? 0;
|
|
5199
|
+
let V = -Se, E = 0, F = _e, j = Math.sqrt(V * V + F * F);
|
|
5200
|
+
j < 1e-6 && (V = 0, E = Se, F = -we, j = Math.sqrt(V * V + E * E + F * F) || 1), V /= j, E /= j, F /= j;
|
|
5201
|
+
const Te = we * F - Se * E, Ee = Se * V - _e * F, pe = _e * E - we * V;
|
|
5202
|
+
for (let K = 1; K <= M; K++) {
|
|
5203
|
+
const xe = K / M * qe, se = 2 * Math.PI * I * (ye - xe) + H * ye;
|
|
5204
|
+
let re = 0, he = 0;
|
|
5205
|
+
J === "zigzag" ? re = v * Math.sign(Math.sin(se)) : J === "sine" ? re = v * Math.sin(se) : J === "spiral" && (re = v * Math.sin(se), he = v * Math.cos(se)), Be[K] += V * re + Te * he, Re[K] += E * re + Ee * he, Me[K] += F * re + pe * he;
|
|
5206
|
+
}
|
|
5207
|
+
}
|
|
5208
|
+
if ($)
|
|
5209
|
+
for (let v = 1; v <= M && d < L; v++) {
|
|
5210
|
+
const I = v / M, H = Be[v] - O, V = Re[v] - Qe, E = Me[v] - Vt, F = d * 8, j = d * 4;
|
|
5211
|
+
N[F] = H, N[F + 1] = V, N[F + 2] = E, N[F + 3] = Oe, N[F + 4] = Le, N[F + 5] = Ne, N[F + 6] = Xe + (Ue - Xe) * I, N[F + 7] = Ue, k[j] = 0, k[j + 1] = 0, k[j + 2] = 0, k[j + 3] = 0, X[j] = H, X[j + 1] = V, X[j + 2] = E, X[j + 3] = 0, d++;
|
|
5212
|
+
}
|
|
5213
|
+
else
|
|
5214
|
+
for (let v = 0; v < M && !(p + 42 > ue.length); v++) {
|
|
5215
|
+
const I = v / M, H = (v + 1) / M, V = Be[v], E = Re[v], F = Me[v], j = Be[v + 1], Te = Re[v + 1], Ee = Me[v + 1], pe = Xt * (1 - I), K = Xt * (1 - H), xe = je * (1 - I) * (1 - I), se = je * (1 - H) * (1 - H), re = V + ne * pe, he = E + ae * pe, yt = F + oe * pe, Jt = V - ne * pe, Kt = E - ae * pe, Qt = F - oe * pe, ei = j + ne * K, ti = Te + ae * K, ii = Ee + oe * K, is = j - ne * K, ss = Te - ae * K, rs = Ee - oe * K, Ie = (ns, as, os, ls) => {
|
|
5216
|
+
ue[p++] = ns, ue[p++] = as, ue[p++] = os, ue[p++] = Oe, ue[p++] = Le, ue[p++] = Ne, ue[p++] = ls;
|
|
5217
|
+
};
|
|
5218
|
+
Ie(re, he, yt, xe), Ie(Jt, Kt, Qt, xe), Ie(ei, ti, ii, se), Ie(Jt, Kt, Qt, xe), Ie(is, ss, rs, se), Ie(ei, ti, ii, se);
|
|
5219
|
+
}
|
|
5220
|
+
}
|
|
5221
|
+
$ && d > W && ze.set(y.id, { first: W, count: d - W });
|
|
5222
|
+
}
|
|
5223
|
+
d > 0 && (n.queue.writeBuffer(z, 0, N, 0, d * 8), n.queue.writeBuffer(me, 0, k, 0, d * 4), n.queue.writeBuffer(De, 0, X, 0, d * 4)), Ve = p / 7, Ve > 0 && n.queue.writeBuffer(At, 0, ue, 0, p);
|
|
5224
|
+
}
|
|
5225
|
+
const Bt = () => {
|
|
5226
|
+
n.queue.writeBuffer(C, 0, new Float32Array([1, 0, a.width, a.height, 0, 0, 0, 0])), n.queue.writeBuffer(B, 0, new Float32Array([0, 1, a.width, a.height, 0, 0, 0, 0]));
|
|
5227
|
+
};
|
|
5228
|
+
Bt();
|
|
5229
|
+
const Rt = new Float32Array(16).fill(0);
|
|
5230
|
+
Rt[0] = 1, n.queue.writeBuffer(A, 0, Rt);
|
|
5231
|
+
const te = Vs(n), ce = Ds(n), {
|
|
5232
|
+
particlePipeline: Ii,
|
|
5233
|
+
particleAdditivePipeline: Gi,
|
|
5234
|
+
particleDepthWritePipeline: Di,
|
|
5235
|
+
blurPipeline: $e,
|
|
5236
|
+
compositePipeline: zi,
|
|
5237
|
+
directRenderPipeline: Mt,
|
|
5238
|
+
finalCompositePipeline: Vi,
|
|
5239
|
+
glbMeshPipeline: Fi
|
|
5240
|
+
} = zs(n, l, ce), Tt = n.createShaderModule({ code: `
|
|
5241
|
+
struct U { mvp: mat4x4<f32> };
|
|
5242
|
+
@group(0) @binding(0) var<uniform> u: U;
|
|
5243
|
+
struct VIn { @location(0) pos: vec3<f32>, @location(1) col: vec4<f32> };
|
|
5244
|
+
struct VOut { @builtin(position) pos: vec4<f32>, @location(0) col: vec4<f32> };
|
|
5245
|
+
@vertex fn vs(v: VIn) -> VOut { var o: VOut; o.pos = u.mvp * vec4<f32>(v.pos, 1.0); o.col = v.col; return o; }
|
|
5246
|
+
@fragment fn fs(i: VOut) -> @location(0) vec4<f32> { return i.col; }
|
|
5247
|
+
` }), Et = n.createBindGroupLayout({
|
|
5248
|
+
entries: [{ binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: "uniform" } }]
|
|
5249
|
+
}), Oi = n.createRenderPipeline({
|
|
5250
|
+
layout: n.createPipelineLayout({ bindGroupLayouts: [Et] }),
|
|
5251
|
+
vertex: {
|
|
5252
|
+
module: Tt,
|
|
5253
|
+
entryPoint: "vs",
|
|
5254
|
+
buffers: [{ arrayStride: 28, attributes: [
|
|
5255
|
+
{ shaderLocation: 0, offset: 0, format: "float32x3" },
|
|
5256
|
+
{ shaderLocation: 1, offset: 12, format: "float32x4" }
|
|
5257
|
+
] }]
|
|
5258
|
+
},
|
|
5259
|
+
fragment: {
|
|
5260
|
+
module: Tt,
|
|
5261
|
+
entryPoint: "fs",
|
|
5262
|
+
targets: [{ format: "rgba16float", blend: {
|
|
5263
|
+
// renders into the HDR sceneTexture
|
|
5264
|
+
color: { srcFactor: "src-alpha", dstFactor: "one-minus-src-alpha" },
|
|
5265
|
+
alpha: { srcFactor: "src-alpha", dstFactor: "one-minus-src-alpha" }
|
|
5266
|
+
} }]
|
|
5267
|
+
},
|
|
5268
|
+
primitive: { topology: "triangle-list" },
|
|
5269
|
+
// depth24plus to match the non-bloom pass; test against the resolved scene depth
|
|
5270
|
+
// (occlusion) but don't write (transparent ribbon).
|
|
5271
|
+
depthStencil: { format: "depth24plus", depthWriteEnabled: !1, depthCompare: "less-equal" }
|
|
5272
|
+
}), Ct = 512 * 64 * 6, ue = new Float32Array(Ct * 7), At = n.createBuffer({
|
|
5273
|
+
size: Ct * 7 * 4,
|
|
5274
|
+
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
|
|
5275
|
+
label: "ribbonBuffer"
|
|
5276
|
+
}), Li = n.createBindGroup({
|
|
5277
|
+
layout: Et,
|
|
5278
|
+
entries: [{ binding: 0, resource: { buffer: R } }]
|
|
5279
|
+
});
|
|
5280
|
+
let Ve = 0, { sceneTexture: ie, bloomTexA: ve, bloomTexB: de } = ui(n, l, a.width, a.height), Pe = di(n, a.width, a.height);
|
|
5281
|
+
const ot = { uniformBuffer: R, appearanceUniformBuffer: D, horizontalBlurUniformBuffer: C, verticalBlurUniformBuffer: B, bloomIntensityBuffer: A };
|
|
5282
|
+
let We = St(n, te, ot, { sceneTexture: ie, bloomTexA: ve, bloomTexB: de });
|
|
5283
|
+
const U = {
|
|
5284
|
+
mvp: new Float32Array(16),
|
|
5285
|
+
position: new Float32Array([0, 0, 10]),
|
|
5286
|
+
right: new Float32Array([1, 0, 0]),
|
|
5287
|
+
// camera basis (world space) — for stable ribbon width
|
|
5288
|
+
up: new Float32Array([0, 1, 0]),
|
|
5289
|
+
hasCamera: !1
|
|
5290
|
+
};
|
|
5291
|
+
let ye = 0, Ni = 0;
|
|
5292
|
+
const Ce = { key: null, ms: !1, bindGroup: null };
|
|
5293
|
+
let Ut = !1, lt = !0, Je = !1, Ke = null, ct = a.width, ut = a.height;
|
|
5294
|
+
function It() {
|
|
5295
|
+
const d = [ie, ve, de, Pe], p = ui(n, l, a.width, a.height);
|
|
5296
|
+
ie = p.sceneTexture, ve = p.bloomTexA, de = p.bloomTexB, Pe = di(n, a.width, a.height), Bt(), S.clear(), m.resizeTextures(), We = St(n, te, ot, { sceneTexture: ie, bloomTexA: ve, bloomTexB: de });
|
|
5297
|
+
let b = !1;
|
|
5298
|
+
const y = () => {
|
|
5299
|
+
if (!b) {
|
|
5300
|
+
b = !0, requestAnimationFrame(y);
|
|
5301
|
+
return;
|
|
5302
|
+
}
|
|
5303
|
+
d.forEach((x) => x.destroy());
|
|
5304
|
+
};
|
|
5305
|
+
requestAnimationFrame(y);
|
|
5306
|
+
}
|
|
5307
|
+
function Xi(d, p, b) {
|
|
5308
|
+
U.mvp.set(Ns(d, p)), p && p.length >= 10 && (U.right[0] = p[0], U.right[1] = p[4], U.right[2] = p[8], U.up[0] = p[1], U.up[1] = p[5], U.up[2] = p[9]), b && (U.position[0] = b.x ?? b[0], U.position[1] = b.y ?? b[1], U.position[2] = b.z ?? b[2]), U.hasCamera = !0;
|
|
5309
|
+
}
|
|
5310
|
+
function ki(d, p) {
|
|
5311
|
+
U.mvp.set(d), p && (U.position[0] = p.x ?? p[0], U.position[1] = p.y ?? p[1], U.position[2] = p.z ?? p[2]), U.hasCamera = !0;
|
|
5312
|
+
}
|
|
5313
|
+
async function dt(d) {
|
|
5314
|
+
if (Je) {
|
|
5315
|
+
Ke = d;
|
|
5316
|
+
return;
|
|
5317
|
+
}
|
|
5318
|
+
Je = !0;
|
|
5319
|
+
try {
|
|
5320
|
+
for (const p in _) delete _[p];
|
|
5321
|
+
S.clear(), m.resizeTextures(), We = St(n, te, ot, { sceneTexture: ie, bloomTexA: ve, bloomTexB: de }), await u.replaceSystems({ systems: [], activeSystemIndex: 0 });
|
|
5322
|
+
for (const p of d)
|
|
5323
|
+
await u.addSystems(p.preset, p.position || [0, 0, 0]);
|
|
5324
|
+
for (const { config: p } of u.particleSystems)
|
|
5325
|
+
_[p.id] || (_[p.id] = T());
|
|
5326
|
+
lt = !0, u.respawnAllSystems();
|
|
5327
|
+
} finally {
|
|
5328
|
+
if (Je = !1, Ke) {
|
|
5329
|
+
const p = Ke;
|
|
5330
|
+
Ke = null, dt(p);
|
|
5331
|
+
}
|
|
5332
|
+
}
|
|
5333
|
+
}
|
|
5334
|
+
async function ji(d, p = [0, 0, 0]) {
|
|
5335
|
+
return dt([{ preset: d, position: p }]);
|
|
5336
|
+
}
|
|
5337
|
+
function Yi(d) {
|
|
5338
|
+
if (Ut || Je || !u.ready || (d > 0.1 && (d = 0.1), d <= 0) || u.particleSystems.length === 0) return;
|
|
5339
|
+
if ((a.width !== ct || a.height !== ut) && (ct = a.width, ut = a.height, It()), ye += d, Q.length) {
|
|
5340
|
+
for (const g of Q) {
|
|
5341
|
+
if (g.getPosition) {
|
|
5342
|
+
const w = g.getPosition();
|
|
5343
|
+
g.pos = w ? Array.isArray(w) ? [w[0], w[1], w[2]] : [w.x, w.y, w.z] : null;
|
|
5344
|
+
}
|
|
5345
|
+
g.vel = g.pos && g.prevPos && g.wasActive && d > 0 ? [(g.pos[0] - g.prevPos[0]) / d, (g.pos[1] - g.prevPos[1]) / d, (g.pos[2] - g.prevPos[2]) / d] : [0, 0, 0], g.justResumed = !!g.pos && !g.wasActive, g.justResumed && (g.hist.length = 0);
|
|
5346
|
+
}
|
|
5347
|
+
for (const { system: g, config: w } of u.particleSystems) {
|
|
5348
|
+
const G = _t(w.id);
|
|
5349
|
+
if (!(!G || G.historyOnly) && (w.hidden = !G.pos, G.pos)) {
|
|
5350
|
+
let q = null;
|
|
5351
|
+
if (G.orientToDirection && G.vel) {
|
|
5352
|
+
const M = G.vel[0], J = G.vel[2];
|
|
5353
|
+
Math.hypot(M, J) > 1e-4 && (q = [0, 0, Math.atan2(M, J)]);
|
|
5354
|
+
}
|
|
5355
|
+
g.setSimulationTransform({ position: G.pos, velocity: G.vel, rotation: q }), g.updateAppearanceUniform(), (G.justResumed || g.activeParticles === 0) && g.spawnParticles();
|
|
5356
|
+
}
|
|
5357
|
+
}
|
|
5358
|
+
for (const g of Q)
|
|
5359
|
+
g.pos ? Ci(g, ye) : g.hist.length = 0, g.prevPos = g.pos ? g.pos.slice() : null, g.wasActive = !!g.pos;
|
|
5360
|
+
if (globalThis.__HZFX_DEBUG && (Ni++ & 63) === 0) {
|
|
5361
|
+
const g = u.particleSystems.reduce((M, J) => M + (J.system.activeParticles | 0), 0), w = Q.find((M) => M.pos), G = w ? Math.hypot(U.position[0] - w.pos[0], U.position[1] - w.pos[1], U.position[2] - w.pos[2]).toFixed(1) : "-", q = Q.map((M) => `{ids:[${[...M.ids]}],pos:${M.pos ? "1" : "0"},hist:${M.hist.length}}`).join(",");
|
|
5362
|
+
console.info(`[HZFX] movingGroups(${Q.length})=[${q}] activeParticles=${g} systems=${u.particleSystems.length} ribbonVerts=${Ve} camDist=${G} t=${ye.toFixed(1)}`);
|
|
5363
|
+
}
|
|
5364
|
+
}
|
|
5365
|
+
if (u.updateAllSystems(d), s ? u.loop ?? i : i) {
|
|
5366
|
+
const g = u.particleSystems.length > 0 && u.particleSystems.every(({ system: w }) => w.activeParticles === 0 && !w.emitting);
|
|
5367
|
+
g && lt && u.respawnAllSystems(), lt = !g;
|
|
5368
|
+
}
|
|
5369
|
+
for (const { system: g, config: w } of u.particleSystems)
|
|
5370
|
+
w.glbModelEnabled && g.glbAnimator && (g.glbAnimator.update(d), g.updateAnimatedGLBBuffer());
|
|
5371
|
+
n.queue.writeBuffer(R, 0, U.mvp), n.queue.writeBuffer(R, 64, new Float32Array([
|
|
5372
|
+
U.position[0],
|
|
5373
|
+
U.position[1],
|
|
5374
|
+
U.position[2],
|
|
5375
|
+
a.height / Math.max(1, a.width),
|
|
5376
|
+
ye
|
|
5377
|
+
])), Ui();
|
|
5378
|
+
const b = u.particleSystems.some(({ config: g }) => g.bloomEnabled), y = n.createCommandEncoder();
|
|
5379
|
+
let x = !1;
|
|
5380
|
+
if (e)
|
|
5381
|
+
try {
|
|
5382
|
+
const g = e();
|
|
5383
|
+
if (g) {
|
|
5384
|
+
let w = null, G = null, q = !1;
|
|
5385
|
+
if (g instanceof GPUTexture ? g.width === a.width && g.height === a.height && (w = g, G = () => g.createView({ aspect: "depth-only" }), q = g.sampleCount > 1) : g.view && (w = g.view, G = () => g.view, q = !!g.multisampled), w) {
|
|
5386
|
+
const { pipeline: M, layout: J } = h(q);
|
|
5387
|
+
(Ce.key !== w || Ce.ms !== q) && (Ce.key = w, Ce.ms = q, Ce.bindGroup = n.createBindGroup({
|
|
5388
|
+
layout: J,
|
|
5389
|
+
entries: [{ binding: 0, resource: G() }]
|
|
5390
|
+
}));
|
|
5391
|
+
const ee = y.beginRenderPass({
|
|
5392
|
+
colorAttachments: [],
|
|
5393
|
+
depthStencilAttachment: { view: Pe.createView(), depthClearValue: 1, depthLoadOp: "clear", depthStoreOp: "store" }
|
|
5394
|
+
});
|
|
5395
|
+
ee.setPipeline(M), ee.setBindGroup(0, Ce.bindGroup), ee.draw(3), ee.end(), x = !0;
|
|
5396
|
+
}
|
|
5397
|
+
}
|
|
5398
|
+
} catch {
|
|
5399
|
+
}
|
|
5400
|
+
const Y = y.beginRenderPass({
|
|
5401
|
+
colorAttachments: [{ view: ie.createView(), loadOp: "clear", storeOp: "store", clearValue: { r: 0, g: 0, b: 0, a: 0 } }],
|
|
5402
|
+
depthStencilAttachment: x ? { view: Pe.createView(), depthLoadOp: "load", depthStoreOp: "store" } : { view: Pe.createView(), depthClearValue: 1, depthLoadOp: "clear", depthStoreOp: "store" }
|
|
5403
|
+
});
|
|
5404
|
+
for (const { system: g, config: w } of u.particleSystems)
|
|
5405
|
+
w.bloomEnabled || w.hidden || g.activeParticles === 0 || Gt(Y, g, w, !0);
|
|
5406
|
+
if (Ve > 0 && (Y.setPipeline(Oi), Y.setBindGroup(0, Li), Y.setVertexBuffer(0, At), Y.draw(Ve)), Y.end(), b)
|
|
5407
|
+
for (const { system: g, config: w } of u.particleSystems) {
|
|
5408
|
+
if (!w.bloomEnabled || w.hidden || g.activeParticles === 0) continue;
|
|
5409
|
+
const G = g.config.id, q = m.getBloomSourceTexture(G, a.width, a.height), M = y.beginRenderPass({
|
|
5410
|
+
colorAttachments: [{ view: q.createView(), loadOp: "clear", storeOp: "store", clearValue: { r: 0, g: 0, b: 0, a: 0 } }],
|
|
5411
|
+
depthStencilAttachment: { view: Pe.createView(), depthClearValue: 1, depthLoadOp: "load", depthStoreOp: "store" }
|
|
5412
|
+
});
|
|
5413
|
+
Gt(M, g, w, !1), M.end();
|
|
5414
|
+
const J = new Float32Array(16).fill(0);
|
|
5415
|
+
J[0] = w.bloomIntensity, n.queue.writeBuffer(A, 0, J);
|
|
5416
|
+
const ee = {
|
|
5417
|
+
colorAttachments: [{ view: ve.createView(), loadOp: "clear", storeOp: "store", clearValue: { r: 0, g: 0, b: 0, a: 0 } }]
|
|
5418
|
+
}, fe = {
|
|
5419
|
+
colorAttachments: [{ view: de.createView(), loadOp: "clear", storeOp: "store", clearValue: { r: 0, g: 0, b: 0, a: 0 } }]
|
|
5420
|
+
};
|
|
5421
|
+
S.systemBloomHorizontalBindGroups[G] || (S.systemBloomHorizontalBindGroups[G] = n.createBindGroup({
|
|
5422
|
+
layout: ce.bloomBindGroupLayout,
|
|
5423
|
+
entries: [
|
|
5424
|
+
{ binding: 0, resource: te },
|
|
5425
|
+
{ binding: 1, resource: q.createView() },
|
|
5426
|
+
{ binding: 2, resource: { buffer: C } }
|
|
5427
|
+
]
|
|
5428
|
+
}));
|
|
5429
|
+
let O = y.beginRenderPass(ee);
|
|
5430
|
+
O.setPipeline($e), O.setBindGroup(0, S.systemBloomHorizontalBindGroups[G]), O.draw(3), O.end(), O = y.beginRenderPass(fe), O.setPipeline($e), O.setBindGroup(0, We.verticalBlurBindGroup), O.draw(3), O.end(), S.secondHorizontalBindGroups[G] || (S.secondHorizontalBindGroups[G] = n.createBindGroup({
|
|
5431
|
+
layout: ce.bloomBindGroupLayout,
|
|
5432
|
+
entries: [
|
|
5433
|
+
{ binding: 0, resource: te },
|
|
5434
|
+
{ binding: 1, resource: de.createView() },
|
|
5435
|
+
{ binding: 2, resource: { buffer: C } }
|
|
5436
|
+
]
|
|
5437
|
+
})), O = y.beginRenderPass(ee), O.setPipeline($e), O.setBindGroup(0, S.secondHorizontalBindGroups[G]), O.draw(3), O.end(), O = y.beginRenderPass(fe), O.setPipeline($e), O.setBindGroup(0, We.verticalBlurBindGroup), O.draw(3), O.end();
|
|
5438
|
+
const Qe = m.getBloomCompositeTexture(G, a.width, a.height);
|
|
5439
|
+
O = y.beginRenderPass({
|
|
5440
|
+
colorAttachments: [{ view: Qe.createView(), loadOp: "clear", storeOp: "store", clearValue: { r: 0, g: 0, b: 0, a: 0 } }]
|
|
5441
|
+
}), O.setPipeline(zi), O.setBindGroup(0, n.createBindGroup({
|
|
5442
|
+
layout: ce.compositeBindGroupLayout,
|
|
5443
|
+
entries: [
|
|
5444
|
+
{ binding: 0, resource: te },
|
|
5445
|
+
{ binding: 1, resource: q.createView() },
|
|
5446
|
+
{ binding: 2, resource: de.createView() },
|
|
5447
|
+
{ binding: 3, resource: { buffer: g.bloomIntensityBuffer } }
|
|
5448
|
+
]
|
|
5449
|
+
})), O.draw(3), O.end();
|
|
5450
|
+
}
|
|
5451
|
+
const Z = m.getCombinedTexture(a.width, a.height), $ = y.beginRenderPass({
|
|
5452
|
+
colorAttachments: [{ view: Z.createView(), loadOp: "clear", storeOp: "store", clearValue: { r: 0, g: 0, b: 0, a: 0 } }]
|
|
5453
|
+
});
|
|
5454
|
+
$.setPipeline(Mt), $.setBindGroup(0, n.createBindGroup({
|
|
5455
|
+
layout: ce.compositeBindGroupLayout,
|
|
5456
|
+
entries: [
|
|
5457
|
+
{ binding: 0, resource: te },
|
|
5458
|
+
{ binding: 1, resource: ie.createView() },
|
|
5459
|
+
{ binding: 2, resource: ie.createView() },
|
|
5460
|
+
{ binding: 3, resource: { buffer: A } }
|
|
5461
|
+
]
|
|
5462
|
+
})), $.draw(3);
|
|
5463
|
+
for (const { config: g, system: w } of u.particleSystems) {
|
|
5464
|
+
if (!g.bloomEnabled || g.hidden || w.activeParticles === 0) continue;
|
|
5465
|
+
const G = w.config.id;
|
|
5466
|
+
$.setPipeline(Mt), $.setBindGroup(0, n.createBindGroup({
|
|
5467
|
+
layout: ce.compositeBindGroupLayout,
|
|
5468
|
+
entries: [
|
|
5469
|
+
{ binding: 0, resource: te },
|
|
5470
|
+
{ binding: 1, resource: m.getBloomCompositeTexture(G, a.width, a.height).createView() },
|
|
5471
|
+
{ binding: 2, resource: ie.createView() },
|
|
5472
|
+
{ binding: 3, resource: { buffer: A } }
|
|
5473
|
+
]
|
|
5474
|
+
})), $.draw(3);
|
|
5475
|
+
}
|
|
5476
|
+
$.end();
|
|
5477
|
+
const W = y.beginRenderPass({
|
|
5478
|
+
colorAttachments: [{
|
|
5479
|
+
view: o.getCurrentTexture().createView(),
|
|
5480
|
+
loadOp: c ? "load" : "clear",
|
|
5481
|
+
storeOp: "store",
|
|
5482
|
+
clearValue: { r: 0, g: 0, b: 0, a: 0 }
|
|
5483
|
+
}]
|
|
5484
|
+
});
|
|
5485
|
+
W.setPipeline(Vi), S.finalBindGroup || (S.finalBindGroup = n.createBindGroup({
|
|
5486
|
+
layout: ce.compositeBindGroupLayout,
|
|
5487
|
+
entries: [
|
|
5488
|
+
{ binding: 0, resource: te },
|
|
5489
|
+
{ binding: 1, resource: Z.createView() },
|
|
5490
|
+
{ binding: 2, resource: ie.createView() },
|
|
5491
|
+
{ binding: 3, resource: { buffer: A } }
|
|
5492
|
+
]
|
|
5493
|
+
})), W.setBindGroup(0, S.finalBindGroup), W.draw(3), W.end(), n.queue.submit([y.finish()]);
|
|
5494
|
+
}
|
|
5495
|
+
function Gt(d, p, b, y) {
|
|
5496
|
+
const x = p.config.id, Y = b.glbModelEnabled && p.glbMeshData;
|
|
5497
|
+
let Z;
|
|
5498
|
+
if (y) {
|
|
5499
|
+
const W = !S.systemBindGroups[x] || S.textureStates[x] !== b.textureEnabled || S.textureRefs[x] !== p.particleTexture;
|
|
5500
|
+
S.textureStates[x] = b.textureEnabled, S.textureRefs[x] = p.particleTexture, W && (S.systemBindGroups[x] = n.createBindGroup({
|
|
5501
|
+
layout: ce.particleBindGroupLayout,
|
|
5502
|
+
entries: [
|
|
5503
|
+
{ binding: 0, resource: { buffer: R } },
|
|
5504
|
+
{ binding: 1, resource: { buffer: p.appearanceUniformBuffer } },
|
|
5505
|
+
{ binding: 2, resource: p.particleTexture.createView() },
|
|
5506
|
+
{ binding: 3, resource: te }
|
|
5507
|
+
]
|
|
5508
|
+
})), Z = S.systemBindGroups[x];
|
|
5509
|
+
} else
|
|
5510
|
+
Z = n.createBindGroup({
|
|
5511
|
+
layout: ce.particleBindGroupLayout,
|
|
5512
|
+
entries: [
|
|
5513
|
+
{ binding: 0, resource: { buffer: R } },
|
|
5514
|
+
{ binding: 1, resource: { buffer: p.appearanceUniformBuffer } },
|
|
5515
|
+
{ binding: 2, resource: p.particleTexture.createView() },
|
|
5516
|
+
{ binding: 3, resource: te }
|
|
5517
|
+
]
|
|
5518
|
+
});
|
|
5519
|
+
const $ = b.shapeDisplay !== !1;
|
|
5520
|
+
if (Y)
|
|
5521
|
+
$ && (d.setPipeline(Fi), d.setBindGroup(0, Z), d.setVertexBuffer(0, p.glbVertexBuffer), d.setVertexBuffer(1, p.instanceBuffer), d.setVertexBuffer(2, p.velocityBuffer), d.setIndexBuffer(p.glbIndexBuffer, p.glbIndexFormat), d.drawIndexed(p.glbIndexCount, p.activeParticles));
|
|
5522
|
+
else {
|
|
5523
|
+
d.setPipeline(b.blendMode === "additive" ? Gi : Ii), d.setIndexBuffer(P, "uint16"), _[x] || (_[x] = T()), d.setVertexBuffer(0, _[x]), d.setBindGroup(0, Z), $ && (d.setVertexBuffer(1, p.instanceBuffer), d.setVertexBuffer(2, p.velocityBuffer), d.setVertexBuffer(3, p.trailBuffer), d.drawIndexed(6, p.activeParticles));
|
|
5524
|
+
const W = ze.get(x);
|
|
5525
|
+
W && (d.setVertexBuffer(1, z), d.setVertexBuffer(2, me), d.setVertexBuffer(3, De), d.drawIndexed(6, W.count, 0, 0, W.first)), $ && b.depthWriteEnabled && (d.setPipeline(Di), d.drawIndexed(6, p.activeParticles));
|
|
5526
|
+
}
|
|
5527
|
+
}
|
|
5528
|
+
function qi() {
|
|
5529
|
+
ct = a.width, ut = a.height, It();
|
|
5530
|
+
}
|
|
5531
|
+
function Hi() {
|
|
5532
|
+
S.clear();
|
|
5533
|
+
}
|
|
5534
|
+
function Zi() {
|
|
5535
|
+
Ut = !0, u.destroy(), [ie, ve, de, Pe].forEach((d) => d == null ? void 0 : d.destroy()), m.resizeTextures(), [
|
|
5536
|
+
R,
|
|
5537
|
+
D,
|
|
5538
|
+
C,
|
|
5539
|
+
B,
|
|
5540
|
+
A,
|
|
5541
|
+
P,
|
|
5542
|
+
z,
|
|
5543
|
+
me,
|
|
5544
|
+
De
|
|
5545
|
+
].forEach((d) => d == null ? void 0 : d.destroy()), Object.values(_).forEach((d) => d == null ? void 0 : d.destroy());
|
|
5546
|
+
}
|
|
5547
|
+
async function Dt(d, p) {
|
|
5548
|
+
const b = await u.addSystems(d, p);
|
|
5549
|
+
for (const { config: y } of u.particleSystems)
|
|
5550
|
+
_[y.id] || (_[y.id] = T());
|
|
5551
|
+
return u.respawnAllSystems(), new Set(Array.isArray(b) ? b : []);
|
|
5552
|
+
}
|
|
5553
|
+
function zt(d) {
|
|
5554
|
+
for (const p of d) {
|
|
5555
|
+
const b = u.particleSystems.findIndex((y) => y.config.id === p);
|
|
5556
|
+
b >= 0 && u.removeSystem(b);
|
|
5557
|
+
}
|
|
5558
|
+
}
|
|
5559
|
+
async function $i(d, p = [0, 0, 0]) {
|
|
5560
|
+
const b = await Dt(d, p);
|
|
5561
|
+
return { remove() {
|
|
5562
|
+
zt(b);
|
|
5563
|
+
} };
|
|
5564
|
+
}
|
|
5565
|
+
async function Wi(d, p = {}) {
|
|
5566
|
+
const b = await Dt(d, [0, 0, 0]);
|
|
5567
|
+
globalThis.__HZFX_DEBUG && console.info(`[HZFX] addMovingEmitter: presetSystems=${(d && d.systems || []).length} newIds=[${[...b]}]`);
|
|
5568
|
+
const y = { ids: b, pos: null, hist: [], getPosition: p.getPosition || null, orientToDirection: !!p.orientToDirection };
|
|
5569
|
+
return Q.push(y), {
|
|
5570
|
+
setPosition(x) {
|
|
5571
|
+
x && (y.pos = Array.isArray(x) ? [x[0], x[1], x[2]] : [x.x, x.y, x.z]);
|
|
5572
|
+
},
|
|
5573
|
+
setOrientToDirection(x) {
|
|
5574
|
+
y.orientToDirection = !!x;
|
|
5575
|
+
},
|
|
5576
|
+
remove() {
|
|
5577
|
+
zt(b);
|
|
5578
|
+
const x = Q.indexOf(y);
|
|
5579
|
+
x >= 0 && Q.splice(x, 1);
|
|
5580
|
+
}
|
|
5581
|
+
};
|
|
5582
|
+
}
|
|
5583
|
+
function Ji(d, p) {
|
|
5584
|
+
const y = { ids: d instanceof Set ? d : new Set(d), pos: null, hist: [], getPosition: p, historyOnly: !0 };
|
|
5585
|
+
return Q.push(y), {
|
|
5586
|
+
remove() {
|
|
5587
|
+
const x = Q.indexOf(y);
|
|
5588
|
+
x >= 0 && Q.splice(x, 1);
|
|
5589
|
+
},
|
|
5590
|
+
// Update which systems this history group covers WITHOUT losing the accumulated path
|
|
5591
|
+
// history. Needed when the scene's systems change (e.g. duplicate/add/remove) while the
|
|
5592
|
+
// group is active — otherwise a newly-added system's id isn't in the set and its trail
|
|
5593
|
+
// can't follow the recorded movement path (it falls back to straight extrapolation).
|
|
5594
|
+
setIds(x) {
|
|
5595
|
+
y.ids = x instanceof Set ? x : new Set(x);
|
|
5596
|
+
}
|
|
5597
|
+
};
|
|
5598
|
+
}
|
|
5599
|
+
return {
|
|
5600
|
+
manager: u,
|
|
5601
|
+
device: n,
|
|
5602
|
+
context: o,
|
|
5603
|
+
setCamera: Xi,
|
|
5604
|
+
setCameraMVP: ki,
|
|
5605
|
+
setEmitters: dt,
|
|
5606
|
+
loadPreset: ji,
|
|
5607
|
+
addEmitter: $i,
|
|
5608
|
+
addMovingEmitter: Wi,
|
|
5609
|
+
render: Yi,
|
|
5610
|
+
resize: qi,
|
|
5611
|
+
clearCaches: Hi,
|
|
5612
|
+
trackHistoryGroup: Ji,
|
|
5613
|
+
destroy: Zi
|
|
5614
|
+
};
|
|
5615
|
+
}
|
|
5616
|
+
function sr(r) {
|
|
5617
|
+
return () => {
|
|
5618
|
+
var t, e, i, s, n, o;
|
|
5619
|
+
try {
|
|
5620
|
+
const a = r.backend;
|
|
5621
|
+
if (!a) return null;
|
|
5622
|
+
if (r.needsFrameBufferTarget && r._frameBufferTarget) {
|
|
5623
|
+
const u = (i = (e = (t = r._textures) == null ? void 0 : t.get) == null ? void 0 : e.call(t, r._frameBufferTarget)) == null ? void 0 : i.depthTexture, f = u ? (s = a.get(u)) == null ? void 0 : s.texture : null;
|
|
5624
|
+
if (f && f.width === r.domElement.width && f.height === r.domElement.height) return f;
|
|
5625
|
+
}
|
|
5626
|
+
const c = r.getCanvasTarget ? a.get(r.getCanvasTarget()) : null, l = ((o = (n = c == null ? void 0 : c.descriptor) == null ? void 0 : n.depthStencilAttachment) == null ? void 0 : o.view) ?? null;
|
|
5627
|
+
return l ? { view: l, multisampled: (r.currentSamples ?? 0) > 1 } : null;
|
|
5628
|
+
} catch {
|
|
5629
|
+
return null;
|
|
5630
|
+
}
|
|
4350
5631
|
};
|
|
4351
5632
|
}
|
|
4352
5633
|
export {
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
5634
|
+
Ts as GLBAnimator,
|
|
5635
|
+
Zs as Objects3DManager,
|
|
5636
|
+
cs as ParticleEmitter,
|
|
5637
|
+
us as ParticlePhysics,
|
|
5638
|
+
si as ParticleScript,
|
|
5639
|
+
bt as ParticleSystem,
|
|
5640
|
+
Es as ParticleSystemManager,
|
|
5641
|
+
ds as ParticleTextureManager,
|
|
5642
|
+
Si as blurShader,
|
|
5643
|
+
xi as compositeShader,
|
|
5644
|
+
Ds as createBindGroupLayouts,
|
|
5645
|
+
St as createBindGroups,
|
|
5646
|
+
Ge as createBuffer,
|
|
5647
|
+
Fs as createCubeGeometry,
|
|
5648
|
+
di as createDepthTexture,
|
|
5649
|
+
Js as createLookAtMatrix,
|
|
5650
|
+
Ks as createProjectionMatrix,
|
|
5651
|
+
zs as createRenderPipelines,
|
|
5652
|
+
ui as createRenderTextures,
|
|
5653
|
+
Vs as createSampler,
|
|
5654
|
+
Os as createSphereGeometry,
|
|
5655
|
+
vi as directRenderShader,
|
|
5656
|
+
ws as extractGLBTexture,
|
|
5657
|
+
tr as fetchPreset,
|
|
5658
|
+
Gs as glbMeshParticleShader,
|
|
5659
|
+
$s as hexToRgb,
|
|
5660
|
+
ir as initHzFxOverlay,
|
|
5661
|
+
Cs as initWebGPU,
|
|
5662
|
+
Ti as isHZFX,
|
|
5663
|
+
er as loadScene,
|
|
5664
|
+
sr as makeThreeSceneDepth,
|
|
5665
|
+
Ns as multiplyMatrices,
|
|
5666
|
+
Is as object3dShader,
|
|
5667
|
+
ks as packHZFX,
|
|
5668
|
+
gi as parseGLB,
|
|
5669
|
+
As as particlePhysicsShader,
|
|
5670
|
+
bi as particleShader,
|
|
5671
|
+
Ws as rgbToHex,
|
|
5672
|
+
Qs as saveScene,
|
|
5673
|
+
Ys as serializeSystemConfig,
|
|
5674
|
+
Ei as unpackHZFX
|
|
4387
5675
|
};
|