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/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
- const n = this.skeleton.bones.length
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
- const n = this.skeleton.bones.length
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
- const n = this.morphing.morphs.length
339
- this.morphTweenState = {
340
- active: new Uint8Array(n),
341
- startWeight: new Float32Array(n),
342
- targetWeight: new Float32Array(n),
343
- startTimeMs: new Float32Array(n),
344
- durationMs: new Float32Array(n),
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
- const cx = result.x
554
- const cy = result.y
555
- const cz = result.z
556
- const cw = result.w
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 = currentWeight
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(identityQuat, appendQuat, absRatio)
886
- const rx = result.x
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) {