reze-engine 0.6.5 → 0.6.7
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 +74 -6
- package/dist/engine.d.ts +1 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +3 -0
- package/dist/ik-solver.d.ts +2 -1
- package/dist/ik-solver.d.ts.map +1 -1
- package/dist/ik-solver.js +31 -14
- package/dist/model.d.ts +13 -0
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +168 -8
- package/package.json +1 -1
- package/src/engine.ts +8 -0
- package/src/ik-solver.ts +37 -14
- package/src/model.ts +200 -16
- 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_ts.d.ts +0 -143
- package/dist/engine_ts.d.ts.map +0 -1
- package/dist/engine_ts.js +0 -1575
- package/dist/ik.d.ts +0 -32
- package/dist/ik.d.ts.map +0 -1
- package/dist/ik.js +0 -337
- package/dist/player.d.ts +0 -64
- package/dist/player.d.ts.map +0 -1
- package/dist/player.js +0 -220
- package/dist/pool-scene.d.ts +0 -52
- package/dist/pool-scene.d.ts.map +0 -1
- package/dist/pool-scene.js +0 -1122
- package/dist/pool.d.ts +0 -38
- package/dist/pool.d.ts.map +0 -1
- package/dist/pool.js +0 -422
- package/dist/rzm-converter.d.ts +0 -12
- package/dist/rzm-converter.d.ts.map +0 -1
- package/dist/rzm-converter.js +0 -40
- package/dist/rzm-loader.d.ts +0 -24
- package/dist/rzm-loader.d.ts.map +0 -1
- package/dist/rzm-loader.js +0 -488
- package/dist/rzm-writer.d.ts +0 -27
- package/dist/rzm-writer.d.ts.map +0 -1
- package/dist/rzm-writer.js +0 -701
package/README.md
CHANGED
|
@@ -2,17 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
A lightweight engine built with WebGPU and TypeScript for real-time 3D anime character MMD model rendering.
|
|
4
4
|
|
|
5
|
+

