reze-engine 0.3.4 → 0.3.6
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/dist/ammo-loader.d.ts +0 -1
- package/dist/ammo-loader.d.ts.map +1 -1
- package/dist/ammo-loader.js +0 -3
- package/dist/engine.d.ts +2 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +44 -100
- package/dist/ik-solver.d.ts +7 -2
- package/dist/ik-solver.d.ts.map +1 -1
- package/dist/ik-solver.js +110 -137
- package/dist/math.d.ts +10 -6
- package/dist/math.d.ts.map +1 -1
- package/dist/math.js +36 -62
- package/dist/model.d.ts +1 -19
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +24 -93
- package/dist/player.d.ts +6 -20
- package/dist/player.d.ts.map +1 -1
- package/dist/player.js +89 -193
- package/package.json +1 -1
- package/src/ammo-loader.ts +0 -4
- package/src/engine.ts +54 -101
- package/src/ik-solver.ts +121 -178
- package/src/math.ts +43 -82
- package/src/model.ts +26 -101
- package/src/player.ts +116 -212
- package/src/bezier-interpolate.ts +0 -47
- package/src/ik.ts +0 -449
package/src/model.ts
CHANGED
|
@@ -50,24 +50,6 @@ export interface IKLink {
|
|
|
50
50
|
hasLimit: boolean
|
|
51
51
|
minAngle?: Vec3 // Minimum Euler angles (radians)
|
|
52
52
|
maxAngle?: Vec3 // Maximum Euler angles (radians)
|
|
53
|
-
rotationOrder?: EulerRotationOrder // YXZ, ZYX, or XZY
|
|
54
|
-
solveAxis?: SolveAxis // None, Fixed, X, Y, or Z
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Euler rotation order for angle constraints
|
|
58
|
-
export enum EulerRotationOrder {
|
|
59
|
-
YXZ = 0,
|
|
60
|
-
ZYX = 1,
|
|
61
|
-
XZY = 2,
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Solve axis optimization
|
|
65
|
-
export enum SolveAxis {
|
|
66
|
-
None = 0,
|
|
67
|
-
Fixed = 1,
|
|
68
|
-
X = 2,
|
|
69
|
-
Y = 3,
|
|
70
|
-
Z = 4,
|
|
71
53
|
}
|
|
72
54
|
|
|
73
55
|
// IK solver definition
|
|
@@ -78,7 +60,6 @@ export interface IKSolver {
|
|
|
78
60
|
iterationCount: number
|
|
79
61
|
limitAngle: number // Max rotation per iteration (radians)
|
|
80
62
|
links: IKLink[] // Chain bones from effector to root
|
|
81
|
-
canSkipWhenPhysicsEnabled: boolean
|
|
82
63
|
}
|
|
83
64
|
|
|
84
65
|
// IK chain info per bone (runtime state)
|
|
@@ -128,7 +109,6 @@ export interface SkeletonRuntime {
|
|
|
128
109
|
localRotations: Float32Array // quat per bone (x,y,z,w) length = boneCount*4
|
|
129
110
|
localTranslations: Float32Array // vec3 per bone length = boneCount*3
|
|
130
111
|
worldMatrices: Float32Array // mat4 per bone length = boneCount*16
|
|
131
|
-
computedBones: boolean[] // length = boneCount
|
|
132
112
|
ikChainInfo?: IKChainInfo[] // IK chain info per bone (only for IK chain bones)
|
|
133
113
|
ikSolvers?: IKSolver[] // All IK solvers in the model
|
|
134
114
|
}
|
|
@@ -245,7 +225,6 @@ export class Model {
|
|
|
245
225
|
acc[bone.name] = index
|
|
246
226
|
return acc
|
|
247
227
|
}, {} as Record<string, number>),
|
|
248
|
-
computedBones: new Array(boneCount).fill(false),
|
|
249
228
|
}
|
|
250
229
|
|
|
251
230
|
const rotations = this.runtimeSkeleton.localRotations
|
|
@@ -283,18 +262,6 @@ export class Model {
|
|
|
283
262
|
for (let i = 0; i < boneCount; i++) {
|
|
284
263
|
const bone = bones[i]
|
|
285
264
|
if (bone.ikTargetIndex !== undefined && bone.ikLinks && bone.ikLinks.length > 0) {
|
|
286
|
-
// Check if all links are affected by physics (for optimization)
|
|
287
|
-
let canSkipWhenPhysicsEnabled = true
|
|
288
|
-
for (const link of bone.ikLinks) {
|
|
289
|
-
// For now, assume no bones are physics-controlled (can be enhanced later)
|
|
290
|
-
// If a bone has a rigidbody attached, it's physics-controlled
|
|
291
|
-
const hasPhysics = this.rigidbodies.some((rb) => rb.boneIndex === link.boneIndex)
|
|
292
|
-
if (!hasPhysics) {
|
|
293
|
-
canSkipWhenPhysicsEnabled = false
|
|
294
|
-
break
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
265
|
const solver: IKSolver = {
|
|
299
266
|
index: solverIndex++,
|
|
300
267
|
ikBoneIndex: i,
|
|
@@ -302,7 +269,6 @@ export class Model {
|
|
|
302
269
|
iterationCount: bone.ikIteration ?? 1,
|
|
303
270
|
limitAngle: bone.ikLimitAngle ?? Math.PI,
|
|
304
271
|
links: bone.ikLinks,
|
|
305
|
-
canSkipWhenPhysicsEnabled,
|
|
306
272
|
}
|
|
307
273
|
ikSolvers.push(solver)
|
|
308
274
|
}
|
|
@@ -313,35 +279,24 @@ export class Model {
|
|
|
313
279
|
}
|
|
314
280
|
|
|
315
281
|
private initializeRotTweenBuffers(): void {
|
|
316
|
-
|
|
317
|
-
this.rotTweenState = {
|
|
318
|
-
active: new Uint8Array(n),
|
|
319
|
-
startQuat: new Float32Array(n * 4),
|
|
320
|
-
targetQuat: new Float32Array(n * 4),
|
|
321
|
-
startTimeMs: new Float32Array(n),
|
|
322
|
-
durationMs: new Float32Array(n),
|
|
323
|
-
}
|
|
282
|
+
this.rotTweenState = this.createTweenState(this.skeleton.bones.length, 4, 4)
|
|
324
283
|
}
|
|
325
284
|
|
|
326
285
|
private initializeTransTweenBuffers(): void {
|
|
327
|
-
|
|
328
|
-
this.transTweenState = {
|
|
329
|
-
active: new Uint8Array(n),
|
|
330
|
-
startVec: new Float32Array(n * 3),
|
|
331
|
-
targetVec: new Float32Array(n * 3),
|
|
332
|
-
startTimeMs: new Float32Array(n),
|
|
333
|
-
durationMs: new Float32Array(n),
|
|
334
|
-
}
|
|
286
|
+
this.transTweenState = this.createTweenState(this.skeleton.bones.length, 3, 3)
|
|
335
287
|
}
|
|
336
288
|
|
|
337
289
|
private initializeMorphTweenBuffers(): void {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
290
|
+
this.morphTweenState = this.createTweenState(this.morphing.morphs.length, 1, 1)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
private createTweenState(count: number, startSize: number, targetSize: number): any {
|
|
294
|
+
return {
|
|
295
|
+
active: new Uint8Array(count),
|
|
296
|
+
startQuat: new Float32Array(count * startSize),
|
|
297
|
+
targetQuat: new Float32Array(count * targetSize),
|
|
298
|
+
startTimeMs: new Float32Array(count),
|
|
299
|
+
durationMs: new Float32Array(count),
|
|
345
300
|
}
|
|
346
301
|
}
|
|
347
302
|
|
|
@@ -444,33 +399,22 @@ export class Model {
|
|
|
444
399
|
return hasActiveTweens
|
|
445
400
|
}
|
|
446
401
|
|
|
447
|
-
// Get interleaved vertex data for GPU upload
|
|
448
|
-
// Format: [x,y,z, nx,ny,nz, u,v, x,y,z, nx,ny,nz, u,v, ...]
|
|
449
402
|
getVertices(): Float32Array<ArrayBuffer> {
|
|
450
403
|
return this.vertexData
|
|
451
404
|
}
|
|
452
405
|
|
|
453
|
-
// Get texture information
|
|
454
406
|
getTextures(): Texture[] {
|
|
455
407
|
return this.textures
|
|
456
408
|
}
|
|
457
409
|
|
|
458
|
-
// Get material information
|
|
459
410
|
getMaterials(): Material[] {
|
|
460
411
|
return this.materials
|
|
461
412
|
}
|
|
462
413
|
|
|
463
|
-
// Get vertex count
|
|
464
|
-
getVertexCount(): number {
|
|
465
|
-
return this.vertexCount
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
// Get index data for GPU upload
|
|
469
414
|
getIndices(): Uint32Array<ArrayBuffer> {
|
|
470
415
|
return this.indexData
|
|
471
416
|
}
|
|
472
417
|
|
|
473
|
-
// Accessors for skeleton/skinning
|
|
474
418
|
getSkeleton(): Skeleton {
|
|
475
419
|
return this.skeleton
|
|
476
420
|
}
|
|
@@ -479,7 +423,6 @@ export class Model {
|
|
|
479
423
|
return this.skinning
|
|
480
424
|
}
|
|
481
425
|
|
|
482
|
-
// Accessors for physics data
|
|
483
426
|
getRigidbodies(): Rigidbody[] {
|
|
484
427
|
return this.rigidbodies
|
|
485
428
|
}
|
|
@@ -488,7 +431,6 @@ export class Model {
|
|
|
488
431
|
return this.joints
|
|
489
432
|
}
|
|
490
433
|
|
|
491
|
-
// Accessors for morphing
|
|
492
434
|
getMorphing(): Morphing {
|
|
493
435
|
return this.morphing
|
|
494
436
|
}
|
|
@@ -499,10 +441,6 @@ export class Model {
|
|
|
499
441
|
|
|
500
442
|
// ------- Bone helpers (public API) -------
|
|
501
443
|
|
|
502
|
-
getBoneNames(): string[] {
|
|
503
|
-
return this.skeleton.bones.map((b) => b.name)
|
|
504
|
-
}
|
|
505
|
-
|
|
506
444
|
rotateBones(names: string[], quats: Quat[], durationMs?: number): void {
|
|
507
445
|
const state = this.rotTweenState
|
|
508
446
|
const normalized = quats.map((q) => q.normalize())
|
|
@@ -550,14 +488,10 @@ export class Model {
|
|
|
550
488
|
state.targetQuat[qi + 3]
|
|
551
489
|
)
|
|
552
490
|
const result = Quat.slerp(startQuat, targetQuat, e)
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
sx = cx
|
|
558
|
-
sy = cy
|
|
559
|
-
sz = cz
|
|
560
|
-
sw = cw
|
|
491
|
+
sx = result.x
|
|
492
|
+
sy = result.y
|
|
493
|
+
sz = result.z
|
|
494
|
+
sw = result.w
|
|
561
495
|
}
|
|
562
496
|
|
|
563
497
|
state.startQuat[qi] = sx
|
|
@@ -684,10 +618,6 @@ export class Model {
|
|
|
684
618
|
return this.skeleton.inverseBindMatrices
|
|
685
619
|
}
|
|
686
620
|
|
|
687
|
-
getMorphNames(): string[] {
|
|
688
|
-
return this.morphing.morphs.map((m) => m.name)
|
|
689
|
-
}
|
|
690
|
-
|
|
691
621
|
setMorphWeight(name: string, weight: number, durationMs?: number): void {
|
|
692
622
|
const idx = this.runtimeMorph.nameIndex[name] ?? -1
|
|
693
623
|
if (idx < 0 || idx >= this.runtimeMorph.weights.length) return
|
|
@@ -706,10 +636,9 @@ export class Model {
|
|
|
706
636
|
// Animated change
|
|
707
637
|
const state = this.morphTweenState
|
|
708
638
|
const now = performance.now()
|
|
709
|
-
const currentWeight = this.runtimeMorph.weights[idx]
|
|
710
639
|
|
|
711
640
|
// If already tweening, start from current interpolated value
|
|
712
|
-
let startWeight =
|
|
641
|
+
let startWeight = this.runtimeMorph.weights[idx]
|
|
713
642
|
if (state.active[idx] === 1) {
|
|
714
643
|
const startMs = state.startTimeMs[idx]
|
|
715
644
|
const prevDur = Math.max(1, state.durationMs[idx])
|
|
@@ -802,13 +731,13 @@ export class Model {
|
|
|
802
731
|
this.applyMorphs()
|
|
803
732
|
}
|
|
804
733
|
|
|
805
|
-
// Compute initial world matrices (needed for IK solving)
|
|
734
|
+
// Compute initial world matrices (needed for IK solving to read bone positions)
|
|
806
735
|
this.computeWorldMatrices()
|
|
807
736
|
|
|
808
|
-
// Solve IK chains (modifies localRotations)
|
|
737
|
+
// Solve IK chains (modifies localRotations with final IK rotations)
|
|
809
738
|
this.solveIKChains()
|
|
810
739
|
|
|
811
|
-
// Recompute world matrices with IK rotations applied
|
|
740
|
+
// Recompute world matrices with final IK rotations applied to localRotations
|
|
812
741
|
this.computeWorldMatrices()
|
|
813
742
|
|
|
814
743
|
return hasActiveMorphTweens
|
|
@@ -827,8 +756,7 @@ export class Model {
|
|
|
827
756
|
this.runtimeSkeleton.localRotations,
|
|
828
757
|
this.runtimeSkeleton.localTranslations,
|
|
829
758
|
this.runtimeSkeleton.worldMatrices,
|
|
830
|
-
ikChainInfo
|
|
831
|
-
false // usePhysics - can be enhanced later
|
|
759
|
+
ikChainInfo
|
|
832
760
|
)
|
|
833
761
|
}
|
|
834
762
|
|
|
@@ -837,11 +765,13 @@ export class Model {
|
|
|
837
765
|
const localRot = this.runtimeSkeleton.localRotations
|
|
838
766
|
const localTrans = this.runtimeSkeleton.localTranslations
|
|
839
767
|
const worldBuf = this.runtimeSkeleton.worldMatrices
|
|
840
|
-
const computed = this.runtimeSkeleton.computedBones.fill(false)
|
|
841
768
|
const boneCount = bones.length
|
|
842
769
|
|
|
843
770
|
if (boneCount === 0) return
|
|
844
771
|
|
|
772
|
+
// Local computed array (avoids instance field overhead)
|
|
773
|
+
const computed = new Array<boolean>(boneCount).fill(false)
|
|
774
|
+
|
|
845
775
|
const computeWorld = (i: number): void => {
|
|
846
776
|
if (computed[i]) return
|
|
847
777
|
|
|
@@ -880,14 +810,9 @@ export class Model {
|
|
|
880
810
|
ay = -ay
|
|
881
811
|
az = -az
|
|
882
812
|
}
|
|
883
|
-
const identityQuat = new Quat(0, 0, 0, 1)
|
|
884
813
|
const appendQuat = new Quat(ax, ay, az, aw)
|
|
885
|
-
const result = Quat.slerp(
|
|
886
|
-
|
|
887
|
-
const ry = result.y
|
|
888
|
-
const rz = result.z
|
|
889
|
-
const rw = result.w
|
|
890
|
-
rotateM = Mat4.fromQuat(rx, ry, rz, rw).multiply(rotateM)
|
|
814
|
+
const result = Quat.slerp(new Quat(0, 0, 0, 1), appendQuat, absRatio)
|
|
815
|
+
rotateM = Mat4.fromQuat(result.x, result.y, result.z, result.w).multiply(rotateM)
|
|
891
816
|
}
|
|
892
817
|
|
|
893
818
|
if (b.appendMove) {
|