reze-engine 0.9.5 → 0.10.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/src/engine.ts CHANGED
@@ -81,7 +81,7 @@ interface ModelInstance {
81
81
  export class Engine {
82
82
  private static instance: Engine | null = null
83
83
 
84
- public static getInstance(): Engine {
84
+ static getInstance(): Engine {
85
85
  if (!Engine.instance) {
86
86
  throw new Error("Engine not ready: create Engine, await init(), then load models via engine.loadModel().")
87
87
  }
@@ -199,7 +199,7 @@ export class Engine {
199
199
  }
200
200
 
201
201
  // Step 1: Get WebGPU device and context
202
- public async init() {
202
+ async init() {
203
203
  const adapter = await navigator.gpu?.requestAdapter()
204
204
  const device = await adapter?.requestDevice()
205
205
  if (!device) {
@@ -747,7 +747,7 @@ export class Engine {
747
747
  // Screen-stable edgeline: extrusion ∝ camera distance (same idea as MMD viewers / babylon-mmd-style scaling)
748
748
  let camDist = max(length(camera.viewPos - worldPos), 0.25);
749
749
  let refDist = 30.0;
750
- let edgeScale = 0.032;
750
+ let edgeScale = 0.025;
751
751
  let expandedPos = worldPos + worldNormal * material.edgeSize * edgeScale * (camDist / refDist);
752
752
  output.position = camera.projection * camera.view * vec4f(expandedPos, 1.0);
753
753
  return output;
@@ -972,10 +972,10 @@ export class Engine {
972
972
  }
973
973
 
974
974
  /** Set static camera look-at / orbit center. Clears any model follow binding. */
975
- public setCameraTarget(v: Vec3): void
975
+ setCameraTarget(v: Vec3): void
976
976
  /** Bind camera orbit center to a model's bone (Souls-style follow cam). Pass null to unbind. */
977
- public setCameraTarget(model: Model | null, boneName: string, offset?: Vec3): void
978
- public setCameraTarget(modelOrVec: Model | Vec3 | null, boneName?: string, offset?: Vec3): void {
977
+ setCameraTarget(model: Model | null, boneName: string, offset?: Vec3): void
978
+ setCameraTarget(modelOrVec: Model | Vec3 | null, boneName?: string, offset?: Vec3): void {
979
979
  if (modelOrVec === null) {
980
980
  this.cameraTargetModel = null
981
981
  return
@@ -995,7 +995,7 @@ export class Engine {
995
995
  }
996
996
 
997
997
  /** Souls-style follow cam: orbit center tracks a model bone each frame. Shorthand for setCameraTarget(model, boneName, offset). */
998
- public setCameraFollow(model: Model | null, boneName?: string, offset?: Vec3): void {
998
+ setCameraFollow(model: Model | null, boneName?: string, offset?: Vec3): void {
999
999
  if (model === null) {
1000
1000
  this.cameraTargetModel = null
1001
1001
  return
@@ -1007,12 +1007,12 @@ export class Engine {
1007
1007
  this.cameraTargetOffset.z = offset?.z ?? 0
1008
1008
  }
1009
1009
 
1010
- public getCameraDistance(): number { return this.camera.radius }
1011
- public setCameraDistance(d: number): void { this.camera.radius = d }
1012
- public getCameraAlpha(): number { return this.camera.alpha }
1013
- public setCameraAlpha(a: number): void { this.camera.alpha = a }
1014
- public getCameraBeta(): number { return this.camera.beta }
1015
- public setCameraBeta(b: number): void { this.camera.beta = b }
1010
+ getCameraDistance(): number { return this.camera.radius }
1011
+ setCameraDistance(d: number): void { this.camera.radius = d }
1012
+ getCameraAlpha(): number { return this.camera.alpha }
1013
+ setCameraAlpha(a: number): void { this.camera.alpha = a }
1014
+ getCameraBeta(): number { return this.camera.beta }
1015
+ setCameraBeta(b: number): void { this.camera.beta = b }
1016
1016
 
1017
1017
  // Step 5: Create lighting buffers
1018
1018
  private setupLighting() {
@@ -1039,16 +1039,6 @@ export class Engine {
1039
1039
  this.updateLightBuffer()
1040
1040
  }
1041
1041
 
1042
- public clearLights() {
1043
- this.lightCount = 0
1044
- // Clear all light data by setting intensity to 0
1045
- for (let i = 0; i < 4; i++) {
1046
- const baseIndex = 4 + i * 8
1047
- this.lightData[baseIndex + 7] = 0 // color.w / intensity
1048
- }
1049
- this.updateLightBuffer()
1050
- }
1051
-
1052
1042
  private addLight(direction: Vec3, color: Vec3, intensity: number = 1.0): boolean {
1053
1043
  if (this.lightCount >= 4) return false
1054
1044
 
@@ -1068,7 +1058,7 @@ export class Engine {
1068
1058
  return true
1069
1059
  }
1070
1060
 
1071
- public addGround(options?: {
1061
+ addGround(options?: {
1072
1062
  width?: number
1073
1063
  height?: number
1074
1064
  diffuseColor?: Vec3
@@ -1113,11 +1103,11 @@ export class Engine {
1113
1103
  this.device.queue.writeBuffer(this.lightUniformBuffer, 0, this.lightData)
1114
1104
  }
1115
1105
 
1116
- public getStats(): EngineStats {
1106
+ getStats(): EngineStats {
1117
1107
  return { ...this.stats }
1118
1108
  }
1119
1109
 
1120
- public runRenderLoop(callback?: () => void) {
1110
+ runRenderLoop(callback?: () => void) {
1121
1111
  this.renderLoopCallback = callback || null
1122
1112
 
1123
1113
  const loop = () => {
@@ -1133,7 +1123,7 @@ export class Engine {
1133
1123
  this.animationFrameId = requestAnimationFrame(loop)
1134
1124
  }
1135
1125
 
1136
- public stopRenderLoop() {
1126
+ stopRenderLoop() {
1137
1127
  if (this.animationFrameId !== null) {
1138
1128
  cancelAnimationFrame(this.animationFrameId)
1139
1129
  this.animationFrameId = null
@@ -1141,7 +1131,7 @@ export class Engine {
1141
1131
  this.renderLoopCallback = null
1142
1132
  }
1143
1133
 
1144
- public dispose() {
1134
+ dispose() {
1145
1135
  this.stopRenderLoop()
1146
1136
  this.forEachInstance((inst) => inst.model.stopAnimation())
1147
1137
  if (Engine.instance === this) Engine.instance = null
@@ -1159,9 +1149,9 @@ export class Engine {
1159
1149
  }
1160
1150
  }
1161
1151
 
1162
- public async loadModel(path: string): Promise<Model>
1163
- public async loadModel(name: string, path: string): Promise<Model>
1164
- public async loadModel(nameOrPath: string, path?: string): Promise<Model> {
1152
+ async loadModel(path: string): Promise<Model>
1153
+ async loadModel(name: string, path: string): Promise<Model>
1154
+ async loadModel(nameOrPath: string, path?: string): Promise<Model> {
1165
1155
  const pmxPath = path === undefined ? nameOrPath : path
1166
1156
  const name = path === undefined ? "model_" + (this._nextDefaultModelId++) : nameOrPath
1167
1157
  const model = await PmxLoader.load(pmxPath)
@@ -1170,7 +1160,7 @@ export class Engine {
1170
1160
  return model
1171
1161
  }
1172
1162
 
1173
- public async addModel(model: Model, pmxPath: string, name?: string): Promise<string> {
1163
+ async addModel(model: Model, pmxPath: string, name?: string): Promise<string> {
1174
1164
  const requested = name ?? model.name
1175
1165
  let key = requested
1176
1166
  let n = 1
@@ -1184,19 +1174,19 @@ export class Engine {
1184
1174
  return key
1185
1175
  }
1186
1176
 
1187
- public removeModel(name: string): void {
1177
+ removeModel(name: string): void {
1188
1178
  this.modelInstances.delete(name)
1189
1179
  }
1190
1180
 
1191
- public getModelNames(): string[] {
1181
+ getModelNames(): string[] {
1192
1182
  return Array.from(this.modelInstances.keys())
1193
1183
  }
1194
1184
 
1195
- public getModel(name: string): Model | null {
1185
+ getModel(name: string): Model | null {
1196
1186
  return this.modelInstances.get(name)?.model ?? null
1197
1187
  }
1198
1188
 
1199
- public markVertexBufferDirty(modelNameOrModel?: string | Model): void {
1189
+ markVertexBufferDirty(modelNameOrModel?: string | Model): void {
1200
1190
  if (modelNameOrModel === undefined) return
1201
1191
  if (typeof modelNameOrModel === "string") {
1202
1192
  const inst = this.modelInstances.get(modelNameOrModel)
@@ -1211,38 +1201,38 @@ export class Engine {
1211
1201
  }
1212
1202
  }
1213
1203
 
1214
- public setMaterialVisible(modelName: string, materialName: string, visible: boolean): void {
1204
+ setMaterialVisible(modelName: string, materialName: string, visible: boolean): void {
1215
1205
  const inst = this.modelInstances.get(modelName)
1216
1206
  if (!inst) return
1217
1207
  if (visible) inst.hiddenMaterials.delete(materialName)
1218
1208
  else inst.hiddenMaterials.add(materialName)
1219
1209
  }
1220
1210
 
1221
- public toggleMaterialVisible(modelName: string, materialName: string): void {
1211
+ toggleMaterialVisible(modelName: string, materialName: string): void {
1222
1212
  const inst = this.modelInstances.get(modelName)
1223
1213
  if (!inst) return
1224
1214
  if (inst.hiddenMaterials.has(materialName)) inst.hiddenMaterials.delete(materialName)
1225
1215
  else inst.hiddenMaterials.add(materialName)
1226
1216
  }
1227
1217
 
1228
- public isMaterialVisible(modelName: string, materialName: string): boolean {
1218
+ isMaterialVisible(modelName: string, materialName: string): boolean {
1229
1219
  const inst = this.modelInstances.get(modelName)
1230
1220
  return inst ? !inst.hiddenMaterials.has(materialName) : false
1231
1221
  }
1232
1222
 
1233
- public setIKEnabled(enabled: boolean): void {
1223
+ setIKEnabled(enabled: boolean): void {
1234
1224
  this.ikEnabled = enabled
1235
1225
  }
1236
1226
 
1237
- public getIKEnabled(): boolean {
1227
+ getIKEnabled(): boolean {
1238
1228
  return this.ikEnabled
1239
1229
  }
1240
1230
 
1241
- public setPhysicsEnabled(enabled: boolean): void {
1231
+ setPhysicsEnabled(enabled: boolean): void {
1242
1232
  this.physicsEnabled = enabled
1243
1233
  }
1244
1234
 
1245
- public getPhysicsEnabled(): boolean {
1235
+ getPhysicsEnabled(): boolean {
1246
1236
  return this.physicsEnabled
1247
1237
  }
1248
1238
 
@@ -1803,7 +1793,7 @@ export class Engine {
1803
1793
  this.onRaycast(hitModel, hitMaterial, screenX, screenY)
1804
1794
  }
1805
1795
 
1806
- public render() {
1796
+ render() {
1807
1797
  if (!this.multisampleTexture || !this.camera || !this.device) return
1808
1798
 
1809
1799
  const currentTime = performance.now()
package/src/ik-solver.ts CHANGED
@@ -21,13 +21,13 @@ const enum InternalSolveAxis {
21
21
  }
22
22
 
23
23
  class IKChain {
24
- public readonly boneIndex: number
25
- public readonly minimumAngle: Vec3 | null
26
- public readonly maximumAngle: Vec3 | null
27
- public readonly rotationOrder: InternalEulerRotationOrder
28
- public readonly solveAxis: InternalSolveAxis
24
+ readonly boneIndex: number
25
+ readonly minimumAngle: Vec3 | null
26
+ readonly maximumAngle: Vec3 | null
27
+ readonly rotationOrder: InternalEulerRotationOrder
28
+ readonly solveAxis: InternalSolveAxis
29
29
 
30
- public constructor(boneIndex: number, link: IKLink) {
30
+ constructor(boneIndex: number, link: IKLink) {
31
31
  this.boneIndex = boneIndex
32
32
 
33
33
  if (link.hasLimit && link.minAngle && link.maxAngle) {
@@ -76,7 +76,7 @@ export class IKSolverSystem {
76
76
  private static readonly EPSILON = 1.0e-8
77
77
  private static readonly THRESHOLD = (88 * Math.PI) / 180
78
78
 
79
- public static solve(
79
+ static solve(
80
80
  ikSolvers: IKSolver[],
81
81
  bones: Bone[],
82
82
  localRotations: Quat[],
package/src/index.ts CHANGED
@@ -1,10 +1,14 @@
1
1
  export { Engine, type EngineStats } from "./engine"
2
2
  export { Model } from "./model"
3
3
  export { Vec3, Quat, Mat4 } from "./math"
4
- export {
5
- AnimationState,
6
- type AnimationClip,
7
- type BoneKeyframe,
8
- type MorphKeyframe,
4
+ export type {
5
+ AnimationClip,
6
+ AnimationPlayOptions,
7
+ AnimationProgress,
8
+ BoneKeyframe,
9
+ MorphKeyframe,
10
+ BoneInterpolation,
11
+ ControlPoint,
9
12
  } from "./animation"
13
+ export { FPS } from "./animation"
10
14
  export { Physics, type PhysicsOptions } from "./physics"
package/src/model.ts CHANGED
@@ -5,6 +5,8 @@ import { IKSolverSystem } from "./ik-solver"
5
5
  import { VMDLoader, type VMDKeyFrame } from "./vmd-loader"
6
6
  import {
7
7
  AnimationClip,
8
+ AnimationPlayOptions,
9
+ AnimationProgress,
8
10
  AnimationState,
9
11
  BoneInterpolation,
10
12
  BoneKeyframe,
@@ -13,7 +15,6 @@ import {
13
15
  rawInterpolationToBoneInterpolation,
14
16
  } from "./animation"
15
17
 
16
- const VMD_FPS = 30
17
18
  const VERTEX_STRIDE = 8
18
19
 
19
20
  export interface Texture {
@@ -480,7 +481,7 @@ export class Model {
480
481
  return this.runtimeMorph.weights
481
482
  }
482
483
 
483
- // ------- Bone helpers (public API) -------
484
+ // ------- Bone helpers (API) -------
484
485
 
485
486
  rotateBones(boneRotations: Record<string, Quat>, durationMs?: number): void {
486
487
  const state = this.tweenState
@@ -822,7 +823,6 @@ export class Model {
822
823
  rotation: kf.rotation,
823
824
  translation: kf.translation,
824
825
  interpolation: kf.interpolation,
825
- time: kf.frame / VMD_FPS,
826
826
  }))
827
827
  )
828
828
  }
@@ -843,27 +843,33 @@ export class Model {
843
843
  morphName: name,
844
844
  frame: kf.frame,
845
845
  weight: kf.weight,
846
- time: kf.frame / VMD_FPS,
847
846
  }))
848
847
  )
849
848
  }
850
- let maxTime = 0
849
+ let maxFrame = 0
851
850
  for (const frames of boneTracks.values()) {
852
- if (frames.length > 0) maxTime = Math.max(maxTime, frames[frames.length - 1].time)
851
+ if (frames.length > 0) maxFrame = Math.max(maxFrame, frames[frames.length - 1].frame)
853
852
  }
854
853
  for (const frames of morphTracks.values()) {
855
- if (frames.length > 0) maxTime = Math.max(maxTime, frames[frames.length - 1].time)
854
+ if (frames.length > 0) maxFrame = Math.max(maxFrame, frames[frames.length - 1].frame)
856
855
  }
857
- return { boneTracks, morphTracks, duration: maxTime }
856
+ return { boneTracks, morphTracks, frameCount: maxFrame }
858
857
  }
859
858
 
860
- async loadAnimation(animationName: string, vmdUrl: string): Promise<void> {
861
- const vmdKeyFrames = await VMDLoader.load(vmdUrl)
862
- const clip = this.buildClipFromVmdKeyFrames(vmdKeyFrames)
863
- this.animationState.loadAnimation(animationName, clip)
859
+ loadAnimation(animationName: string, source: string): Promise<void>
860
+ loadAnimation(animationName: string, source: AnimationClip): void
861
+ loadAnimation(animationName: string, source: string | AnimationClip): Promise<void> | void {
862
+ if (typeof source !== "string") {
863
+ this.animationState.loadAnimation(animationName, source)
864
+ return
865
+ }
866
+ return VMDLoader.load(source).then((vmdKeyFrames) => {
867
+ const clip = this.buildClipFromVmdKeyFrames(vmdKeyFrames)
868
+ this.animationState.loadAnimation(animationName, clip)
869
+ })
864
870
  }
865
871
 
866
- public resetAllBones(): void {
872
+ resetAllBones(): void {
867
873
  for (let boneIdx = 0; boneIdx < this.skeleton.bones.length; boneIdx++) {
868
874
  const localRot = this.runtimeSkeleton.localRotations[boneIdx]
869
875
  const localTrans = this.runtimeSkeleton.localTranslations[boneIdx]
@@ -874,7 +880,7 @@ export class Model {
874
880
  this.computeWorldMatrices()
875
881
  }
876
882
 
877
- public resetAllMorphs(): void {
883
+ resetAllMorphs(): void {
878
884
  for (let morphIdx = 0; morphIdx < this.morphing.morphs.length; morphIdx++) {
879
885
  const morphName = this.morphing.morphs[morphIdx].name
880
886
  this.setMorphWeight(morphName, 0)
@@ -883,21 +889,26 @@ export class Model {
883
889
  this.applyMorphs()
884
890
  }
885
891
 
886
- getAnimationState(): AnimationState {
887
- return this.animationState
892
+ getAnimationClip(name: string): AnimationClip | null {
893
+ return this.animationState.getAnimationClip(name)
888
894
  }
889
895
 
890
896
  play(): void
891
897
  play(name: string): boolean
892
- play(name?: string): void | boolean {
898
+ play(name: string, options?: AnimationPlayOptions): boolean
899
+ play(name?: string, options?: AnimationPlayOptions): void | boolean {
893
900
  if (name === undefined) {
894
901
  this.animationState.play()
895
902
  return
896
903
  }
897
- return this.animationState.play(name)
904
+ this.resetAllBones()
905
+ this.resetAllMorphs()
906
+ return this.animationState.play(name, options)
898
907
  }
899
908
 
900
909
  show(name: string): void {
910
+ this.resetAllBones()
911
+ this.resetAllMorphs()
901
912
  this.animationState.show(name)
902
913
  }
903
914
 
@@ -924,46 +935,55 @@ export class Model {
924
935
  this.animationState.stop()
925
936
  }
926
937
 
927
- seek(time: number): void {
928
- this.animationState.seek(time)
938
+ // Seek by absolute timeline seconds, not frame index.
939
+ seek(seconds: number): void {
940
+ this.animationState.seek(seconds)
929
941
  }
930
942
 
931
943
  // @deprecated Use model.seek()
932
- seekAnimation(time: number): void {
933
- this.animationState.seek(time)
944
+ seekAnimation(seconds: number): void {
945
+ this.animationState.seek(seconds)
934
946
  }
935
947
 
936
- getAnimationProgress(): { current: number; duration: number; percentage: number; animationName: string | null } {
948
+ getAnimationProgress(): AnimationProgress {
937
949
  const p = this.animationState.getProgress()
938
- return { current: p.current, duration: p.duration, percentage: p.percentage, animationName: p.animationName }
950
+ return {
951
+ current: p.current,
952
+ duration: p.duration,
953
+ percentage: p.percentage,
954
+ animationName: p.animationName,
955
+ looping: p.looping,
956
+ playing: p.playing,
957
+ paused: p.paused,
958
+ }
939
959
  }
940
960
 
941
- private static upperBound<T extends { time: number }>(time: number, keyFrames: T[], startIdx: number = 0): number {
961
+ private static upperBound<T extends { frame: number }>(frame: number, keyFrames: T[], startIdx: number = 0): number {
942
962
  let left = startIdx,
943
963
  right = keyFrames.length
944
964
  while (left < right) {
945
965
  const mid = Math.floor((left + right) / 2)
946
- if (keyFrames[mid].time <= time) left = mid + 1
966
+ if (keyFrames[mid].frame <= frame) left = mid + 1
947
967
  else right = mid
948
968
  }
949
969
  return left
950
970
  }
951
971
 
952
- private findKeyframeIndex<T extends { time: number }>(time: number, keyFrames: T[], cachedIdx: number): number {
972
+ private findKeyframeIndex<T extends { frame: number }>(frame: number, keyFrames: T[], cachedIdx: number): number {
953
973
  if (keyFrames.length === 0) return -1
954
974
 
955
975
  if (cachedIdx >= 0 && cachedIdx < keyFrames.length) {
956
- const frameTime = keyFrames[cachedIdx].time
957
- const nextFrameTime = cachedIdx + 1 < keyFrames.length ? keyFrames[cachedIdx + 1].time : Infinity
958
- if (time >= frameTime && time < nextFrameTime) {
976
+ const currentFrame = keyFrames[cachedIdx].frame
977
+ const nextFrame = cachedIdx + 1 < keyFrames.length ? keyFrames[cachedIdx + 1].frame : Infinity
978
+ if (frame >= currentFrame && frame < nextFrame) {
959
979
  return cachedIdx
960
980
  }
961
981
  }
962
- const idx = Model.upperBound(time, keyFrames, 0) - 1
982
+ const idx = Model.upperBound(frame, keyFrames, 0) - 1
963
983
  return idx
964
984
  }
965
985
 
966
- private applyPoseFromClip(clip: AnimationClip | null, time: number): void {
986
+ private applyPoseFromClip(clip: AnimationClip | null, frame: number): void {
967
987
  if (!clip) return
968
988
  if (clip !== this.lastAppliedClip) {
969
989
  this.boneTrackIndices.clear()
@@ -975,8 +995,8 @@ export class Model {
975
995
  if (keyFrames.length === 0) continue
976
996
 
977
997
  const cachedIdx = this.boneTrackIndices.get(boneName) ?? -1
978
- const clampedTime = Math.max(keyFrames[0].time, Math.min(keyFrames[keyFrames.length - 1].time, time))
979
- const idx = this.findKeyframeIndex(clampedTime, keyFrames, cachedIdx)
998
+ const clampedFrame = Math.max(keyFrames[0].frame, Math.min(keyFrames[keyFrames.length - 1].frame, frame))
999
+ const idx = this.findKeyframeIndex(clampedFrame, keyFrames, cachedIdx)
980
1000
 
981
1001
  if (idx < 0) continue
982
1002
 
@@ -997,8 +1017,8 @@ export class Model {
997
1017
  const localTranslation = this.convertVMDTranslationToLocal(boneIdx, frameA.translation, frameRotation)
998
1018
  localTrans.set(localTranslation)
999
1019
  } else {
1000
- const timeDelta = frameB.time - frameA.time
1001
- const gradient = (clampedTime - frameA.time) / timeDelta
1020
+ const frameDelta = frameB.frame - frameA.frame
1021
+ const gradient = frameDelta > 0 ? (clampedFrame - frameA.frame) / frameDelta : 0
1002
1022
  const interp = frameB.interpolation
1003
1023
 
1004
1024
  const rotT = interpolateControlPoints(interp.rotation, gradient)
@@ -1025,8 +1045,8 @@ export class Model {
1025
1045
  if (keyFrames.length === 0) continue
1026
1046
 
1027
1047
  const cachedIdx = this.morphTrackIndices.get(morphName) ?? -1
1028
- const clampedTime = Math.max(keyFrames[0].time, Math.min(keyFrames[keyFrames.length - 1].time, time))
1029
- const idx = this.findKeyframeIndex(clampedTime, keyFrames, cachedIdx)
1048
+ const clampedFrame = Math.max(keyFrames[0].frame, Math.min(keyFrames[keyFrames.length - 1].frame, frame))
1049
+ const idx = this.findKeyframeIndex(clampedFrame, keyFrames, cachedIdx)
1030
1050
 
1031
1051
  if (idx < 0) continue
1032
1052
 
@@ -1041,7 +1061,9 @@ export class Model {
1041
1061
  const weight = frameB
1042
1062
  ? frameA.weight +
1043
1063
  (frameB.weight - frameA.weight) *
1044
- ((clampedTime - keyFrames[idx].time) / (keyFrames[idx + 1].time - keyFrames[idx].time))
1064
+ (keyFrames[idx + 1].frame > keyFrames[idx].frame
1065
+ ? (clampedFrame - keyFrames[idx].frame) / (keyFrames[idx + 1].frame - keyFrames[idx].frame)
1066
+ : 0)
1045
1067
  : frameA.weight
1046
1068
 
1047
1069
  this.runtimeMorph.weights[morphIdx] = weight
@@ -1059,9 +1081,9 @@ export class Model {
1059
1081
 
1060
1082
  this.animationState.update(deltaTime)
1061
1083
  const clip = this.animationState.getCurrentClip()
1062
- const time = this.animationState.getCurrentTime()
1084
+ const frame = this.animationState.getCurrentFrame()
1063
1085
  if (clip !== null) {
1064
- this.applyPoseFromClip(clip, time)
1086
+ this.applyPoseFromClip(clip, frame)
1065
1087
  }
1066
1088
 
1067
1089
  // Apply morphs if tweens changed morphs or animation changed morphs
@@ -1223,7 +1245,7 @@ export class Model {
1223
1245
  }
1224
1246
  }
1225
1247
 
1226
- public computeWorldMatrices(): void {
1248
+ computeWorldMatrices(): void {
1227
1249
  const bones = this.skeleton.bones
1228
1250
  const localRot = this.runtimeSkeleton.localRotations
1229
1251
  const localTrans = this.runtimeSkeleton.localTranslations