reze-engine 0.3.10 → 0.3.12
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 +66 -66
- package/dist/audio.d.ts +29 -0
- package/dist/audio.d.ts.map +1 -0
- package/dist/audio.js +116 -0
- package/dist/engine.js +4 -4
- package/dist/ik-solver.d.ts +2 -3
- package/dist/ik-solver.d.ts.map +1 -1
- package/dist/ik-solver.js +16 -32
- package/dist/math.d.ts +4 -0
- package/dist/math.d.ts.map +1 -1
- package/dist/math.js +72 -13
- package/dist/model.d.ts +5 -5
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +119 -127
- package/dist/particles.d.ts +67 -0
- package/dist/particles.d.ts.map +1 -0
- package/dist/particles.js +266 -0
- package/dist/physics.d.ts +2 -2
- package/dist/physics.d.ts.map +1 -1
- package/dist/physics.js +6 -10
- package/package.json +1 -1
- package/src/camera.ts +358 -358
- package/src/engine.ts +4 -4
- package/src/ik-solver.ts +411 -431
- package/src/math.ts +584 -520
- package/src/model.ts +129 -158
- package/src/physics.ts +742 -752
- package/src/vmd-loader.ts +276 -276
- package/dist/bezier-interpolate.d.ts +0 -15
- package/dist/bezier-interpolate.d.ts.map +0 -1
- package/dist/bezier-interpolate.js +0 -40
- package/dist/engine_r.d.ts +0 -132
- package/dist/engine_r.d.ts.map +0 -1
- package/dist/engine_r.js +0 -1489
- package/dist/engine_ts.d.ts +0 -143
- package/dist/engine_ts.d.ts.map +0 -1
- package/dist/engine_ts.js +0 -1575
- package/dist/player.d.ts +0 -64
- package/dist/player.d.ts.map +0 -1
- package/dist/player.js +0 -220
- package/src/player.ts +0 -290
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { Vec3 } from "./math";
|
|
2
|
+
const MAX_PARTICLES = 30000;
|
|
3
|
+
export const DEFAULT_PARTICLE_CONFIG = {
|
|
4
|
+
particleCount: 5000, // Reduced from 23000 for better performance
|
|
5
|
+
particleSize: 0.1, // Smaller particles
|
|
6
|
+
fadeSpeed: 0.008, // Faster fade = particles die sooner
|
|
7
|
+
explosionForce: 0.6, // Smaller explosion radius
|
|
8
|
+
hoverDuration: 1.2, // Shorter hover
|
|
9
|
+
gravity: 0.00265,
|
|
10
|
+
friction: 0.95494,
|
|
11
|
+
rocketSpeed: 1.0,
|
|
12
|
+
rocketSize: 0.4, // Smaller rocket trail
|
|
13
|
+
};
|
|
14
|
+
export class Firework {
|
|
15
|
+
constructor(startX, config) {
|
|
16
|
+
this.startX = startX;
|
|
17
|
+
this.config = config;
|
|
18
|
+
this.phase = "rocket";
|
|
19
|
+
this.timer = 0;
|
|
20
|
+
this.colors = [];
|
|
21
|
+
this.rocketAlive = true;
|
|
22
|
+
this.rocketLifetime = 1.0;
|
|
23
|
+
this.justExploded = false; // Flag for triggering audio
|
|
24
|
+
// Explosion particle data
|
|
25
|
+
this.particles = null;
|
|
26
|
+
this.baseColors = null;
|
|
27
|
+
// Generate color palette (mono, dual, or tri-color)
|
|
28
|
+
const rand = Math.random();
|
|
29
|
+
const baseHue = Math.random();
|
|
30
|
+
if (rand < 0.33) {
|
|
31
|
+
// MONO (1 Color)
|
|
32
|
+
this.colors.push(this.hslToRgb(baseHue, 1.0, 0.6));
|
|
33
|
+
}
|
|
34
|
+
else if (rand < 0.66) {
|
|
35
|
+
// DUAL (2 Colors - Complementary)
|
|
36
|
+
this.colors.push(this.hslToRgb(baseHue, 1.0, 0.6));
|
|
37
|
+
this.colors.push(this.hslToRgb((baseHue + 0.5) % 1.0, 1.0, 0.5));
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
// TRI (3 Colors - Triad)
|
|
41
|
+
this.colors.push(this.hslToRgb(baseHue, 1.0, 0.6));
|
|
42
|
+
this.colors.push(this.hslToRgb((baseHue + 0.33) % 1.0, 1.0, 0.6));
|
|
43
|
+
this.colors.push(this.hslToRgb((baseHue + 0.66) % 1.0, 1.0, 0.6));
|
|
44
|
+
}
|
|
45
|
+
this.pos = new Vec3(startX, -50, (Math.random() - 0.5) * 30);
|
|
46
|
+
this.vel = new Vec3((Math.random() - 0.5) * 0.5, config.rocketSpeed * (0.9 + Math.random() * 0.3), (Math.random() - 0.5) * 0.5);
|
|
47
|
+
this.targetY = 10 + Math.random() * 20; // Higher explosion point
|
|
48
|
+
}
|
|
49
|
+
hslToRgb(h, s, l) {
|
|
50
|
+
let r, g, b;
|
|
51
|
+
if (s === 0) {
|
|
52
|
+
r = g = b = l;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
const hue2rgb = (p, q, t) => {
|
|
56
|
+
if (t < 0)
|
|
57
|
+
t += 1;
|
|
58
|
+
if (t > 1)
|
|
59
|
+
t -= 1;
|
|
60
|
+
if (t < 1 / 6)
|
|
61
|
+
return p + (q - p) * 6 * t;
|
|
62
|
+
if (t < 1 / 2)
|
|
63
|
+
return q;
|
|
64
|
+
if (t < 2 / 3)
|
|
65
|
+
return p + (q - p) * (2 / 3 - t) * 6;
|
|
66
|
+
return p;
|
|
67
|
+
};
|
|
68
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
69
|
+
const p = 2 * l - q;
|
|
70
|
+
r = hue2rgb(p, q, h + 1 / 3);
|
|
71
|
+
g = hue2rgb(p, q, h);
|
|
72
|
+
b = hue2rgb(p, q, h - 1 / 3);
|
|
73
|
+
}
|
|
74
|
+
return new Vec3(r, g, b);
|
|
75
|
+
}
|
|
76
|
+
update(deltaTime) {
|
|
77
|
+
if (this.phase === "rocket") {
|
|
78
|
+
this.pos.x += this.vel.x;
|
|
79
|
+
this.pos.y += this.vel.y;
|
|
80
|
+
this.pos.z += this.vel.z;
|
|
81
|
+
this.vel.y *= 0.99;
|
|
82
|
+
this.rocketLifetime -= deltaTime * 0.5;
|
|
83
|
+
if (this.vel.y < 0.2 || this.pos.y >= this.targetY || this.rocketLifetime <= 0) {
|
|
84
|
+
this.explode();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
else if (this.phase === "explode") {
|
|
88
|
+
this.timer += deltaTime;
|
|
89
|
+
if (!this.particles)
|
|
90
|
+
return;
|
|
91
|
+
const isHovering = this.timer < this.config.hoverDuration;
|
|
92
|
+
const gravityFactor = this.smoothstep(this.timer, this.config.hoverDuration, this.config.hoverDuration + 0.5);
|
|
93
|
+
let aliveCount = 0;
|
|
94
|
+
const positions = this.particles.positions;
|
|
95
|
+
const velocities = this.particles.velocities;
|
|
96
|
+
const colors = this.particles.colors;
|
|
97
|
+
const lifetimes = this.particles.lifetimes;
|
|
98
|
+
for (let i = 0; i < this.particles.count; i++) {
|
|
99
|
+
if (lifetimes[i] > 0) {
|
|
100
|
+
aliveCount++;
|
|
101
|
+
const i3 = i * 3;
|
|
102
|
+
// Update position
|
|
103
|
+
positions[i3] += velocities[i3];
|
|
104
|
+
positions[i3 + 1] += velocities[i3 + 1];
|
|
105
|
+
positions[i3 + 2] += velocities[i3 + 2];
|
|
106
|
+
if (isHovering) {
|
|
107
|
+
// Hovering phase - apply friction
|
|
108
|
+
velocities[i3] *= this.config.friction;
|
|
109
|
+
velocities[i3 + 1] *= this.config.friction;
|
|
110
|
+
velocities[i3 + 2] *= this.config.friction;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
// Falling phase - apply gravity and fade
|
|
114
|
+
velocities[i3 + 1] -= this.config.gravity * gravityFactor;
|
|
115
|
+
velocities[i3] *= 0.98;
|
|
116
|
+
velocities[i3 + 1] *= 0.98;
|
|
117
|
+
velocities[i3 + 2] *= 0.98;
|
|
118
|
+
lifetimes[i] -= this.config.fadeSpeed;
|
|
119
|
+
}
|
|
120
|
+
// Update color alpha
|
|
121
|
+
const alpha = Math.max(0, lifetimes[i]);
|
|
122
|
+
if (this.baseColors) {
|
|
123
|
+
colors[i3] = this.baseColors[i3] * alpha * 1.5;
|
|
124
|
+
colors[i3 + 1] = this.baseColors[i3 + 1] * alpha * 1.5;
|
|
125
|
+
colors[i3 + 2] = this.baseColors[i3 + 2] * alpha * 1.5;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (aliveCount === 0) {
|
|
130
|
+
this.phase = "dead";
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
smoothstep(x, edge0, edge1) {
|
|
135
|
+
const t = Math.max(0, Math.min(1, (x - edge0) / (edge1 - edge0)));
|
|
136
|
+
return t * t * (3 - 2 * t);
|
|
137
|
+
}
|
|
138
|
+
explode() {
|
|
139
|
+
this.phase = "explode";
|
|
140
|
+
this.timer = 0;
|
|
141
|
+
this.rocketAlive = false;
|
|
142
|
+
this.justExploded = true; // Mark for audio trigger
|
|
143
|
+
const particleCount = Math.min(this.config.particleCount, MAX_PARTICLES);
|
|
144
|
+
const positions = new Float32Array(particleCount * 3);
|
|
145
|
+
const velocities = new Float32Array(particleCount * 3);
|
|
146
|
+
const colors = new Float32Array(particleCount * 3);
|
|
147
|
+
const lifetimes = new Float32Array(particleCount);
|
|
148
|
+
this.baseColors = new Float32Array(particleCount * 3);
|
|
149
|
+
const baseSpeed = this.config.explosionForce * (0.8 + Math.random() * 0.4);
|
|
150
|
+
for (let i = 0; i < particleCount; i++) {
|
|
151
|
+
const i3 = i * 3;
|
|
152
|
+
// Set initial position to explosion center
|
|
153
|
+
positions[i3] = this.pos.x;
|
|
154
|
+
positions[i3 + 1] = this.pos.y;
|
|
155
|
+
positions[i3 + 2] = this.pos.z;
|
|
156
|
+
// Generate spherical velocity distribution
|
|
157
|
+
const theta = Math.random() * Math.PI * 2;
|
|
158
|
+
const phi = Math.acos(2 * Math.random() - 1);
|
|
159
|
+
const speed = baseSpeed * (0.8 + Math.random() * 0.4);
|
|
160
|
+
velocities[i3] = speed * Math.sin(phi) * Math.cos(theta);
|
|
161
|
+
velocities[i3 + 1] = speed * Math.sin(phi) * Math.sin(theta);
|
|
162
|
+
velocities[i3 + 2] = speed * Math.cos(phi);
|
|
163
|
+
// Pick color from palette and vary brightness
|
|
164
|
+
const targetColor = this.colors[Math.floor(Math.random() * this.colors.length)];
|
|
165
|
+
const brightness = 0.5 + Math.random() * 0.8;
|
|
166
|
+
this.baseColors[i3] = targetColor.x * brightness;
|
|
167
|
+
this.baseColors[i3 + 1] = targetColor.y * brightness;
|
|
168
|
+
this.baseColors[i3 + 2] = targetColor.z * brightness;
|
|
169
|
+
colors[i3] = this.baseColors[i3];
|
|
170
|
+
colors[i3 + 1] = this.baseColors[i3 + 1];
|
|
171
|
+
colors[i3 + 2] = this.baseColors[i3 + 2];
|
|
172
|
+
lifetimes[i] = 1.0;
|
|
173
|
+
}
|
|
174
|
+
this.particles = {
|
|
175
|
+
positions,
|
|
176
|
+
velocities,
|
|
177
|
+
colors,
|
|
178
|
+
lifetimes,
|
|
179
|
+
count: particleCount,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
isDead() {
|
|
183
|
+
return this.phase === "dead";
|
|
184
|
+
}
|
|
185
|
+
isRocket() {
|
|
186
|
+
return this.phase === "rocket" && this.rocketAlive;
|
|
187
|
+
}
|
|
188
|
+
getRocketPosition() {
|
|
189
|
+
return this.pos;
|
|
190
|
+
}
|
|
191
|
+
getRocketColor() {
|
|
192
|
+
return this.colors[0];
|
|
193
|
+
}
|
|
194
|
+
getParticleData() {
|
|
195
|
+
return this.particles;
|
|
196
|
+
}
|
|
197
|
+
hasJustExploded() {
|
|
198
|
+
return this.justExploded;
|
|
199
|
+
}
|
|
200
|
+
clearExplosionFlag() {
|
|
201
|
+
this.justExploded = false;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
export class ParticleSystem {
|
|
205
|
+
constructor(config) {
|
|
206
|
+
this.fireworks = [];
|
|
207
|
+
this.config = { ...DEFAULT_PARTICLE_CONFIG };
|
|
208
|
+
this.maxConcurrentFireworks = 5; // Limit concurrent fireworks for performance
|
|
209
|
+
// Auto-launch settings
|
|
210
|
+
this.autoLaunch = false;
|
|
211
|
+
this.launchInterval = 3000; // ms
|
|
212
|
+
this.lastLaunchTime = 0;
|
|
213
|
+
this.nextLaunchDelay = 0;
|
|
214
|
+
if (config) {
|
|
215
|
+
this.config = { ...this.config, ...config };
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
update(deltaTime) {
|
|
219
|
+
// Update existing fireworks
|
|
220
|
+
for (let i = this.fireworks.length - 1; i >= 0; i--) {
|
|
221
|
+
this.fireworks[i].update(deltaTime);
|
|
222
|
+
if (this.fireworks[i].isDead()) {
|
|
223
|
+
this.fireworks.splice(i, 1);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
// Auto-launch
|
|
227
|
+
if (this.autoLaunch) {
|
|
228
|
+
const now = performance.now();
|
|
229
|
+
if (now - this.lastLaunchTime > this.nextLaunchDelay) {
|
|
230
|
+
this.lastLaunchTime = now;
|
|
231
|
+
this.nextLaunchDelay = this.launchInterval + Math.random() * 1000;
|
|
232
|
+
this.spawnFirework();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
spawnFirework(x) {
|
|
237
|
+
// Don't spawn if we're at the limit (for performance)
|
|
238
|
+
if (this.fireworks.length >= this.maxConcurrentFireworks) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
const startX = x !== undefined ? x : (Math.random() - 0.5) * 5;
|
|
242
|
+
this.fireworks.push(new Firework(startX, this.config));
|
|
243
|
+
}
|
|
244
|
+
getFireworks() {
|
|
245
|
+
return this.fireworks;
|
|
246
|
+
}
|
|
247
|
+
setAutoLaunch(enabled) {
|
|
248
|
+
this.autoLaunch = enabled;
|
|
249
|
+
if (enabled) {
|
|
250
|
+
this.lastLaunchTime = performance.now();
|
|
251
|
+
this.nextLaunchDelay = 0;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
setConfig(config) {
|
|
255
|
+
this.config = { ...this.config, ...config };
|
|
256
|
+
}
|
|
257
|
+
getConfig() {
|
|
258
|
+
return { ...this.config };
|
|
259
|
+
}
|
|
260
|
+
setMaxConcurrentFireworks(max) {
|
|
261
|
+
this.maxConcurrentFireworks = Math.max(1, max);
|
|
262
|
+
}
|
|
263
|
+
getMaxConcurrentFireworks() {
|
|
264
|
+
return this.maxConcurrentFireworks;
|
|
265
|
+
}
|
|
266
|
+
}
|
package/dist/physics.d.ts
CHANGED
|
@@ -72,8 +72,8 @@ export declare class Physics {
|
|
|
72
72
|
private createAmmoRigidbodies;
|
|
73
73
|
private createAmmoJoints;
|
|
74
74
|
private normalizeAngle;
|
|
75
|
-
reset(boneWorldMatrices:
|
|
76
|
-
step(dt: number, boneWorldMatrices:
|
|
75
|
+
reset(boneWorldMatrices: Mat4[], boneInverseBindMatrices: Float32Array): void;
|
|
76
|
+
step(dt: number, boneWorldMatrices: Mat4[], boneInverseBindMatrices: Float32Array): void;
|
|
77
77
|
private computeBodyOffsets;
|
|
78
78
|
private positionBodiesFromBones;
|
|
79
79
|
private syncFromBones;
|
package/dist/physics.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"physics.d.ts","sourceRoot":"","sources":["../src/physics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAIzC,oBAAY,cAAc;IACxB,MAAM,IAAI;IACV,GAAG,IAAI;IACP,OAAO,IAAI;CACZ;AAED,oBAAY,aAAa;IACvB,MAAM,IAAI;IACV,OAAO,IAAI;IACX,SAAS,IAAI;CACd;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,MAAM,CAAA;IACrB,KAAK,EAAE,cAAc,CAAA;IACrB,IAAI,EAAE,IAAI,CAAA;IACV,aAAa,EAAE,IAAI,CAAA;IACnB,aAAa,EAAE,IAAI,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,MAAM,CAAA;IACrB,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,aAAa,CAAA;IACnB,uBAAuB,EAAE,IAAI,CAAA;IAC7B,gBAAgB,CAAC,EAAE,IAAI,CAAA;CACxB;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,eAAe,EAAE,MAAM,CAAA;IACvB,eAAe,EAAE,MAAM,CAAA;IACvB,QAAQ,EAAE,IAAI,CAAA;IACd,QAAQ,EAAE,IAAI,CAAA;IACd,WAAW,EAAE,IAAI,CAAA;IACjB,WAAW,EAAE,IAAI,CAAA;IACjB,WAAW,EAAE,IAAI,CAAA;IACjB,WAAW,EAAE,IAAI,CAAA;IACjB,cAAc,EAAE,IAAI,CAAA;IACpB,cAAc,EAAE,IAAI,CAAA;CACrB;AAED,qBAAa,OAAO;IAClB,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,WAAW,CAAqC;IACxD,OAAO,CAAC,IAAI,CAA4B;IAExC,OAAO,CAAC,aAAa,CAAY;IAEjC,OAAO,CAAC,eAAe,CAAY;IAEnC,OAAO,CAAC,eAAe,CAAY;IACnC,OAAO,CAAC,sBAAsB,CAAQ;IACtC,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,UAAU,CAAO;IACzB,OAAO,CAAC,oCAAoC,CAAO;IAEnD,OAAO,CAAC,UAAU,CAAY;gBAElB,WAAW,EAAE,SAAS,EAAE,EAAE,MAAM,GAAE,KAAK,EAAO;YAM5C,QAAQ;IAatB,UAAU,CAAC,OAAO,EAAE,IAAI,GAAG,IAAI;IAU/B,UAAU,IAAI,IAAI;IAIlB,cAAc,IAAI,SAAS,EAAE;IAI7B,SAAS,IAAI,KAAK,EAAE;IAIpB,sBAAsB,IAAI,KAAK,CAAC;QAAE,QAAQ,EAAE,IAAI,CAAC;QAAC,QAAQ,EAAE,IAAI,CAAA;KAAE,CAAC;IA6CnE,OAAO,CAAC,eAAe;IAwBvB,OAAO,CAAC,qBAAqB;IA+F7B,OAAO,CAAC,gBAAgB;IA0KxB,OAAO,CAAC,cAAc;IAetB,KAAK,CAAC,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"physics.d.ts","sourceRoot":"","sources":["../src/physics.ts"],"names":[],"mappings":"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"}
|
package/dist/physics.js
CHANGED
|
@@ -336,7 +336,7 @@ export class Physics {
|
|
|
336
336
|
if (!this.ammoInitialized || !this.ammo || !this.dynamicsWorld) {
|
|
337
337
|
return;
|
|
338
338
|
}
|
|
339
|
-
const boneCount = boneWorldMatrices.length
|
|
339
|
+
const boneCount = boneWorldMatrices.length;
|
|
340
340
|
const Ammo = this.ammo;
|
|
341
341
|
// Ensure body offsets are computed
|
|
342
342
|
if (!this.rigidbodiesInitialized) {
|
|
@@ -351,9 +351,8 @@ export class Physics {
|
|
|
351
351
|
if (!ammoBody || rb.boneIndex < 0 || rb.boneIndex >= boneCount)
|
|
352
352
|
continue;
|
|
353
353
|
const boneIdx = rb.boneIndex;
|
|
354
|
-
const worldMatIdx = boneIdx * 16;
|
|
355
354
|
// Get bone world matrix
|
|
356
|
-
const boneWorldMat =
|
|
355
|
+
const boneWorldMat = boneWorldMatrices[boneIdx];
|
|
357
356
|
// Compute body world matrix: bodyWorld = boneWorld × bodyOffsetMatrix
|
|
358
357
|
// (like babylon-mmd: bodyWorldMatrix = bodyOffsetMatrix.multiplyToRef(bodyWorldMatrix))
|
|
359
358
|
const bodyOffsetMatrix = rb.bodyOffsetMatrix || rb.bodyOffsetMatrixInverse.inverse();
|
|
@@ -394,7 +393,7 @@ export class Physics {
|
|
|
394
393
|
if (!this.ammoInitialized || !this.ammo || !this.dynamicsWorld) {
|
|
395
394
|
return;
|
|
396
395
|
}
|
|
397
|
-
const boneCount = boneWorldMatrices.length
|
|
396
|
+
const boneCount = boneWorldMatrices.length;
|
|
398
397
|
if (this.firstFrame) {
|
|
399
398
|
if (!this.rigidbodiesInitialized) {
|
|
400
399
|
this.computeBodyOffsets(boneInverseBindMatrices, boneCount);
|
|
@@ -451,8 +450,7 @@ export class Physics {
|
|
|
451
450
|
if (!ammoBody || rb.boneIndex < 0 || rb.boneIndex >= boneCount)
|
|
452
451
|
continue;
|
|
453
452
|
const boneIdx = rb.boneIndex;
|
|
454
|
-
const
|
|
455
|
-
const boneWorldMat = new Mat4(boneWorldMatrices.subarray(worldMatIdx, worldMatIdx + 16));
|
|
453
|
+
const boneWorldMat = boneWorldMatrices[boneIdx];
|
|
456
454
|
// nodeWorld = boneWorld × shapeLocal (not shapeLocal × boneWorld)
|
|
457
455
|
const bodyOffsetMatrix = rb.bodyOffsetMatrix || rb.bodyOffsetMatrixInverse.inverse();
|
|
458
456
|
const nodeWorldMatrix = boneWorldMat.multiply(bodyOffsetMatrix);
|
|
@@ -494,8 +492,7 @@ export class Physics {
|
|
|
494
492
|
rb.boneIndex >= 0 &&
|
|
495
493
|
rb.boneIndex < boneCount) {
|
|
496
494
|
const boneIdx = rb.boneIndex;
|
|
497
|
-
const
|
|
498
|
-
const boneWorldMat = new Mat4(boneWorldMatrices.subarray(worldMatIdx, worldMatIdx + 16));
|
|
495
|
+
const boneWorldMat = boneWorldMatrices[boneIdx];
|
|
499
496
|
// nodeWorld = boneWorld × shapeLocal (not shapeLocal × boneWorld)
|
|
500
497
|
const bodyOffsetMatrix = rb.bodyOffsetMatrix || rb.bodyOffsetMatrixInverse.inverse();
|
|
501
498
|
const nodeWorldMatrix = boneWorldMat.multiply(bodyOffsetMatrix);
|
|
@@ -539,7 +536,6 @@ export class Physics {
|
|
|
539
536
|
// Only dynamic rigidbodies drive bones (Static/Kinematic follow bones)
|
|
540
537
|
if (rb.type === RigidbodyType.Dynamic && rb.boneIndex >= 0 && rb.boneIndex < boneCount) {
|
|
541
538
|
const boneIdx = rb.boneIndex;
|
|
542
|
-
const worldMatIdx = boneIdx * 16;
|
|
543
539
|
const transform = ammoBody.getWorldTransform();
|
|
544
540
|
const origin = transform.getOrigin();
|
|
545
541
|
const rotation = transform.getRotation();
|
|
@@ -550,7 +546,7 @@ export class Physics {
|
|
|
550
546
|
const boneWorldMat = nodeWorldMatrix.multiply(rb.bodyOffsetMatrixInverse);
|
|
551
547
|
const values = boneWorldMat.values;
|
|
552
548
|
if (!isNaN(values[0]) && !isNaN(values[15]) && Math.abs(values[0]) < 1e6 && Math.abs(values[15]) < 1e6) {
|
|
553
|
-
boneWorldMatrices.set(values
|
|
549
|
+
boneWorldMatrices[boneIdx].values.set(values);
|
|
554
550
|
}
|
|
555
551
|
else {
|
|
556
552
|
console.warn(`[Physics] Invalid bone world matrix for rigidbody ${i} (${rb.name}), skipping update`);
|