reze-engine 0.13.0 → 0.13.2

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/src/physics.ts CHANGED
@@ -1,4 +1,11 @@
1
1
  import { Quat, Vec3, Mat4 } from "./math"
2
+
3
+ // Physics-local scratch pool for per-frame sync (syncFromBones, applyAmmoRigidbodiesToBones).
4
+ // Each method uses only these slots and completes synchronously before the next is called.
5
+ const _physMat: Float32Array[] = [
6
+ new Float32Array(16), new Float32Array(16), new Float32Array(16),
7
+ ]
8
+ const _physQuat = new Quat(0, 0, 0, 1)
2
9
  import { loadAmmo } from "./ammo-loader"
3
10
  import type { AmmoInstance } from "@fred3d/ammo"
4
11
 
@@ -500,11 +507,11 @@ export class Physics {
500
507
  }
501
508
 
502
509
  // Step order: 1) Sync Static/Kinematic from bones, 2) Step physics, 3) Apply dynamic to bones
503
- this.syncFromBones(boneWorldMatrices, boneInverseBindMatrices, boneCount)
510
+ this.syncFromBones(boneWorldMatrices, boneCount)
504
511
 
505
512
  this.stepAmmoPhysics(dt)
506
513
 
507
- this.applyAmmoRigidbodiesToBones(boneWorldMatrices, boneInverseBindMatrices, boneCount)
514
+ this.applyAmmoRigidbodiesToBones(boneWorldMatrices, boneCount)
508
515
  }
509
516
 
510
517
  // Compute bodyOffsetMatrixInverse for all rigidbodies (called once during initialization)
@@ -583,7 +590,7 @@ export class Physics {
583
590
  }
584
591
 
585
592
  // Sync Static (FollowBone) and Kinematic rigidbodies to follow bone transforms
586
- private syncFromBones(boneWorldMatrices: Mat4[], boneInverseBindMatrices: Float32Array, boneCount: number): void {
593
+ private syncFromBones(boneWorldMatrices: Mat4[], boneCount: number): void {
587
594
  if (!this.ammo || !this.dynamicsWorld) return
588
595
 
589
596
  const Ammo = this.ammo
@@ -602,16 +609,18 @@ export class Physics {
602
609
  const boneIdx = rb.boneIndex
603
610
  const boneWorldMat = boneWorldMatrices[boneIdx]
604
611
 
605
- // nodeWorld = boneWorld × shapeLocal (not shapeLocal × boneWorld)
606
- const bodyOffsetMatrix = rb.bodyOffsetMatrix || rb.bodyOffsetMatrixInverse.inverse()
607
- const nodeWorldMatrix = boneWorldMat.multiply(bodyOffsetMatrix)
612
+ // Lazy-cache bodyOffsetMatrix on first hit (cold path).
613
+ if (!rb.bodyOffsetMatrix) rb.bodyOffsetMatrix = rb.bodyOffsetMatrixInverse.inverse()
608
614
 
609
- const worldPos = nodeWorldMatrix.getPosition()
610
- const worldRot = nodeWorldMatrix.toQuat()
615
+ // nodeWorld = boneWorld × bodyOffsetMatrix → _physMat[0]
616
+ Mat4.multiplyArrays(boneWorldMat.values, 0, rb.bodyOffsetMatrix.values, 0, _physMat[0], 0)
617
+ const nodeVals = _physMat[0]
618
+ const wx = nodeVals[12], wy = nodeVals[13], wz = nodeVals[14]
619
+ Mat4.toQuatFromArrayInto(nodeVals, 0, _physQuat)
611
620
 
612
621
  const transform = new Ammo.btTransform()
613
- const pos = new Ammo.btVector3(worldPos.x, worldPos.y, worldPos.z)
614
- const quat = new Ammo.btQuaternion(worldRot.x, worldRot.y, worldRot.z, worldRot.w)
622
+ const pos = new Ammo.btVector3(wx, wy, wz)
623
+ const quat = new Ammo.btQuaternion(_physQuat.x, _physQuat.y, _physQuat.z, _physQuat.w)
615
624
 
616
625
  transform.setOrigin(pos)
617
626
  transform.setRotation(quat)
@@ -643,11 +652,7 @@ export class Physics {
643
652
  }
644
653
 
645
654
  // Apply dynamic rigidbody world transforms to bone world matrices in-place
646
- private applyAmmoRigidbodiesToBones(
647
- boneWorldMatrices: Mat4[],
648
- boneInverseBindMatrices: Float32Array,
649
- boneCount: number
650
- ): void {
655
+ private applyAmmoRigidbodiesToBones(boneWorldMatrices: Mat4[], boneCount: number): void {
651
656
  if (!this.ammo || !this.dynamicsWorld) return
652
657
 
653
658
  for (let i = 0; i < this.rigidbodies.length; i++) {
@@ -663,16 +668,19 @@ export class Physics {
663
668
  const origin = transform.getOrigin()
664
669
  const rotation = transform.getRotation()
665
670
 
666
- const nodePos = new Vec3(origin.x(), origin.y(), origin.z())
667
- const nodeRot = new Quat(rotation.x(), rotation.y(), rotation.z(), rotation.w())
668
- const nodeWorldMatrix = Mat4.fromPositionRotation(nodePos, nodeRot)
671
+ // nodeWorldMatrix _physMat[0] (from ammo position/rotation directly)
672
+ Mat4.fromPositionRotationInto(
673
+ origin.x(), origin.y(), origin.z(),
674
+ rotation.x(), rotation.y(), rotation.z(), rotation.w(),
675
+ _physMat[0]
676
+ )
669
677
 
670
- // boneWorld = nodeWorld × bodyOffsetMatrixInverse (not bodyOffsetMatrixInverse × nodeWorld)
671
- const boneWorldMat = nodeWorldMatrix.multiply(rb.bodyOffsetMatrixInverse)
678
+ // boneWorld = nodeWorld × bodyOffsetMatrixInverse _physMat[1]
679
+ const boneVals = _physMat[1]
680
+ Mat4.multiplyArrays(_physMat[0], 0, rb.bodyOffsetMatrixInverse.values, 0, boneVals, 0)
672
681
 
673
- const values = boneWorldMat.values
674
- if (!isNaN(values[0]) && !isNaN(values[15]) && Math.abs(values[0]) < 1e6 && Math.abs(values[15]) < 1e6) {
675
- boneWorldMatrices[boneIdx].values.set(values)
682
+ if (!isNaN(boneVals[0]) && !isNaN(boneVals[15]) && Math.abs(boneVals[0]) < 1e6 && Math.abs(boneVals[15]) < 1e6) {
683
+ boneWorldMatrices[boneIdx].values.set(boneVals)
676
684
  } else {
677
685
  console.warn(`[Physics] Invalid bone world matrix for rigidbody ${i} (${rb.name}), skipping update`)
678
686
  }