reze-engine 0.2.19 → 0.3.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/README.md +67 -66
- package/dist/bezier-interpolate.d.ts +15 -0
- package/dist/bezier-interpolate.d.ts.map +1 -0
- package/dist/bezier-interpolate.js +40 -0
- package/dist/engine.d.ts +7 -9
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +252 -143
- package/dist/ik-solver.d.ts +26 -0
- package/dist/ik-solver.d.ts.map +1 -0
- package/dist/ik-solver.js +372 -0
- package/dist/math.d.ts +1 -0
- package/dist/math.d.ts.map +1 -1
- package/dist/math.js +8 -0
- package/dist/model.d.ts +46 -1
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +201 -3
- package/dist/pmx-loader.d.ts.map +1 -1
- package/dist/pmx-loader.js +57 -36
- package/dist/vmd-loader.d.ts +11 -1
- package/dist/vmd-loader.d.ts.map +1 -1
- package/dist/vmd-loader.js +91 -15
- package/package.json +1 -1
- package/src/bezier-interpolate.ts +47 -0
- package/src/camera.ts +358 -358
- package/src/engine.ts +275 -164
- package/src/ik-solver.ts +488 -0
- package/src/math.ts +555 -546
- package/src/model.ts +284 -3
- package/src/physics.ts +752 -752
- package/src/pmx-loader.ts +1173 -1145
- package/src/vmd-loader.ts +276 -179
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IK Solver implementation
|
|
3
|
+
* Based on reference from babylon-mmd and Saba MMD library
|
|
4
|
+
* https://github.com/benikabocha/saba/blob/master/src/Saba/Model/MMD/MMDIkSolver.cpp
|
|
5
|
+
*/
|
|
6
|
+
import { Mat4, Quat, Vec3 } from "./math";
|
|
7
|
+
var InternalEulerRotationOrder;
|
|
8
|
+
(function (InternalEulerRotationOrder) {
|
|
9
|
+
InternalEulerRotationOrder[InternalEulerRotationOrder["YXZ"] = 0] = "YXZ";
|
|
10
|
+
InternalEulerRotationOrder[InternalEulerRotationOrder["ZYX"] = 1] = "ZYX";
|
|
11
|
+
InternalEulerRotationOrder[InternalEulerRotationOrder["XZY"] = 2] = "XZY";
|
|
12
|
+
})(InternalEulerRotationOrder || (InternalEulerRotationOrder = {}));
|
|
13
|
+
var InternalSolveAxis;
|
|
14
|
+
(function (InternalSolveAxis) {
|
|
15
|
+
InternalSolveAxis[InternalSolveAxis["None"] = 0] = "None";
|
|
16
|
+
InternalSolveAxis[InternalSolveAxis["Fixed"] = 1] = "Fixed";
|
|
17
|
+
InternalSolveAxis[InternalSolveAxis["X"] = 2] = "X";
|
|
18
|
+
InternalSolveAxis[InternalSolveAxis["Y"] = 3] = "Y";
|
|
19
|
+
InternalSolveAxis[InternalSolveAxis["Z"] = 4] = "Z";
|
|
20
|
+
})(InternalSolveAxis || (InternalSolveAxis = {}));
|
|
21
|
+
class IKChain {
|
|
22
|
+
constructor(boneIndex, link) {
|
|
23
|
+
this.boneIndex = boneIndex;
|
|
24
|
+
if (link.hasLimit && link.minAngle && link.maxAngle) {
|
|
25
|
+
// Normalize min/max angles
|
|
26
|
+
const minX = Math.min(link.minAngle.x, link.maxAngle.x);
|
|
27
|
+
const minY = Math.min(link.minAngle.y, link.maxAngle.y);
|
|
28
|
+
const minZ = Math.min(link.minAngle.z, link.maxAngle.z);
|
|
29
|
+
const maxX = Math.max(link.minAngle.x, link.maxAngle.x);
|
|
30
|
+
const maxY = Math.max(link.minAngle.y, link.maxAngle.y);
|
|
31
|
+
const maxZ = Math.max(link.minAngle.z, link.maxAngle.z);
|
|
32
|
+
this.minimumAngle = new Vec3(minX, minY, minZ);
|
|
33
|
+
this.maximumAngle = new Vec3(maxX, maxY, maxZ);
|
|
34
|
+
// Determine rotation order based on constraint ranges
|
|
35
|
+
const halfPi = Math.PI * 0.5;
|
|
36
|
+
if (-halfPi < minX && maxX < halfPi) {
|
|
37
|
+
this.rotationOrder = InternalEulerRotationOrder.YXZ;
|
|
38
|
+
}
|
|
39
|
+
else if (-halfPi < minY && maxY < halfPi) {
|
|
40
|
+
this.rotationOrder = InternalEulerRotationOrder.ZYX;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
this.rotationOrder = InternalEulerRotationOrder.XZY;
|
|
44
|
+
}
|
|
45
|
+
// Determine solve axis optimization
|
|
46
|
+
if (minX === 0 && maxX === 0 && minY === 0 && maxY === 0 && minZ === 0 && maxZ === 0) {
|
|
47
|
+
this.solveAxis = InternalSolveAxis.Fixed;
|
|
48
|
+
}
|
|
49
|
+
else if (minY === 0 && maxY === 0 && minZ === 0 && maxZ === 0) {
|
|
50
|
+
this.solveAxis = InternalSolveAxis.X;
|
|
51
|
+
}
|
|
52
|
+
else if (minX === 0 && maxX === 0 && minZ === 0 && maxZ === 0) {
|
|
53
|
+
this.solveAxis = InternalSolveAxis.Y;
|
|
54
|
+
}
|
|
55
|
+
else if (minX === 0 && maxX === 0 && minY === 0 && maxY === 0) {
|
|
56
|
+
this.solveAxis = InternalSolveAxis.Z;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
this.solveAxis = InternalSolveAxis.None;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
this.minimumAngle = null;
|
|
64
|
+
this.maximumAngle = null;
|
|
65
|
+
this.rotationOrder = InternalEulerRotationOrder.XZY; // not used
|
|
66
|
+
this.solveAxis = InternalSolveAxis.None;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Solve IK chains for a model
|
|
72
|
+
*/
|
|
73
|
+
export class IKSolverSystem {
|
|
74
|
+
/**
|
|
75
|
+
* Solve all IK chains
|
|
76
|
+
*/
|
|
77
|
+
static solve(ikSolvers, bones, localRotations, localTranslations, worldMatrices, ikChainInfo, usePhysics = false) {
|
|
78
|
+
for (const solver of ikSolvers) {
|
|
79
|
+
if (usePhysics && solver.canSkipWhenPhysicsEnabled) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
this.solveIK(solver, bones, localRotations, localTranslations, worldMatrices, ikChainInfo);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
static solveIK(solver, bones, localRotations, localTranslations, worldMatrices, ikChainInfo) {
|
|
86
|
+
if (solver.links.length === 0)
|
|
87
|
+
return;
|
|
88
|
+
const ikBoneIndex = solver.ikBoneIndex;
|
|
89
|
+
const targetBoneIndex = solver.targetBoneIndex;
|
|
90
|
+
// Reset IK rotations
|
|
91
|
+
for (const link of solver.links) {
|
|
92
|
+
const chainInfo = ikChainInfo[link.boneIndex];
|
|
93
|
+
if (chainInfo) {
|
|
94
|
+
chainInfo.ikRotation = new Quat(0, 0, 0, 1);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Get IK bone and target positions
|
|
98
|
+
const ikPosition = this.getWorldTranslation(ikBoneIndex, worldMatrices);
|
|
99
|
+
const targetPosition = this.getWorldTranslation(targetBoneIndex, worldMatrices);
|
|
100
|
+
if (ikPosition.subtract(targetPosition).length() < this.EPSILON)
|
|
101
|
+
return;
|
|
102
|
+
// Build IK chains
|
|
103
|
+
const chains = [];
|
|
104
|
+
for (const link of solver.links) {
|
|
105
|
+
chains.push(new IKChain(link.boneIndex, link));
|
|
106
|
+
}
|
|
107
|
+
// Update chain bones and target bone world matrices (initial state, no IK yet)
|
|
108
|
+
for (let i = chains.length - 1; i >= 0; i--) {
|
|
109
|
+
this.updateWorldMatrix(chains[i].boneIndex, bones, localRotations, localTranslations, worldMatrices);
|
|
110
|
+
}
|
|
111
|
+
this.updateWorldMatrix(targetBoneIndex, bones, localRotations, localTranslations, worldMatrices);
|
|
112
|
+
// Re-read positions after initial update
|
|
113
|
+
const updatedIkPosition = this.getWorldTranslation(ikBoneIndex, worldMatrices);
|
|
114
|
+
const updatedTargetPosition = this.getWorldTranslation(targetBoneIndex, worldMatrices);
|
|
115
|
+
if (updatedIkPosition.subtract(updatedTargetPosition).length() < this.EPSILON)
|
|
116
|
+
return;
|
|
117
|
+
// Solve iteratively
|
|
118
|
+
const iteration = Math.min(solver.iterationCount, 256);
|
|
119
|
+
const halfIteration = iteration >> 1;
|
|
120
|
+
for (let i = 0; i < iteration; i++) {
|
|
121
|
+
for (let chainIndex = 0; chainIndex < chains.length; chainIndex++) {
|
|
122
|
+
const chain = chains[chainIndex];
|
|
123
|
+
if (chain.solveAxis !== InternalSolveAxis.Fixed) {
|
|
124
|
+
this.solveChain(chain, chainIndex, solver, ikBoneIndex, targetBoneIndex, bones, localRotations, localTranslations, worldMatrices, ikChainInfo, i < halfIteration);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Re-read positions after this iteration
|
|
128
|
+
const currentIkPosition = this.getWorldTranslation(ikBoneIndex, worldMatrices);
|
|
129
|
+
const currentTargetPosition = this.getWorldTranslation(targetBoneIndex, worldMatrices);
|
|
130
|
+
const distance = currentIkPosition.subtract(currentTargetPosition).length();
|
|
131
|
+
if (distance < this.EPSILON)
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
// Apply IK rotations to local rotations
|
|
135
|
+
for (const link of solver.links) {
|
|
136
|
+
const chainInfo = ikChainInfo[link.boneIndex];
|
|
137
|
+
if (chainInfo && chainInfo.ikRotation) {
|
|
138
|
+
const qi = link.boneIndex * 4;
|
|
139
|
+
const localRot = new Quat(localRotations[qi], localRotations[qi + 1], localRotations[qi + 2], localRotations[qi + 3]);
|
|
140
|
+
const finalRot = chainInfo.ikRotation.multiply(localRot).normalize();
|
|
141
|
+
localRotations[qi] = finalRot.x;
|
|
142
|
+
localRotations[qi + 1] = finalRot.y;
|
|
143
|
+
localRotations[qi + 2] = finalRot.z;
|
|
144
|
+
localRotations[qi + 3] = finalRot.w;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
static solveChain(chain, chainIndex, solver, ikBoneIndex, targetBoneIndex, bones, localRotations, localTranslations, worldMatrices, ikChainInfo, useAxis) {
|
|
149
|
+
const chainBoneIndex = chain.boneIndex;
|
|
150
|
+
const chainPosition = this.getWorldTranslation(chainBoneIndex, worldMatrices);
|
|
151
|
+
const ikPosition = this.getWorldTranslation(ikBoneIndex, worldMatrices);
|
|
152
|
+
const targetPosition = this.getWorldTranslation(targetBoneIndex, worldMatrices);
|
|
153
|
+
const chainTargetVector = chainPosition.subtract(targetPosition).normalize();
|
|
154
|
+
const chainIkVector = chainPosition.subtract(ikPosition).normalize();
|
|
155
|
+
const chainRotationAxis = chainTargetVector.cross(chainIkVector);
|
|
156
|
+
if (chainRotationAxis.length() < this.EPSILON)
|
|
157
|
+
return;
|
|
158
|
+
// Get parent's world rotation matrix (translation removed)
|
|
159
|
+
const parentWorldRotMatrix = this.getParentWorldRotationMatrix(chainBoneIndex, bones, worldMatrices);
|
|
160
|
+
let finalRotationAxis;
|
|
161
|
+
if (chain.minimumAngle !== null && useAxis) {
|
|
162
|
+
switch (chain.solveAxis) {
|
|
163
|
+
case InternalSolveAxis.None: {
|
|
164
|
+
const invParentRot = parentWorldRotMatrix.inverse();
|
|
165
|
+
finalRotationAxis = this.transformNormal(chainRotationAxis, invParentRot).normalize();
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
case InternalSolveAxis.X: {
|
|
169
|
+
const m = parentWorldRotMatrix.values;
|
|
170
|
+
const axisX = new Vec3(m[0], m[1], m[2]);
|
|
171
|
+
const dot = chainRotationAxis.dot(axisX);
|
|
172
|
+
finalRotationAxis = new Vec3(dot >= 0 ? 1 : -1, 0, 0);
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
case InternalSolveAxis.Y: {
|
|
176
|
+
const m = parentWorldRotMatrix.values;
|
|
177
|
+
const axisY = new Vec3(m[4], m[5], m[6]);
|
|
178
|
+
const dot = chainRotationAxis.dot(axisY);
|
|
179
|
+
finalRotationAxis = new Vec3(0, dot >= 0 ? 1 : -1, 0);
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
case InternalSolveAxis.Z: {
|
|
183
|
+
const m = parentWorldRotMatrix.values;
|
|
184
|
+
const axisZ = new Vec3(m[8], m[9], m[10]);
|
|
185
|
+
const dot = chainRotationAxis.dot(axisZ);
|
|
186
|
+
finalRotationAxis = new Vec3(0, 0, dot >= 0 ? 1 : -1);
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
default:
|
|
190
|
+
finalRotationAxis = chainRotationAxis;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
const invParentRot = parentWorldRotMatrix.inverse();
|
|
195
|
+
finalRotationAxis = this.transformNormal(chainRotationAxis, invParentRot).normalize();
|
|
196
|
+
}
|
|
197
|
+
let dot = chainTargetVector.dot(chainIkVector);
|
|
198
|
+
dot = Math.max(-1.0, Math.min(1.0, dot));
|
|
199
|
+
const angle = Math.min(solver.limitAngle * (chainIndex + 1), Math.acos(dot));
|
|
200
|
+
const ikRotation = Quat.fromAxisAngle(finalRotationAxis, angle);
|
|
201
|
+
const chainInfo = ikChainInfo[chainBoneIndex];
|
|
202
|
+
if (chainInfo) {
|
|
203
|
+
chainInfo.ikRotation = ikRotation.multiply(chainInfo.ikRotation);
|
|
204
|
+
// Apply angle constraints if present
|
|
205
|
+
if (chain.minimumAngle !== null && chain.maximumAngle !== null) {
|
|
206
|
+
const qi = chainBoneIndex * 4;
|
|
207
|
+
const localRot = new Quat(localRotations[qi], localRotations[qi + 1], localRotations[qi + 2], localRotations[qi + 3]);
|
|
208
|
+
chainInfo.localRotation = localRot.clone();
|
|
209
|
+
const combinedRot = chainInfo.ikRotation.multiply(localRot);
|
|
210
|
+
const rotMatrix = Mat4.fromQuat(combinedRot.x, combinedRot.y, combinedRot.z, combinedRot.w);
|
|
211
|
+
const m = rotMatrix.values;
|
|
212
|
+
let rX, rY, rZ;
|
|
213
|
+
switch (chain.rotationOrder) {
|
|
214
|
+
case InternalEulerRotationOrder.YXZ: {
|
|
215
|
+
rX = Math.asin(-m[9]); // m32
|
|
216
|
+
if (Math.abs(rX) > this.THRESHOLD) {
|
|
217
|
+
rX = rX < 0 ? -this.THRESHOLD : this.THRESHOLD;
|
|
218
|
+
}
|
|
219
|
+
let cosX = Math.cos(rX);
|
|
220
|
+
if (cosX !== 0)
|
|
221
|
+
cosX = 1 / cosX;
|
|
222
|
+
rY = Math.atan2(m[8] * cosX, m[10] * cosX); // m31, m33
|
|
223
|
+
rZ = Math.atan2(m[1] * cosX, m[5] * cosX); // m12, m22
|
|
224
|
+
rX = this.limitAngle(rX, chain.minimumAngle.x, chain.maximumAngle.x, useAxis);
|
|
225
|
+
rY = this.limitAngle(rY, chain.minimumAngle.y, chain.maximumAngle.y, useAxis);
|
|
226
|
+
rZ = this.limitAngle(rZ, chain.minimumAngle.z, chain.maximumAngle.z, useAxis);
|
|
227
|
+
chainInfo.ikRotation = Quat.fromAxisAngle(new Vec3(0, 1, 0), rY);
|
|
228
|
+
chainInfo.ikRotation = chainInfo.ikRotation.multiply(Quat.fromAxisAngle(new Vec3(1, 0, 0), rX));
|
|
229
|
+
chainInfo.ikRotation = chainInfo.ikRotation.multiply(Quat.fromAxisAngle(new Vec3(0, 0, 1), rZ));
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
case InternalEulerRotationOrder.ZYX: {
|
|
233
|
+
rY = Math.asin(-m[2]); // m13
|
|
234
|
+
if (Math.abs(rY) > this.THRESHOLD) {
|
|
235
|
+
rY = rY < 0 ? -this.THRESHOLD : this.THRESHOLD;
|
|
236
|
+
}
|
|
237
|
+
let cosY = Math.cos(rY);
|
|
238
|
+
if (cosY !== 0)
|
|
239
|
+
cosY = 1 / cosY;
|
|
240
|
+
rX = Math.atan2(m[6] * cosY, m[10] * cosY); // m23, m33
|
|
241
|
+
rZ = Math.atan2(m[1] * cosY, m[0] * cosY); // m12, m11
|
|
242
|
+
rX = this.limitAngle(rX, chain.minimumAngle.x, chain.maximumAngle.x, useAxis);
|
|
243
|
+
rY = this.limitAngle(rY, chain.minimumAngle.y, chain.maximumAngle.y, useAxis);
|
|
244
|
+
rZ = this.limitAngle(rZ, chain.minimumAngle.z, chain.maximumAngle.z, useAxis);
|
|
245
|
+
chainInfo.ikRotation = Quat.fromAxisAngle(new Vec3(0, 0, 1), rZ);
|
|
246
|
+
chainInfo.ikRotation = chainInfo.ikRotation.multiply(Quat.fromAxisAngle(new Vec3(0, 1, 0), rY));
|
|
247
|
+
chainInfo.ikRotation = chainInfo.ikRotation.multiply(Quat.fromAxisAngle(new Vec3(1, 0, 0), rX));
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
case InternalEulerRotationOrder.XZY: {
|
|
251
|
+
rZ = Math.asin(-m[4]); // m21
|
|
252
|
+
if (Math.abs(rZ) > this.THRESHOLD) {
|
|
253
|
+
rZ = rZ < 0 ? -this.THRESHOLD : this.THRESHOLD;
|
|
254
|
+
}
|
|
255
|
+
let cosZ = Math.cos(rZ);
|
|
256
|
+
if (cosZ !== 0)
|
|
257
|
+
cosZ = 1 / cosZ;
|
|
258
|
+
rX = Math.atan2(m[6] * cosZ, m[5] * cosZ); // m23, m22
|
|
259
|
+
rY = Math.atan2(m[8] * cosZ, m[0] * cosZ); // m31, m11
|
|
260
|
+
rX = this.limitAngle(rX, chain.minimumAngle.x, chain.maximumAngle.x, useAxis);
|
|
261
|
+
rY = this.limitAngle(rY, chain.minimumAngle.y, chain.maximumAngle.y, useAxis);
|
|
262
|
+
rZ = this.limitAngle(rZ, chain.minimumAngle.z, chain.maximumAngle.z, useAxis);
|
|
263
|
+
chainInfo.ikRotation = Quat.fromAxisAngle(new Vec3(1, 0, 0), rX);
|
|
264
|
+
chainInfo.ikRotation = chainInfo.ikRotation.multiply(Quat.fromAxisAngle(new Vec3(0, 0, 1), rZ));
|
|
265
|
+
chainInfo.ikRotation = chainInfo.ikRotation.multiply(Quat.fromAxisAngle(new Vec3(0, 1, 0), rY));
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
const invertedLocalRotation = localRot.conjugate().normalize();
|
|
270
|
+
chainInfo.ikRotation = chainInfo.ikRotation.multiply(invertedLocalRotation);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
// Update world matrices for affected bones (using IK-modified rotations)
|
|
274
|
+
for (let i = chainIndex; i >= 0; i--) {
|
|
275
|
+
const link = solver.links[i];
|
|
276
|
+
this.updateWorldMatrixWithIK(link.boneIndex, bones, localRotations, localTranslations, worldMatrices, ikChainInfo);
|
|
277
|
+
}
|
|
278
|
+
this.updateWorldMatrix(targetBoneIndex, bones, localRotations, localTranslations, worldMatrices);
|
|
279
|
+
}
|
|
280
|
+
static limitAngle(angle, min, max, useAxis) {
|
|
281
|
+
if (angle < min) {
|
|
282
|
+
const diff = 2 * min - angle;
|
|
283
|
+
return diff <= max && useAxis ? diff : min;
|
|
284
|
+
}
|
|
285
|
+
else if (angle > max) {
|
|
286
|
+
const diff = 2 * max - angle;
|
|
287
|
+
return diff >= min && useAxis ? diff : max;
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
return angle;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
static getWorldTranslation(boneIndex, worldMatrices) {
|
|
294
|
+
const offset = boneIndex * 16;
|
|
295
|
+
return new Vec3(worldMatrices[offset + 12], worldMatrices[offset + 13], worldMatrices[offset + 14]);
|
|
296
|
+
}
|
|
297
|
+
static getParentWorldRotationMatrix(boneIndex, bones, worldMatrices) {
|
|
298
|
+
const bone = bones[boneIndex];
|
|
299
|
+
if (bone.parentIndex >= 0) {
|
|
300
|
+
const parentOffset = bone.parentIndex * 16;
|
|
301
|
+
const parentMat = new Mat4(worldMatrices.subarray(parentOffset, parentOffset + 16));
|
|
302
|
+
// Remove translation
|
|
303
|
+
const rotMat = Mat4.identity();
|
|
304
|
+
const m = parentMat.values;
|
|
305
|
+
rotMat.values.set([m[0], m[1], m[2], 0, m[4], m[5], m[6], 0, m[8], m[9], m[10], 0, 0, 0, 0, 1]);
|
|
306
|
+
return rotMat;
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
return Mat4.identity();
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
static transformNormal(normal, matrix) {
|
|
313
|
+
const m = matrix.values;
|
|
314
|
+
return new Vec3(m[0] * normal.x + m[4] * normal.y + m[8] * normal.z, m[1] * normal.x + m[5] * normal.y + m[9] * normal.z, m[2] * normal.x + m[6] * normal.y + m[10] * normal.z);
|
|
315
|
+
}
|
|
316
|
+
static updateWorldMatrixWithIK(boneIndex, bones, localRotations, localTranslations, worldMatrices, ikChainInfo) {
|
|
317
|
+
const bone = bones[boneIndex];
|
|
318
|
+
const qi = boneIndex * 4;
|
|
319
|
+
const ti = boneIndex * 3;
|
|
320
|
+
// Use IK-modified rotation if available
|
|
321
|
+
const localRot = new Quat(localRotations[qi], localRotations[qi + 1], localRotations[qi + 2], localRotations[qi + 3]);
|
|
322
|
+
const chainInfo = ikChainInfo[boneIndex];
|
|
323
|
+
let finalRot = localRot;
|
|
324
|
+
if (chainInfo && chainInfo.ikRotation) {
|
|
325
|
+
finalRot = chainInfo.ikRotation.multiply(localRot).normalize();
|
|
326
|
+
}
|
|
327
|
+
const rotateM = Mat4.fromQuat(finalRot.x, finalRot.y, finalRot.z, finalRot.w);
|
|
328
|
+
const localTx = localTranslations[ti];
|
|
329
|
+
const localTy = localTranslations[ti + 1];
|
|
330
|
+
const localTz = localTranslations[ti + 2];
|
|
331
|
+
const localM = Mat4.identity()
|
|
332
|
+
.translateInPlace(bone.bindTranslation[0], bone.bindTranslation[1], bone.bindTranslation[2])
|
|
333
|
+
.multiply(rotateM)
|
|
334
|
+
.translateInPlace(localTx, localTy, localTz);
|
|
335
|
+
const worldOffset = boneIndex * 16;
|
|
336
|
+
if (bone.parentIndex >= 0) {
|
|
337
|
+
const parentOffset = bone.parentIndex * 16;
|
|
338
|
+
const parentMat = new Mat4(worldMatrices.subarray(parentOffset, parentOffset + 16));
|
|
339
|
+
const worldMat = parentMat.multiply(localM);
|
|
340
|
+
worldMatrices.subarray(worldOffset, worldOffset + 16).set(worldMat.values);
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
worldMatrices.subarray(worldOffset, worldOffset + 16).set(localM.values);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
static updateWorldMatrix(boneIndex, bones, localRotations, localTranslations, worldMatrices) {
|
|
347
|
+
const bone = bones[boneIndex];
|
|
348
|
+
const qi = boneIndex * 4;
|
|
349
|
+
const ti = boneIndex * 3;
|
|
350
|
+
const localRot = new Quat(localRotations[qi], localRotations[qi + 1], localRotations[qi + 2], localRotations[qi + 3]);
|
|
351
|
+
const rotateM = Mat4.fromQuat(localRot.x, localRot.y, localRot.z, localRot.w);
|
|
352
|
+
const localTx = localTranslations[ti];
|
|
353
|
+
const localTy = localTranslations[ti + 1];
|
|
354
|
+
const localTz = localTranslations[ti + 2];
|
|
355
|
+
const localM = Mat4.identity()
|
|
356
|
+
.translateInPlace(bone.bindTranslation[0], bone.bindTranslation[1], bone.bindTranslation[2])
|
|
357
|
+
.multiply(rotateM)
|
|
358
|
+
.translateInPlace(localTx, localTy, localTz);
|
|
359
|
+
const worldOffset = boneIndex * 16;
|
|
360
|
+
if (bone.parentIndex >= 0) {
|
|
361
|
+
const parentOffset = bone.parentIndex * 16;
|
|
362
|
+
const parentMat = new Mat4(worldMatrices.subarray(parentOffset, parentOffset + 16));
|
|
363
|
+
const worldMat = parentMat.multiply(localM);
|
|
364
|
+
worldMatrices.subarray(worldOffset, worldOffset + 16).set(worldMat.values);
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
worldMatrices.subarray(worldOffset, worldOffset + 16).set(localM.values);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
IKSolverSystem.EPSILON = 1.0e-8;
|
|
372
|
+
IKSolverSystem.THRESHOLD = (88 * Math.PI) / 180;
|
package/dist/math.d.ts
CHANGED
|
@@ -28,6 +28,7 @@ export declare class Quat {
|
|
|
28
28
|
rotateVec(v: Vec3): Vec3;
|
|
29
29
|
rotate(v: Vec3): Vec3;
|
|
30
30
|
static fromTo(from: Vec3, to: Vec3): Quat;
|
|
31
|
+
static fromAxisAngle(axis: Vec3, angle: number): Quat;
|
|
31
32
|
toArray(): [number, number, number, number];
|
|
32
33
|
static slerp(a: Quat, b: Quat, t: number): Quat;
|
|
33
34
|
static fromEuler(rotX: number, rotY: number, rotZ: number): Quat;
|
package/dist/math.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../src/math.ts"],"names":[],"mappings":"AACA,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED,qBAAa,IAAI;IACf,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;gBAEG,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM;IAM3C,GAAG,CAAC,KAAK,EAAE,IAAI,GAAG,IAAI;IAItB,QAAQ,CAAC,KAAK,EAAE,IAAI,GAAG,IAAI;IAI3B,MAAM,IAAI,MAAM;IAIhB,SAAS,IAAI,IAAI;IAMjB,KAAK,CAAC,KAAK,EAAE,IAAI,GAAG,IAAI;IAQxB,GAAG,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM;IAIxB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI3B,KAAK,IAAI,IAAI;CAGd;AAED,qBAAa,IAAI;IACf,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;gBAEG,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM;IAOtD,GAAG,CAAC,KAAK,EAAE,IAAI,GAAG,IAAI;IAItB,KAAK,IAAI,IAAI;IAIb,QAAQ,CAAC,KAAK,EAAE,IAAI,GAAG,IAAI;IAU3B,SAAS,IAAI,IAAI;IAKjB,MAAM,IAAI,MAAM;IAIhB,SAAS,IAAI,IAAI;IAOjB,SAAS,CAAC,CAAC,EAAE,IAAI,GAAG,IAAI;IAwBxB,MAAM,CAAC,CAAC,EAAE,IAAI,GAAG,IAAI;IAQrB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../src/math.ts"],"names":[],"mappings":"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"}
|
package/dist/math.js
CHANGED
|
@@ -102,6 +102,14 @@ export class Quat {
|
|
|
102
102
|
const invW = 1 / w;
|
|
103
103
|
return new Quat(axis.x * invW, axis.y * invW, axis.z * invW, w * 0.5).normalize();
|
|
104
104
|
}
|
|
105
|
+
// Static method: create quaternion from rotation axis and angle
|
|
106
|
+
static fromAxisAngle(axis, angle) {
|
|
107
|
+
const normalizedAxis = axis.normalize();
|
|
108
|
+
const halfAngle = angle * 0.5;
|
|
109
|
+
const sinHalf = Math.sin(halfAngle);
|
|
110
|
+
const cosHalf = Math.cos(halfAngle);
|
|
111
|
+
return new Quat(normalizedAxis.x * sinHalf, normalizedAxis.y * sinHalf, normalizedAxis.z * sinHalf, cosHalf);
|
|
112
|
+
}
|
|
105
113
|
toArray() {
|
|
106
114
|
return [this.x, this.y, this.z, this.w];
|
|
107
115
|
}
|
package/dist/model.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Quat } from "./math";
|
|
1
|
+
import { Quat, Vec3 } from "./math";
|
|
2
2
|
import { Rigidbody, Joint } from "./physics";
|
|
3
3
|
export interface Texture {
|
|
4
4
|
path: string;
|
|
@@ -32,6 +32,43 @@ export interface Bone {
|
|
|
32
32
|
appendRatio?: number;
|
|
33
33
|
appendRotate?: boolean;
|
|
34
34
|
appendMove?: boolean;
|
|
35
|
+
ikTargetIndex?: number;
|
|
36
|
+
ikIteration?: number;
|
|
37
|
+
ikLimitAngle?: number;
|
|
38
|
+
ikLinks?: IKLink[];
|
|
39
|
+
}
|
|
40
|
+
export interface IKLink {
|
|
41
|
+
boneIndex: number;
|
|
42
|
+
hasLimit: boolean;
|
|
43
|
+
minAngle?: Vec3;
|
|
44
|
+
maxAngle?: Vec3;
|
|
45
|
+
rotationOrder?: EulerRotationOrder;
|
|
46
|
+
solveAxis?: SolveAxis;
|
|
47
|
+
}
|
|
48
|
+
export declare enum EulerRotationOrder {
|
|
49
|
+
YXZ = 0,
|
|
50
|
+
ZYX = 1,
|
|
51
|
+
XZY = 2
|
|
52
|
+
}
|
|
53
|
+
export declare enum SolveAxis {
|
|
54
|
+
None = 0,
|
|
55
|
+
Fixed = 1,
|
|
56
|
+
X = 2,
|
|
57
|
+
Y = 3,
|
|
58
|
+
Z = 4
|
|
59
|
+
}
|
|
60
|
+
export interface IKSolver {
|
|
61
|
+
index: number;
|
|
62
|
+
ikBoneIndex: number;
|
|
63
|
+
targetBoneIndex: number;
|
|
64
|
+
iterationCount: number;
|
|
65
|
+
limitAngle: number;
|
|
66
|
+
links: IKLink[];
|
|
67
|
+
canSkipWhenPhysicsEnabled: boolean;
|
|
68
|
+
}
|
|
69
|
+
export interface IKChainInfo {
|
|
70
|
+
ikRotation: Quat;
|
|
71
|
+
localRotation: Quat;
|
|
35
72
|
}
|
|
36
73
|
export interface Skeleton {
|
|
37
74
|
bones: Bone[];
|
|
@@ -65,6 +102,8 @@ export interface SkeletonRuntime {
|
|
|
65
102
|
localTranslations: Float32Array;
|
|
66
103
|
worldMatrices: Float32Array;
|
|
67
104
|
computedBones: boolean[];
|
|
105
|
+
ikChainInfo?: IKChainInfo[];
|
|
106
|
+
ikSolvers?: IKSolver[];
|
|
68
107
|
}
|
|
69
108
|
export interface MorphRuntime {
|
|
70
109
|
nameIndex: Record<string, number>;
|
|
@@ -87,13 +126,17 @@ export declare class Model {
|
|
|
87
126
|
private cachedIdentityMat1;
|
|
88
127
|
private cachedIdentityMat2;
|
|
89
128
|
private rotTweenState;
|
|
129
|
+
private transTweenState;
|
|
90
130
|
private morphTweenState;
|
|
91
131
|
constructor(vertexData: Float32Array<ArrayBuffer>, indexData: Uint32Array<ArrayBuffer>, textures: Texture[], materials: Material[], skeleton: Skeleton, skinning: Skinning, morphing: Morphing, rigidbodies?: Rigidbody[], joints?: Joint[]);
|
|
92
132
|
private initializeRuntimeSkeleton;
|
|
133
|
+
private initializeIKRuntime;
|
|
93
134
|
private initializeRotTweenBuffers;
|
|
135
|
+
private initializeTransTweenBuffers;
|
|
94
136
|
private initializeMorphTweenBuffers;
|
|
95
137
|
private initializeRuntimeMorph;
|
|
96
138
|
private updateRotationTweens;
|
|
139
|
+
private updateTranslationTweens;
|
|
97
140
|
private updateMorphWeightTweens;
|
|
98
141
|
getVertices(): Float32Array<ArrayBuffer>;
|
|
99
142
|
getTextures(): Texture[];
|
|
@@ -108,12 +151,14 @@ export declare class Model {
|
|
|
108
151
|
getMorphWeights(): Float32Array;
|
|
109
152
|
getBoneNames(): string[];
|
|
110
153
|
rotateBones(names: string[], quats: Quat[], durationMs?: number): void;
|
|
154
|
+
moveBones(names: string[], relativeTranslations: Vec3[], durationMs?: number): void;
|
|
111
155
|
getBoneWorldMatrices(): Float32Array;
|
|
112
156
|
getBoneInverseBindMatrices(): Float32Array;
|
|
113
157
|
getMorphNames(): string[];
|
|
114
158
|
setMorphWeight(name: string, weight: number, durationMs?: number): void;
|
|
115
159
|
private applyMorphs;
|
|
116
160
|
evaluatePose(): boolean;
|
|
161
|
+
private solveIKChains;
|
|
117
162
|
private computeWorldMatrices;
|
|
118
163
|
}
|
|
119
164
|
//# 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":"AAAA,OAAO,EAAQ,IAAI,EAAa,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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"}
|