|
|
6
|
+
|
|
5
7
|
## Features
|
|
6
8
|
|
|
7
|
-
-
|
|
9
|
+
- Blinn-Phong lighting
|
|
8
10
|
- Alpha blending
|
|
9
|
-
- Post alpha eye rendering
|
|
11
|
+
- Post alpha eye rendering (the see-through eyes)
|
|
10
12
|
- Rim lighting
|
|
11
13
|
- Outlines
|
|
12
14
|
- MSAA 4x anti-aliasing
|
|
13
|
-
- Bone and morph
|
|
15
|
+
- Bone and morph API
|
|
14
16
|
- VMD animation
|
|
15
|
-
-
|
|
17
|
+
- IK solver
|
|
18
|
+
- Ammo/Bullet physics
|
|
16
19
|
|
|
17
20
|
## Usage
|
|
18
21
|
|
|
@@ -24,10 +27,10 @@ export default function Scene() {
|
|
|
24
27
|
const initEngine = useCallback(async () => {
|
|
25
28
|
if (canvasRef.current) {
|
|
26
29
|
try {
|
|
27
|
-
const engine = new Engine(canvasRef.current)
|
|
30
|
+
const engine = new Engine(canvasRef.current, {})
|
|
28
31
|
engineRef.current = engine
|
|
29
32
|
await engine.init()
|
|
30
|
-
await engine.loadModel("/models
|
|
33
|
+
await engine.loadModel("/models/reze/reze.pmx")
|
|
31
34
|
|
|
32
35
|
engine.runRenderLoop(() => {})
|
|
33
36
|
} catch (error) {
|
|
@@ -52,11 +55,76 @@ export default function Scene() {
|
|
|
52
55
|
}
|
|
53
56
|
```
|
|
54
57
|
|
|
58
|
+
Engine options
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
const DEFAULT_ENGINE_OPTIONS: RequiredEngineOptions = {
|
|
62
|
+
ambientColor: new Vec3(0.82, 0.82, 0.82),
|
|
63
|
+
directionalLightIntensity: 0.2,
|
|
64
|
+
minSpecularIntensity: 0.3,
|
|
65
|
+
rimLightIntensity: 0.4,
|
|
66
|
+
cameraDistance: 26.6,
|
|
67
|
+
cameraTarget: new Vec3(0, 12.5, 0),
|
|
68
|
+
cameraFov: Math.PI / 4,
|
|
69
|
+
onRaycast: undefined,
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## API
|
|
74
|
+
|
|
75
|
+
### Animation Playback
|
|
76
|
+
|
|
77
|
+
Load and play VMD animation files.
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
await engine.loadAnimation("/animations/dance.vmd")
|
|
81
|
+
engine.playAnimation()
|
|
82
|
+
engine.pauseAnimation()
|
|
83
|
+
engine.stopAnimation()
|
|
84
|
+
engine.seekAnimation(2.5) // seek to 2.5 seconds
|
|
85
|
+
|
|
86
|
+
const { current, duration, percentage } = engine.getAnimationProgress()
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Bone and Morph Tweening
|
|
90
|
+
|
|
91
|
+
Rotate and move bones with optional tween duration. Translations are VMD-style (relative to bind pose world position).
|
|
92
|
+
|
|
93
|
+
```javascript
|
|
94
|
+
engine.rotateBones({ "首": neckQuat, "頭": headQuat }, 300)
|
|
95
|
+
engine.moveBones({ "センター": centerVec }, 300)
|
|
96
|
+
engine.setMorphWeight("まばたき", 1.0, 300)
|
|
97
|
+
|
|
98
|
+
engine.resetAllBones()
|
|
99
|
+
engine.resetAllMorphs()
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Atomic Pose Setting
|
|
103
|
+
|
|
104
|
+
Set rotations, translations, and morphs in a single atomic pass — for animation editors, motion capture, or any use case that needs precise, immediate pose updates matching the quality of internal VMD playback.
|
|
105
|
+
|
|
106
|
+
```javascript
|
|
107
|
+
engine.setPose(
|
|
108
|
+
{ "首": neckQuat, "頭": headQuat, "左腕": leftArmQuat },
|
|
109
|
+
{ "センター": centerVec },
|
|
110
|
+
{ "まばたき": 0.5, "あ": 0.3 }
|
|
111
|
+
)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
All three parameters are optional. Pass only what you need:
|
|
115
|
+
|
|
116
|
+
```javascript
|
|
117
|
+
engine.setPose(rotations) // rotations only
|
|
118
|
+
engine.setPose(undefined, translations) // translations only
|
|
119
|
+
engine.setPose(undefined, undefined, morphs) // morphs only
|
|
120
|
+
```
|
|
121
|
+
|
|
55
122
|
## Projects Using This Engine
|
|
56
123
|
|
|
57
124
|
- **[MiKaPo](https://mikapo.vercel.app)** - Online real-time motion capture for MMD using webcam and MediaPipe
|
|
58
125
|
- **[Popo](https://popo.love)** - Fine-tuned LLM that generates MMD poses from natural language descriptions
|
|
59
126
|
- **[MPL](https://mmd-mpl.vercel.app)** - Semantic motion programming language for scripting MMD animations with intuitive syntax
|
|
127
|
+
- **[Mixamo-MMD](https://mixamo-mmd.vercel.app)** - Retarget Mixamo FBX animation to VMD in one click
|
|
60
128
|
|
|
61
129
|
## Tutorial
|
|
62
130
|
|
package/dist/engine.d.ts
CHANGED
|
@@ -129,6 +129,7 @@ export declare class Engine {
|
|
|
129
129
|
loadModel(path: string): Promise<void>;
|
|
130
130
|
rotateBones(boneRotations: Record<string, Quat>, durationMs?: number): void;
|
|
131
131
|
moveBones(boneTranslations: Record<string, Vec3>, durationMs?: number): void;
|
|
132
|
+
setPose(rotations?: Record<string, Quat>, translations?: Record<string, Vec3>, morphs?: Record<string, number>): void;
|
|
132
133
|
resetAllBones(): void;
|
|
133
134
|
resetAllMorphs(): void;
|
|
134
135
|
setMorphWeight(name: string, weight: number, durationMs?: number): void;
|
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|
package/dist/engine.js
CHANGED
|
@@ -987,6 +987,9 @@ export class Engine {
|
|
|
987
987
|
moveBones(boneTranslations, durationMs) {
|
|
988
988
|
this.currentModel?.moveBones(boneTranslations, durationMs);
|
|
989
989
|
}
|
|
990
|
+
setPose(rotations, translations, morphs) {
|
|
991
|
+
this.currentModel?.setPose(rotations, translations, morphs);
|
|
992
|
+
}
|
|
990
993
|
resetAllBones() {
|
|
991
994
|
this.currentModel?.resetAllBones();
|
|
992
995
|
}
|
package/dist/ik-solver.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { Mat4, Quat, Vec3 } from "./math";
|
|
7
7
|
import { Bone, IKSolver, IKChainInfo } from "./model";
|
|
8
|
+
export type UpdateWorldMatrixFn = (boneIndex: number, applyIK: boolean) => void;
|
|
8
9
|
/**
|
|
9
10
|
* Solve IK chains for a model
|
|
10
11
|
*/
|
|
@@ -14,7 +15,7 @@ export declare class IKSolverSystem {
|
|
|
14
15
|
/**
|
|
15
16
|
* Solve all IK chains
|
|
16
17
|
*/
|
|
17
|
-
static solve(ikSolvers: IKSolver[], bones: Bone[], localRotations: Quat[], localTranslations: Vec3[], worldMatrices: Mat4[], ikChainInfo: IKChainInfo[]): void;
|
|
18
|
+
static solve(ikSolvers: IKSolver[], bones: Bone[], localRotations: Quat[], localTranslations: Vec3[], worldMatrices: Mat4[], ikChainInfo: IKChainInfo[], updateWorldMatrix?: UpdateWorldMatrixFn): void;
|
|
18
19
|
private static solveIK;
|
|
19
20
|
private static solveChain;
|
|
20
21
|
private static limitAngle;
|
package/dist/ik-solver.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ik-solver.d.ts","sourceRoot":"","sources":["../src/ik-solver.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AACzC,OAAO,EAAE,IAAI,EAAU,QAAQ,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"ik-solver.d.ts","sourceRoot":"","sources":["../src/ik-solver.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AACzC,OAAO,EAAE,IAAI,EAAU,QAAQ,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAG7D,MAAM,MAAM,mBAAmB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;AAoE/E;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAS;IACxC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAuB;IAExD;;OAEG;WACW,KAAK,CACjB,SAAS,EAAE,QAAQ,EAAE,EACrB,KAAK,EAAE,IAAI,EAAE,EACb,cAAc,EAAE,IAAI,EAAE,EACtB,iBAAiB,EAAE,IAAI,EAAE,EACzB,aAAa,EAAE,IAAI,EAAE,EACrB,WAAW,EAAE,WAAW,EAAE,EAC1B,iBAAiB,CAAC,EAAE,mBAAmB,GACtC,IAAI;IAMP,OAAO,CAAC,MAAM,CAAC,OAAO;IAoFtB,OAAO,CAAC,MAAM,CAAC,UAAU;IAqGzB,OAAO,CAAC,MAAM,CAAC,UAAU;IAYzB,OAAO,CAAC,MAAM,CAAC,WAAW;IAM1B,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAKlC,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAmCjC,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAQ/B,OAAO,CAAC,MAAM,CAAC,wBAAwB;IAqBvC,OAAO,CAAC,MAAM,CAAC,4BAA4B;IAc3C,OAAO,CAAC,MAAM,CAAC,eAAe;IAS9B,OAAO,CAAC,MAAM,CAAC,iBAAiB;CAoCjC"}
|
package/dist/ik-solver.js
CHANGED
|
@@ -74,12 +74,12 @@ export class IKSolverSystem {
|
|
|
74
74
|
/**
|
|
75
75
|
* Solve all IK chains
|
|
76
76
|
*/
|
|
77
|
-
static solve(ikSolvers, bones, localRotations, localTranslations, worldMatrices, ikChainInfo) {
|
|
77
|
+
static solve(ikSolvers, bones, localRotations, localTranslations, worldMatrices, ikChainInfo, updateWorldMatrix) {
|
|
78
78
|
for (const solver of ikSolvers) {
|
|
79
|
-
this.solveIK(solver, bones, localRotations, localTranslations, worldMatrices, ikChainInfo);
|
|
79
|
+
this.solveIK(solver, bones, localRotations, localTranslations, worldMatrices, ikChainInfo, updateWorldMatrix);
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
-
static solveIK(solver, bones, localRotations, localTranslations, worldMatrices, ikChainInfo) {
|
|
82
|
+
static solveIK(solver, bones, localRotations, localTranslations, worldMatrices, ikChainInfo, updateWorldMatrix) {
|
|
83
83
|
if (solver.links.length === 0)
|
|
84
84
|
return;
|
|
85
85
|
const ikBoneIndex = solver.ikBoneIndex;
|
|
@@ -99,10 +99,18 @@ export class IKSolverSystem {
|
|
|
99
99
|
chains.push(new IKChain(link.boneIndex, link));
|
|
100
100
|
}
|
|
101
101
|
// Update chain bones and target bone world matrices (initial state, no IK yet)
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
if (updateWorldMatrix) {
|
|
103
|
+
for (let i = chains.length - 1; i >= 0; i--) {
|
|
104
|
+
updateWorldMatrix(chains[i].boneIndex, false);
|
|
105
|
+
}
|
|
106
|
+
updateWorldMatrix(targetBoneIndex, false);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
for (let i = chains.length - 1; i >= 0; i--) {
|
|
110
|
+
this.updateWorldMatrix(chains[i].boneIndex, bones, localRotations, localTranslations, worldMatrices, undefined);
|
|
111
|
+
}
|
|
112
|
+
this.updateWorldMatrix(targetBoneIndex, bones, localRotations, localTranslations, worldMatrices, undefined);
|
|
104
113
|
}
|
|
105
|
-
this.updateWorldMatrix(targetBoneIndex, bones, localRotations, localTranslations, worldMatrices, undefined);
|
|
106
114
|
if (this.getDistance(ikBoneIndex, targetBoneIndex, worldMatrices) < this.EPSILON)
|
|
107
115
|
return;
|
|
108
116
|
// Solve iteratively
|
|
@@ -112,7 +120,7 @@ export class IKSolverSystem {
|
|
|
112
120
|
for (let chainIndex = 0; chainIndex < chains.length; chainIndex++) {
|
|
113
121
|
const chain = chains[chainIndex];
|
|
114
122
|
if (chain.solveAxis !== InternalSolveAxis.Fixed) {
|
|
115
|
-
this.solveChain(chain, chainIndex, solver, ikBoneIndex, targetBoneIndex, bones, localRotations, localTranslations, worldMatrices, ikChainInfo, i < halfIteration);
|
|
123
|
+
this.solveChain(chain, chainIndex, solver, ikBoneIndex, targetBoneIndex, bones, localRotations, localTranslations, worldMatrices, ikChainInfo, i < halfIteration, updateWorldMatrix);
|
|
116
124
|
}
|
|
117
125
|
}
|
|
118
126
|
if (this.getDistance(ikBoneIndex, targetBoneIndex, worldMatrices) < this.EPSILON)
|
|
@@ -128,7 +136,7 @@ export class IKSolverSystem {
|
|
|
128
136
|
}
|
|
129
137
|
}
|
|
130
138
|
}
|
|
131
|
-
static solveChain(chain, chainIndex, solver, ikBoneIndex, targetBoneIndex, bones, localRotations, localTranslations, worldMatrices, ikChainInfo, useAxis) {
|
|
139
|
+
static solveChain(chain, chainIndex, solver, ikBoneIndex, targetBoneIndex, bones, localRotations, localTranslations, worldMatrices, ikChainInfo, useAxis, updateWorldMatrix) {
|
|
132
140
|
const chainBoneIndex = chain.boneIndex;
|
|
133
141
|
const chainPosition = this.getWorldTranslation(chainBoneIndex, worldMatrices);
|
|
134
142
|
const ikPosition = this.getWorldTranslation(ikBoneIndex, worldMatrices);
|
|
@@ -191,13 +199,22 @@ export class IKSolverSystem {
|
|
|
191
199
|
chainInfo.ikRotation = chainInfo.ikRotation.multiply(localRot.clone().conjugate().normalize());
|
|
192
200
|
}
|
|
193
201
|
}
|
|
194
|
-
// Update world matrices for affected bones (using
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
202
|
+
// Update world matrices for affected bones (using callback - handles append correctly)
|
|
203
|
+
if (updateWorldMatrix) {
|
|
204
|
+
for (let i = chainIndex; i >= 0; i--) {
|
|
205
|
+
const link = solver.links[i];
|
|
206
|
+
updateWorldMatrix(link.boneIndex, true); // applyIK = true
|
|
207
|
+
}
|
|
208
|
+
updateWorldMatrix(targetBoneIndex, false);
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
for (let i = chainIndex; i >= 0; i--) {
|
|
212
|
+
const link = solver.links[i];
|
|
213
|
+
this.updateWorldMatrix(link.boneIndex, bones, localRotations, localTranslations, worldMatrices, ikChainInfo);
|
|
214
|
+
}
|
|
215
|
+
this.updateWorldMatrix(ikBoneIndex, bones, localRotations, localTranslations, worldMatrices, undefined);
|
|
216
|
+
this.updateWorldMatrix(targetBoneIndex, bones, localRotations, localTranslations, worldMatrices, undefined);
|
|
198
217
|
}
|
|
199
|
-
this.updateWorldMatrix(ikBoneIndex, bones, localRotations, localTranslations, worldMatrices, undefined);
|
|
200
|
-
this.updateWorldMatrix(targetBoneIndex, bones, localRotations, localTranslations, worldMatrices, undefined);
|
|
201
218
|
}
|
|
202
219
|
static limitAngle(angle, min, max, useAxis) {
|
|
203
220
|
if (angle < min) {
|
package/dist/model.d.ts
CHANGED
|
@@ -146,12 +146,23 @@ export declare class Model {
|
|
|
146
146
|
/**
|
|
147
147
|
* Convert VMD-style relative translation (relative to bind pose world position) to local translation
|
|
148
148
|
* This helper is used by both moveBones and getPoseAtTime to ensure consistent translation handling
|
|
149
|
+
* @param boneIdx - Bone index
|
|
150
|
+
* @param vmdRelativeTranslation - VMD relative translation
|
|
151
|
+
* @param rotation - Optional rotation to use for conversion. If not provided, uses current localRotation.
|
|
152
|
+
* Use animation rotation (from frame) to avoid conflicts when IK modifies rotation.
|
|
149
153
|
*/
|
|
150
154
|
private convertVMDTranslationToLocal;
|
|
151
155
|
getBoneWorldMatrices(): Float32Array;
|
|
152
156
|
getBoneInverseBindMatrices(): Float32Array;
|
|
153
157
|
getSkinMatrices(): Float32Array;
|
|
154
158
|
setMorphWeight(name: string, weight: number, durationMs?: number): void;
|
|
159
|
+
/**
|
|
160
|
+
* Atomic pose setter for external animation editors.
|
|
161
|
+
* Sets bone rotations, translations, and morph weights in a single pass,
|
|
162
|
+
* identical to how getPoseAtTime applies VMD poses during playback.
|
|
163
|
+
* Cancels any active tweens on affected bones/morphs.
|
|
164
|
+
*/
|
|
165
|
+
setPose(rotations?: Record<string, Quat>, translations?: Record<string, Vec3>, morphs?: Record<string, number>): void;
|
|
155
166
|
private applyMorphs;
|
|
156
167
|
/**
|
|
157
168
|
* Load VMD animation file
|
|
@@ -208,6 +219,8 @@ export declare class Model {
|
|
|
208
219
|
*/
|
|
209
220
|
update(deltaTime: number): boolean;
|
|
210
221
|
private solveIKChains;
|
|
222
|
+
private ikComputedSet;
|
|
223
|
+
private computeSingleBoneWorldMatrix;
|
|
211
224
|
private computeWorldMatrices;
|
|
212
225
|
}
|
|
213
226
|
//# sourceMappingURL=model.d.ts.map
|
package/dist/model.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAqB,MAAM,QAAQ,CAAA;AAC5D,OAAO,EAAE,SAAS,EAAE,KAAK,EAAW,MAAM,WAAW,CAAA;AAMrD,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IACzC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IACjC,SAAS,EAAE,MAAM,CAAA;IACjB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,kBAAkB,EAAE,MAAM,CAAA;IAC1B,kBAAkB,EAAE,MAAM,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,gBAAgB,EAAE,MAAM,CAAA;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAC3C,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IACzC,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CACnB;AAGD,MAAM,WAAW,MAAM;IACrB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,IAAI,CAAA;IACf,QAAQ,CAAC,EAAE,IAAI,CAAA;CAChB;AAGD,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,MAAM,CAAA;IACvB,cAAc,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB;AAGD,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,IAAI,CAAA;IAChB,aAAa,EAAE,IAAI,CAAA;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,IAAI,EAAE,CAAA;IACb,mBAAmB,EAAE,YAAY,CAAA;CAClC;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,WAAW,CAAA;IACnB,OAAO,EAAE,UAAU,CAAA;CACpB;AAGD,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;CACzC;AAGD,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;CACd;AAGD,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,iBAAiB,EAAE,CAAA;IAClC,eAAe,CAAC,EAAE,mBAAmB,EAAE,CAAA;CACxC;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,KAAK,EAAE,CAAA;IACf,aAAa,EAAE,YAAY,CAAA;CAC5B;AAGD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjC,cAAc,EAAE,IAAI,EAAE,CAAA;IACtB,iBAAiB,EAAE,IAAI,EAAE,CAAA;IACzB,aAAa,EAAE,IAAI,EAAE,CAAA;IACrB,WAAW,CAAC,EAAE,WAAW,EAAE,CAAA;IAC3B,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAA;CACvB;AAGD,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjC,OAAO,EAAE,YAAY,CAAA;CACtB;AA2BD,qBAAa,KAAK;IAChB,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,cAAc,CAA2B;IACjD,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,SAAS,CAAiB;IAElC,OAAO,CAAC,QAAQ,CAAU;IAC1B,OAAO,CAAC,QAAQ,CAAU;IAG1B,OAAO,CAAC,QAAQ,CAAU;IAG1B,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,MAAM,CAAc;IAG5B,OAAO,CAAC,eAAe,CAAkB;IAGzC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,WAAW,CAAiB;IAGpC,OAAO,CAAC,kBAAkB,CAAkB;IAC5C,OAAO,CAAC,kBAAkB,CAAkB;IAG5C,OAAO,CAAC,iBAAiB,CAAC,CAAc;IAExC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,WAAW,CAAY;IAG/B,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,UAAU,CAAwE;IAC1F,OAAO,CAAC,WAAW,CAA0E;IAC7F,OAAO,CAAC,iBAAiB,CAAY;IACrC,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,aAAa,CAAY;IAGjC,OAAO,CAAC,gBAAgB,CAAiC;IACzD,OAAO,CAAC,iBAAiB,CAAiC;IAG1D,OAAO,CAAC,OAAO,CAAuB;IAGtC,OAAO,CAAC,SAAS,CAAO;IACxB,OAAO,CAAC,cAAc,CAAO;gBAG3B,UAAU,EAAE,YAAY,CAAC,WAAW,CAAC,EACrC,SAAS,EAAE,WAAW,CAAC,WAAW,CAAC,EACnC,QAAQ,EAAE,OAAO,EAAE,EACnB,SAAS,EAAE,QAAQ,EAAE,EACrB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,EAClB,WAAW,GAAE,SAAS,EAAO,EAC7B,MAAM,GAAE,KAAK,EAAO;IA8BtB,OAAO,CAAC,yBAAyB;IA2BjC,OAAO,CAAC,mBAAmB;IAoC3B,OAAO,CAAC,sBAAsB;IAwC9B,OAAO,CAAC,sBAAsB;IAc9B,OAAO,CAAC,YAAY;IA6EpB,WAAW,IAAI,YAAY,CAAC,WAAW,CAAC;IAIxC,WAAW,IAAI,OAAO,EAAE;IAIxB,YAAY,IAAI,QAAQ,EAAE;IAI1B,UAAU,IAAI,WAAW,CAAC,WAAW,CAAC;IAItC,WAAW,IAAI,QAAQ;IAIvB,WAAW,IAAI,QAAQ;IAIvB,cAAc,IAAI,SAAS,EAAE;IAI7B,SAAS,IAAI,KAAK,EAAE;IAIpB,WAAW,IAAI,QAAQ;IAIvB,eAAe,IAAI,YAAY;IAM/B,WAAW,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;IAmD3E,SAAS,CAAC,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;IAoD5E;;;;;;;OAOG;IACH,OAAO,CAAC,4BAA4B;IA2DpC,oBAAoB,IAAI,YAAY;IAWpC,0BAA0B,IAAI,YAAY;IAI1C,eAAe,IAAI,YAAY;IAuB/B,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;IAwCvE;;;;;OAKG;IACH,OAAO,CACL,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,EAChC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,EACnC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,IAAI;IAyCP,OAAO,CAAC,WAAW;IAiEnB;;OAEG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAe5C;;OAEG;IACI,aAAa,IAAI,IAAI;IAerB,cAAc,IAAI,IAAI;IAS7B;;OAEG;IACI,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAI3C;;OAEG;IACI,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIhD;;OAEG;IACH,OAAO,CAAC,aAAa;IA4DrB,aAAa,IAAI,IAAI;IAYrB,cAAc,IAAI,IAAI;IAKtB,aAAa,IAAI,IAAI;IAMrB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMjC;;OAEG;IACH,oBAAoB,IAAI;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;IAUjF;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,UAAU;IAWzB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAmBzB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAsHrB;;;;;OAKG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAgDlC,OAAO,CAAC,aAAa;IAmCrB,OAAO,CAAC,aAAa,CAAyB;IAI9C,OAAO,CAAC,4BAA4B;IAoGpC,OAAO,CAAC,oBAAoB;CA0F7B"}
|
package/dist/model.js
CHANGED
|
@@ -31,6 +31,8 @@ export class Model {
|
|
|
31
31
|
// IK and Physics enable flags
|
|
32
32
|
this.ikEnabled = true;
|
|
33
33
|
this.physicsEnabled = true;
|
|
34
|
+
// Cached set to track which bones are being computed in current IK pass (to avoid infinite recursion)
|
|
35
|
+
this.ikComputedSet = new Set();
|
|
34
36
|
// Store base vertex data (original positions before morphing)
|
|
35
37
|
this.baseVertexData = new Float32Array(vertexData);
|
|
36
38
|
this.vertexData = vertexData;
|
|
@@ -346,8 +348,12 @@ export class Model {
|
|
|
346
348
|
/**
|
|
347
349
|
* Convert VMD-style relative translation (relative to bind pose world position) to local translation
|
|
348
350
|
* This helper is used by both moveBones and getPoseAtTime to ensure consistent translation handling
|
|
351
|
+
* @param boneIdx - Bone index
|
|
352
|
+
* @param vmdRelativeTranslation - VMD relative translation
|
|
353
|
+
* @param rotation - Optional rotation to use for conversion. If not provided, uses current localRotation.
|
|
354
|
+
* Use animation rotation (from frame) to avoid conflicts when IK modifies rotation.
|
|
349
355
|
*/
|
|
350
|
-
convertVMDTranslationToLocal(boneIdx, vmdRelativeTranslation) {
|
|
356
|
+
convertVMDTranslationToLocal(boneIdx, vmdRelativeTranslation, rotation) {
|
|
351
357
|
const skeleton = this.skeleton;
|
|
352
358
|
const bones = skeleton.bones;
|
|
353
359
|
const localRot = this.runtimeSkeleton.localRotations;
|
|
@@ -383,7 +389,9 @@ export class Model {
|
|
|
383
389
|
// Subtract bindTranslation to get position after bind translation
|
|
384
390
|
const afterBindTranslation = parentSpacePos.subtract(new Vec3(bone.bindTranslation[0], bone.bindTranslation[1], bone.bindTranslation[2]));
|
|
385
391
|
// Apply inverse rotation to get local translation
|
|
386
|
-
|
|
392
|
+
// Use provided rotation (animation rotation) or fall back to current localRotation
|
|
393
|
+
// Using animation rotation prevents conflicts when IK modifies the rotation
|
|
394
|
+
const localRotation = rotation ?? localRot[boneIdx];
|
|
387
395
|
// Clone to avoid mutating, then conjugate and normalize
|
|
388
396
|
const invRotation = localRotation.clone().conjugate().normalize();
|
|
389
397
|
const rotationMat = Mat4.fromQuat(invRotation.x, invRotation.y, invRotation.z, invRotation.w);
|
|
@@ -456,6 +464,49 @@ export class Model {
|
|
|
456
464
|
this.runtimeMorph.weights[idx] = startWeight;
|
|
457
465
|
this.applyMorphs();
|
|
458
466
|
}
|
|
467
|
+
/**
|
|
468
|
+
* Atomic pose setter for external animation editors.
|
|
469
|
+
* Sets bone rotations, translations, and morph weights in a single pass,
|
|
470
|
+
* identical to how getPoseAtTime applies VMD poses during playback.
|
|
471
|
+
* Cancels any active tweens on affected bones/morphs.
|
|
472
|
+
*/
|
|
473
|
+
setPose(rotations, translations, morphs) {
|
|
474
|
+
const state = this.tweenState;
|
|
475
|
+
if (rotations) {
|
|
476
|
+
for (const [name, quat] of Object.entries(rotations)) {
|
|
477
|
+
const idx = this.runtimeSkeleton.nameIndex[name] ?? -1;
|
|
478
|
+
if (idx < 0 || idx >= this.skeleton.bones.length)
|
|
479
|
+
continue;
|
|
480
|
+
this.runtimeSkeleton.localRotations[idx].set(quat.clone().normalize());
|
|
481
|
+
state.rotActive[idx] = 0;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
if (translations) {
|
|
485
|
+
for (const [name, vec] of Object.entries(translations)) {
|
|
486
|
+
const idx = this.runtimeSkeleton.nameIndex[name] ?? -1;
|
|
487
|
+
if (idx < 0 || idx >= this.skeleton.bones.length)
|
|
488
|
+
continue;
|
|
489
|
+
const rotation = rotations?.[name]?.clone().normalize();
|
|
490
|
+
const localTranslation = this.convertVMDTranslationToLocal(idx, vec, rotation);
|
|
491
|
+
this.runtimeSkeleton.localTranslations[idx].set(localTranslation);
|
|
492
|
+
state.transActive[idx] = 0;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
if (morphs) {
|
|
496
|
+
let morphChanged = false;
|
|
497
|
+
for (const [name, weight] of Object.entries(morphs)) {
|
|
498
|
+
const idx = this.runtimeMorph.nameIndex[name] ?? -1;
|
|
499
|
+
if (idx < 0 || idx >= this.runtimeMorph.weights.length)
|
|
500
|
+
continue;
|
|
501
|
+
this.runtimeMorph.weights[idx] = Math.max(0, Math.min(1, weight));
|
|
502
|
+
state.morphActive[idx] = 0;
|
|
503
|
+
morphChanged = true;
|
|
504
|
+
}
|
|
505
|
+
if (morphChanged) {
|
|
506
|
+
this.applyMorphs();
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
459
510
|
applyMorphs() {
|
|
460
511
|
// Reset vertex data to base positions
|
|
461
512
|
this.vertexData.set(this.baseVertexData);
|
|
@@ -714,9 +765,12 @@ export class Model {
|
|
|
714
765
|
const localTrans = this.runtimeSkeleton.localTranslations[boneIdx];
|
|
715
766
|
if (!frameB) {
|
|
716
767
|
// No interpolation needed - direct assignment
|
|
717
|
-
|
|
718
|
-
//
|
|
719
|
-
const
|
|
768
|
+
// Use animation frame's rotation for translation conversion to ensure consistency
|
|
769
|
+
// This prevents conflicts when IK later modifies the rotation
|
|
770
|
+
const frameRotation = frameA.rotation;
|
|
771
|
+
localRot.set(frameRotation);
|
|
772
|
+
// Convert VMD relative translation to local translation using animation rotation
|
|
773
|
+
const localTranslation = this.convertVMDTranslationToLocal(boneIdx, frameA.translation, frameRotation);
|
|
720
774
|
localTrans.set(localTranslation);
|
|
721
775
|
}
|
|
722
776
|
else {
|
|
@@ -737,8 +791,10 @@ export class Model {
|
|
|
737
791
|
const tzWeight = getWeight(32);
|
|
738
792
|
// Interpolate VMD relative translations (relative to bind pose world position)
|
|
739
793
|
const interpolatedVMDTranslation = new Vec3(frameA.translation.x + (frameB.translation.x - frameA.translation.x) * txWeight, frameA.translation.y + (frameB.translation.y - frameA.translation.y) * tyWeight, frameA.translation.z + (frameB.translation.z - frameA.translation.z) * tzWeight);
|
|
740
|
-
// Convert interpolated VMD translation to local translation
|
|
741
|
-
|
|
794
|
+
// Convert interpolated VMD translation to local translation using animation rotation
|
|
795
|
+
// This ensures translation is computed for the animation rotation, not the runtime rotation
|
|
796
|
+
// that will be modified by IK, preventing conflicts
|
|
797
|
+
const localTranslation = this.convertVMDTranslationToLocal(boneIdx, interpolatedVMDTranslation, rotation);
|
|
742
798
|
// Direct property writes to avoid object allocation
|
|
743
799
|
localRot.set(rotation);
|
|
744
800
|
localTrans.set(localTranslation);
|
|
@@ -821,7 +877,111 @@ export class Model {
|
|
|
821
877
|
const ikChainInfo = this.runtimeSkeleton.ikChainInfo;
|
|
822
878
|
if (!ikChainInfo)
|
|
823
879
|
return;
|
|
824
|
-
|
|
880
|
+
// Solve each IK solver sequentially, ensuring consistent state between solvers
|
|
881
|
+
for (const solver of ikSolvers) {
|
|
882
|
+
// Recompute ALL world matrices before each solver starts
|
|
883
|
+
// This ensures each solver sees the effects of previous solvers on localRotations
|
|
884
|
+
this.computeWorldMatrices();
|
|
885
|
+
// Clear computed set for this solver's pass
|
|
886
|
+
this.ikComputedSet.clear();
|
|
887
|
+
// Solve this IK chain
|
|
888
|
+
// Pass callback that uses model's world matrix computation (handles append correctly)
|
|
889
|
+
IKSolverSystem.solve([solver], // Solve one at a time
|
|
890
|
+
this.skeleton.bones, this.runtimeSkeleton.localRotations, this.runtimeSkeleton.localTranslations, this.runtimeSkeleton.worldMatrices, ikChainInfo, (boneIndex, applyIK) => {
|
|
891
|
+
// Clear computed set for each bone update to allow recomputation in same iteration
|
|
892
|
+
this.ikComputedSet.delete(boneIndex);
|
|
893
|
+
this.computeSingleBoneWorldMatrix(boneIndex, applyIK);
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
// Add this new method to compute a single bone's world matrix
|
|
898
|
+
// Recursively ensures parents are computed first to avoid using stale parent matrices
|
|
899
|
+
computeSingleBoneWorldMatrix(boneIndex, applyIK) {
|
|
900
|
+
const bones = this.skeleton.bones;
|
|
901
|
+
const localRot = this.runtimeSkeleton.localRotations;
|
|
902
|
+
const localTrans = this.runtimeSkeleton.localTranslations;
|
|
903
|
+
const worldMats = this.runtimeSkeleton.worldMatrices;
|
|
904
|
+
const ikChainInfo = this.runtimeSkeleton.ikChainInfo;
|
|
905
|
+
const b = bones[boneIndex];
|
|
906
|
+
// Prevent infinite recursion: if this bone is already being computed in this call chain, skip
|
|
907
|
+
if (this.ikComputedSet.has(boneIndex)) {
|
|
908
|
+
return;
|
|
909
|
+
}
|
|
910
|
+
// Mark this bone as being computed to prevent infinite recursion
|
|
911
|
+
this.ikComputedSet.add(boneIndex);
|
|
912
|
+
// Recursively compute parent first if it exists (ensures parent matrix is up-to-date)
|
|
913
|
+
if (b.parentIndex >= 0) {
|
|
914
|
+
this.computeSingleBoneWorldMatrix(b.parentIndex, applyIK);
|
|
915
|
+
}
|
|
916
|
+
// Get base rotation
|
|
917
|
+
let boneRot = localRot[boneIndex];
|
|
918
|
+
// Apply IK rotation if requested
|
|
919
|
+
if (applyIK && ikChainInfo) {
|
|
920
|
+
const chainInfo = ikChainInfo[boneIndex];
|
|
921
|
+
if (chainInfo?.ikRotation) {
|
|
922
|
+
boneRot = chainInfo.ikRotation.multiply(boneRot).normalize();
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
let rotateM = Mat4.fromQuat(boneRot.x, boneRot.y, boneRot.z, boneRot.w);
|
|
926
|
+
let addLocalTx = 0, addLocalTy = 0, addLocalTz = 0;
|
|
927
|
+
// Handle append transformations (same logic as computeWorldMatrices)
|
|
928
|
+
const appendParentIdx = b.appendParentIndex;
|
|
929
|
+
const hasAppend = b.appendRotate &&
|
|
930
|
+
appendParentIdx !== undefined &&
|
|
931
|
+
appendParentIdx >= 0 &&
|
|
932
|
+
appendParentIdx < bones.length;
|
|
933
|
+
if (hasAppend) {
|
|
934
|
+
const ratio = b.appendRatio === undefined ? 1 : Math.max(-1, Math.min(1, b.appendRatio));
|
|
935
|
+
const hasRatio = Math.abs(ratio) > 1e-6;
|
|
936
|
+
if (hasRatio) {
|
|
937
|
+
if (b.appendRotate) {
|
|
938
|
+
// Get append parent's rotation
|
|
939
|
+
// During IK solving, use only base local rotation (not IK rotations) to avoid
|
|
940
|
+
// conflicts with IK rotations that are still being computed incrementally
|
|
941
|
+
// IK rotations will be applied to localRotations after IK solving completes
|
|
942
|
+
if (appendParentIdx >= 0) {
|
|
943
|
+
// Compute append parent's world matrix for dependency order, but use base rotation for append
|
|
944
|
+
this.computeSingleBoneWorldMatrix(appendParentIdx, applyIK);
|
|
945
|
+
}
|
|
946
|
+
// Use append parent's base local rotation only (IK rotations are applied after solving)
|
|
947
|
+
let appendRot = localRot[appendParentIdx];
|
|
948
|
+
let ax = appendRot.x, ay = appendRot.y, az = appendRot.z;
|
|
949
|
+
const aw = appendRot.w;
|
|
950
|
+
const absRatio = ratio < 0 ? -ratio : ratio;
|
|
951
|
+
if (ratio < 0) {
|
|
952
|
+
ax = -ax;
|
|
953
|
+
ay = -ay;
|
|
954
|
+
az = -az;
|
|
955
|
+
}
|
|
956
|
+
const appendQuat = new Quat(ax, ay, az, aw);
|
|
957
|
+
const result = Quat.slerp(Quat.identity(), appendQuat, absRatio);
|
|
958
|
+
rotateM = Mat4.fromQuat(result.x, result.y, result.z, result.w).multiply(rotateM);
|
|
959
|
+
}
|
|
960
|
+
if (b.appendMove) {
|
|
961
|
+
const appendTrans = localTrans[appendParentIdx];
|
|
962
|
+
addLocalTx = appendTrans.x * ratio;
|
|
963
|
+
addLocalTy = appendTrans.y * ratio;
|
|
964
|
+
addLocalTz = appendTrans.z * ratio;
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
const boneTrans = localTrans[boneIndex];
|
|
969
|
+
const localTx = boneTrans.x + addLocalTx;
|
|
970
|
+
const localTy = boneTrans.y + addLocalTy;
|
|
971
|
+
const localTz = boneTrans.z + addLocalTz;
|
|
972
|
+
this.cachedIdentityMat1
|
|
973
|
+
.setIdentity()
|
|
974
|
+
.translateInPlace(b.bindTranslation[0], b.bindTranslation[1], b.bindTranslation[2]);
|
|
975
|
+
this.cachedIdentityMat2.setIdentity().translateInPlace(localTx, localTy, localTz);
|
|
976
|
+
const localM = this.cachedIdentityMat1.multiply(rotateM).multiply(this.cachedIdentityMat2);
|
|
977
|
+
const worldMat = worldMats[boneIndex];
|
|
978
|
+
if (b.parentIndex >= 0) {
|
|
979
|
+
const parentMat = worldMats[b.parentIndex];
|
|
980
|
+
Mat4.multiplyArrays(parentMat.values, 0, localM.values, 0, worldMat.values, 0);
|
|
981
|
+
}
|
|
982
|
+
else {
|
|
983
|
+
worldMat.values.set(localM.values);
|
|
984
|
+
}
|
|
825
985
|
}
|
|
826
986
|
computeWorldMatrices() {
|
|
827
987
|
const bones = this.skeleton.bones;
|
package/package.json
CHANGED
package/src/engine.ts
CHANGED
|
@@ -1155,6 +1155,14 @@ export class Engine {
|
|
|
1155
1155
|
this.currentModel?.moveBones(boneTranslations, durationMs)
|
|
1156
1156
|
}
|
|
1157
1157
|
|
|
1158
|
+
public setPose(
|
|
1159
|
+
rotations?: Record<string, Quat>,
|
|
1160
|
+
translations?: Record<string, Vec3>,
|
|
1161
|
+
morphs?: Record<string, number>
|
|
1162
|
+
): void {
|
|
1163
|
+
this.currentModel?.setPose(rotations, translations, morphs)
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1158
1166
|
public resetAllBones() {
|
|
1159
1167
|
this.currentModel?.resetAllBones()
|
|
1160
1168
|
}
|