reze-engine 0.13.0 → 0.13.1

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 CHANGED
@@ -27,7 +27,7 @@ npm install reze-engine
27
27
  ## Usage
28
28
 
29
29
  ```javascript
30
- import { Engine, Vec3 } from "reze-engine"
30
+ import { Engine, Vec3 } from "reze-engine";
31
31
 
32
32
  const engine = new Engine(canvas, {
33
33
  world: { color: new Vec3(0.4, 0.49, 0.65), strength: 1.0 },
@@ -36,17 +36,16 @@ const engine = new Engine(canvas, {
36
36
  strength: 2.0,
37
37
  direction: new Vec3(0, -0.5, 1),
38
38
  },
39
+ bloom: {
40
+ color: new Vec3(0.9, 0.1, 0.8),
41
+ intensity: 0.05,
42
+ threshold: 0.5,
43
+ }
39
44
  camera: { distance: 31.5, target: new Vec3(0, 11.5, 0) }, // MMD units (1 unit = 8 cm)
40
- })
41
- await engine.init()
45
+ });
46
+ await engine.init();
42
47
 
43
- engine.setBloomOptions({
44
- color: new Vec3(0.9, 0.1, 0.8),
45
- intensity: 0.05,
46
- threshold: 0.5,
47
- })
48
-
49
- const model = await engine.loadModel("hero", "/models/hero/hero.pmx")
48
+ const model = await engine.loadModel("hero", "/models/hero/hero.pmx");
50
49
 
51
50
  // Map PMX material names to NPR presets (unlisted names fall back to `default`).
52
51
  engine.setMaterialPresets("hero", {
@@ -58,15 +57,15 @@ engine.setMaterialPresets("hero", {
58
57
  cloth_rough: ["jacket", "pants"],
59
58
  stockings: ["stockings"],
60
59
  metal: ["metal01", "earring"],
61
- })
60
+ });
62
61
 
63
- await model.loadVmd("idle", "/animations/idle.vmd")
64
- model.show("idle")
65
- model.play()
62
+ await model.loadVmd("idle", "/animations/idle.vmd");
63
+ model.show("idle");
64
+ model.play();
66
65
 
67
- engine.setCameraFollow(model, "センター", new Vec3(0, 3.5, 0))
68
- engine.addGround({ width: 160, height: 160 })
69
- engine.runRenderLoop()
66
+ engine.setCameraFollow(model, "センター", new Vec3(0, 3.5, 0));
67
+ engine.addGround({ width: 160, height: 160 });
68
+ engine.runRenderLoop();
70
69
  ```
71
70
 
72
71
  ## API
@@ -115,26 +114,30 @@ Use a hidden `<input type="file" webkitdirectory multiple>` (or drag/drop) and p
115
114
  2. **`engine.loadModel(name, { files, pmxFile })`** — `pmxFile` selects which `.pmx` when the folder contains several.
116
115
 
117
116
  ```javascript
118
- import { Engine, parsePmxFolderInput, pmxFileAtRelativePath } from "reze-engine"
117
+ import {
118
+ Engine,
119
+ parsePmxFolderInput,
120
+ pmxFileAtRelativePath,
121
+ } from "reze-engine";
119
122
 
120
123
  // In <input onChange>:
121
- const picked = parsePmxFolderInput(e.target.files)
122
- e.target.value = ""
124
+ const picked = parsePmxFolderInput(e.target.files);
125
+ e.target.value = "";
123
126
 
124
127
  if (picked.status === "single") {
125
128
  const model = await engine.loadModel("myModel", {
126
129
  files: picked.files,
127
130
  pmxFile: picked.pmxFile,
128
- })
131
+ });
129
132
  }
130
133
 
131
134
  if (picked.status === "multiple") {
132
135
  // Let the user choose `chosenPath` from picked.pmxRelativePaths, then:
133
- const pmxFile = pmxFileAtRelativePath(picked.files, chosenPath)
136
+ const pmxFile = pmxFileAtRelativePath(picked.files, chosenPath);
134
137
  const model = await engine.loadModel("myModel", {
135
138
  files: picked.files,
136
139
  pmxFile,
137
- })
140
+ });
138
141
  }
139
142
  ```
140
143
 
@@ -173,12 +176,12 @@ model.getBoneWorldPosition(name)
173
176
  `model.exportVmd(name)` serialises a loaded clip back to the VMD binary format and returns an `ArrayBuffer`. Bone and morph names are Shift-JIS encoded for compatibility with standard MMD tools.
174
177
 
175
178
  ```javascript
176
- const buffer = model.exportVmd("idle")
177
- const blob = new Blob([buffer], { type: "application/octet-stream" })
178
- const link = document.createElement("a")
179
- link.href = URL.createObjectURL(blob)
180
- link.download = "idle.vmd"
181
- link.click()
179
+ const buffer = model.exportVmd("idle");
180
+ const blob = new Blob([buffer], { type: "application/octet-stream" });
181
+ const link = document.createElement("a");
182
+ link.href = URL.createObjectURL(blob);
183
+ link.download = "idle.vmd";
184
+ link.click();
182
185
  ```
183
186
 
184
187
  #### Playback
@@ -9,12 +9,11 @@ export declare class IKSolverSystem {
9
9
  private static solveChain;
10
10
  private static limitAngle;
11
11
  private static getDistance;
12
- private static getWorldTranslation;
13
- private static extractEulerAngles;
14
- private static limitEulerAngles;
15
- private static reconstructQuatFromEuler;
16
- private static getParentWorldRotationMatrix;
17
- private static transformNormal;
12
+ private static readonly EULER_AXES;
13
+ private static extractEulerAnglesInto;
14
+ private static limitEulerAnglesInto;
15
+ private static reconstructQuatFromEulerInto;
16
+ private static getParentWorldRotationMatrixInto;
18
17
  private static updateWorldMatrix;
19
18
  }
20
19
  //# sourceMappingURL=ik-solver.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ik-solver.d.ts","sourceRoot":"","sources":["../src/ik-solver.ts"],"names":[],"mappings":"AAEA,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,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAS;IACxC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAuB;IAExD,MAAM,CAAC,KAAK,CACV,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"}
1
+ {"version":3,"file":"ik-solver.d.ts","sourceRoot":"","sources":["../src/ik-solver.ts"],"names":[],"mappings":"AAEA,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;AAkF/E,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAS;IACxC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAuB;IAExD,MAAM,CAAC,KAAK,CACV,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;IA4HzB,OAAO,CAAC,MAAM,CAAC,UAAU;IAYzB,OAAO,CAAC,MAAM,CAAC,WAAW;IAW1B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAOjC;IAED,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAsCrC,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAMnC,OAAO,CAAC,MAAM,CAAC,4BAA4B;IAyB3C,OAAO,CAAC,MAAM,CAAC,gCAAgC;IAkB/C,OAAO,CAAC,MAAM,CAAC,iBAAiB;CA2CjC"}
package/dist/ik-solver.js CHANGED
@@ -63,6 +63,19 @@ class IKChain {
63
63
  }
64
64
  }
65
65
  }
66
+ // IK-local scratch pool. Safe because solve() runs synchronously and all scratch
67
+ // use completes before the updateWorldMatrix callback is invoked.
68
+ const _ikVec = [
69
+ new Vec3(0, 0, 0), new Vec3(0, 0, 0), new Vec3(0, 0, 0), new Vec3(0, 0, 0), new Vec3(0, 0, 0),
70
+ new Vec3(0, 0, 0), new Vec3(0, 0, 0), new Vec3(0, 0, 0), new Vec3(0, 0, 0),
71
+ ];
72
+ const _ikQuat = [
73
+ new Quat(0, 0, 0, 1), new Quat(0, 0, 0, 1), new Quat(0, 0, 0, 1),
74
+ new Quat(0, 0, 0, 1), new Quat(0, 0, 0, 1), new Quat(0, 0, 0, 1),
75
+ ];
76
+ const _ikMat = [
77
+ new Float32Array(16), new Float32Array(16), new Float32Array(16), new Float32Array(16),
78
+ ];
66
79
  export class IKSolverSystem {
67
80
  static solve(ikSolvers, bones, localRotations, localTranslations, worldMatrices, ikChainInfo, updateWorldMatrix) {
68
81
  for (const solver of ikSolvers) {
@@ -116,77 +129,100 @@ export class IKSolverSystem {
116
129
  if (this.getDistance(ikBoneIndex, targetBoneIndex, worldMatrices) < this.EPSILON)
117
130
  break;
118
131
  }
119
- // Apply IK rotations to local rotations
132
+ // Apply IK rotations to local rotations (mutate localRot in place)
120
133
  for (const link of solver.links) {
121
134
  const chainInfo = ikChainInfo[link.boneIndex];
122
135
  if (chainInfo?.ikRotation) {
123
136
  const localRot = localRotations[link.boneIndex];
124
- const finalRot = chainInfo.ikRotation.multiply(localRot).normalize();
125
- localRot.set(finalRot);
137
+ Quat.multiplyInto(chainInfo.ikRotation, localRot, localRot);
138
+ localRot.normalize();
126
139
  }
127
140
  }
128
141
  }
129
142
  static solveChain(chain, chainIndex, solver, ikBoneIndex, targetBoneIndex, bones, localRotations, localTranslations, worldMatrices, ikChainInfo, useAxis, updateWorldMatrix) {
130
143
  const chainBoneIndex = chain.boneIndex;
131
- const chainPosition = this.getWorldTranslation(chainBoneIndex, worldMatrices);
132
- const ikPosition = this.getWorldTranslation(ikBoneIndex, worldMatrices);
133
- const targetPosition = this.getWorldTranslation(targetBoneIndex, worldMatrices);
134
- const chainTargetVector = chainPosition.subtract(targetPosition).normalize();
135
- const chainIkVector = chainPosition.subtract(ikPosition).normalize();
136
- const chainRotationAxis = chainTargetVector.cross(chainIkVector);
137
- if (chainRotationAxis.length() < this.EPSILON)
144
+ // scratch layout:
145
+ // _ikVec[0]=chainPos, [1]=ikPos, [2]=targetPos, [3]=chainTargetVec, [4]=chainIkVec,
146
+ // [5]=rotAxis, [6]=finalAxis, [7]=eulerTmp, [8]=limitedEuler
147
+ // _ikMat[0]=parentRot, [1]=invParentRot, [2]=quatToMatTmp
148
+ // _ikQuat[0]=ikRotation, [1]=combinedRot, [2]=localRotConj, [3..5]=axisAngleTmp
149
+ const chainPos = Vec3.setFromMat4Translation(worldMatrices[chainBoneIndex].values, _ikVec[0]);
150
+ const ikPos = Vec3.setFromMat4Translation(worldMatrices[ikBoneIndex].values, _ikVec[1]);
151
+ const targetPos = Vec3.setFromMat4Translation(worldMatrices[targetBoneIndex].values, _ikVec[2]);
152
+ const chainTargetVec = Vec3.subtractInto(chainPos, targetPos, _ikVec[3]);
153
+ chainTargetVec.normalize();
154
+ const chainIkVec = Vec3.subtractInto(chainPos, ikPos, _ikVec[4]);
155
+ chainIkVec.normalize();
156
+ const rotAxis = Vec3.crossInto(chainTargetVec, chainIkVec, _ikVec[5]);
157
+ if (rotAxis.length() < this.EPSILON)
138
158
  return;
139
- // Get parent's world rotation matrix (translation removed)
140
- const parentWorldRotMatrix = this.getParentWorldRotationMatrix(chainBoneIndex, bones, worldMatrices);
141
- let finalRotationAxis;
159
+ // Parent world rotation matrix (translation removed) into _ikMat[0]
160
+ this.getParentWorldRotationMatrixInto(chainBoneIndex, bones, worldMatrices, _ikMat[0]);
161
+ let finalAxis;
142
162
  if (chain.minimumAngle !== null && useAxis) {
143
163
  switch (chain.solveAxis) {
144
164
  case InternalSolveAxis.None: {
145
- const invParentRot = parentWorldRotMatrix.inverse();
146
- finalRotationAxis = this.transformNormal(chainRotationAxis, invParentRot).normalize();
165
+ if (!Mat4.inverseInto(_ikMat[0], _ikMat[1])) {
166
+ finalAxis = rotAxis;
167
+ }
168
+ else {
169
+ finalAxis = Vec3.transformMat4RotationInto(rotAxis, _ikMat[1], _ikVec[6]);
170
+ finalAxis.normalize();
171
+ }
147
172
  break;
148
173
  }
149
174
  case InternalSolveAxis.X:
150
175
  case InternalSolveAxis.Y:
151
176
  case InternalSolveAxis.Z: {
152
- const m = parentWorldRotMatrix.values;
177
+ const m = _ikMat[0];
153
178
  const axisOffset = (chain.solveAxis - InternalSolveAxis.X) * 4;
154
- const axis = new Vec3(m[axisOffset], m[axisOffset + 1], m[axisOffset + 2]);
155
- const dot = chainRotationAxis.dot(axis);
156
- const sign = dot >= 0 ? 1 : -1;
157
- finalRotationAxis =
179
+ const ax = m[axisOffset], ay = m[axisOffset + 1], az = m[axisOffset + 2];
180
+ const dotA = rotAxis.x * ax + rotAxis.y * ay + rotAxis.z * az;
181
+ const sign = dotA >= 0 ? 1 : -1;
182
+ finalAxis =
158
183
  chain.solveAxis === InternalSolveAxis.X
159
- ? new Vec3(sign, 0, 0)
184
+ ? _ikVec[6].setXYZ(sign, 0, 0)
160
185
  : chain.solveAxis === InternalSolveAxis.Y
161
- ? new Vec3(0, sign, 0)
162
- : new Vec3(0, 0, sign);
186
+ ? _ikVec[6].setXYZ(0, sign, 0)
187
+ : _ikVec[6].setXYZ(0, 0, sign);
163
188
  break;
164
189
  }
165
190
  default:
166
- finalRotationAxis = chainRotationAxis;
191
+ finalAxis = rotAxis;
167
192
  }
168
193
  }
169
194
  else {
170
- const invParentRot = parentWorldRotMatrix.inverse();
171
- finalRotationAxis = this.transformNormal(chainRotationAxis, invParentRot).normalize();
195
+ if (!Mat4.inverseInto(_ikMat[0], _ikMat[1])) {
196
+ finalAxis = rotAxis;
197
+ }
198
+ else {
199
+ finalAxis = Vec3.transformMat4RotationInto(rotAxis, _ikMat[1], _ikVec[6]);
200
+ finalAxis.normalize();
201
+ }
172
202
  }
173
- let dot = chainTargetVector.dot(chainIkVector);
174
- dot = Math.max(-1.0, Math.min(1.0, dot));
175
- const angle = Math.min(solver.limitAngle * (chainIndex + 1), Math.acos(dot));
176
- const ikRotation = Quat.fromAxisAngle(finalRotationAxis, angle);
203
+ let dotTI = chainTargetVec.dot(chainIkVec);
204
+ dotTI = Math.max(-1.0, Math.min(1.0, dotTI));
205
+ const angle = Math.min(solver.limitAngle * (chainIndex + 1), Math.acos(dotTI));
206
+ const ikRotation = Quat.fromAxisAngleInto(finalAxis.x, finalAxis.y, finalAxis.z, angle, _ikQuat[0]);
177
207
  const chainInfo = ikChainInfo[chainBoneIndex];
178
208
  if (chainInfo) {
179
- chainInfo.ikRotation = ikRotation.multiply(chainInfo.ikRotation);
180
- // Apply angle constraints if present
209
+ // chainInfo.ikRotation = ikRotation * chainInfo.ikRotation (in place)
210
+ Quat.multiplyInto(ikRotation, chainInfo.ikRotation, chainInfo.ikRotation);
181
211
  if (chain.minimumAngle && chain.maximumAngle) {
182
212
  const localRot = localRotations[chainBoneIndex];
183
213
  chainInfo.localRotation = localRot.clone();
184
- const combinedRot = chainInfo.ikRotation.multiply(localRot);
185
- const euler = this.extractEulerAngles(combinedRot, chain.rotationOrder);
186
- const limited = this.limitEulerAngles(euler, chain.minimumAngle, chain.maximumAngle, useAxis);
187
- chainInfo.ikRotation = this.reconstructQuatFromEuler(limited, chain.rotationOrder);
188
- // Clone localRot to avoid mutating, then conjugate and normalize
189
- chainInfo.ikRotation = chainInfo.ikRotation.multiply(localRot.clone().conjugate().normalize());
214
+ // combinedRot = chainInfo.ikRotation * localRot
215
+ Quat.multiplyInto(chainInfo.ikRotation, localRot, _ikQuat[1]);
216
+ // extract euler into _ikVec[7]
217
+ this.extractEulerAnglesInto(_ikQuat[1], chain.rotationOrder, _ikVec[7]);
218
+ // limit into _ikVec[8]
219
+ this.limitEulerAnglesInto(_ikVec[7], chain.minimumAngle, chain.maximumAngle, useAxis, _ikVec[8]);
220
+ // reconstruct quat into chainInfo.ikRotation (uses _ikQuat[3..5] as tmp)
221
+ this.reconstructQuatFromEulerInto(_ikVec[8], chain.rotationOrder, chainInfo.ikRotation);
222
+ // localRot conjugate into _ikQuat[2] (localRot is unit, so conjugate == inverse)
223
+ _ikQuat[2].setXYZW(-localRot.x, -localRot.y, -localRot.z, localRot.w);
224
+ // chainInfo.ikRotation *= localRotConj
225
+ Quat.multiplyInto(chainInfo.ikRotation, _ikQuat[2], chainInfo.ikRotation);
190
226
  }
191
227
  }
192
228
  // Update world matrices for affected bones (using callback - handles append correctly)
@@ -220,17 +256,16 @@ export class IKSolverSystem {
220
256
  }
221
257
  }
222
258
  static getDistance(boneIndex1, boneIndex2, worldMatrices) {
223
- const pos1 = this.getWorldTranslation(boneIndex1, worldMatrices);
224
- const pos2 = this.getWorldTranslation(boneIndex2, worldMatrices);
225
- return pos1.subtract(pos2).length();
259
+ const m1 = worldMatrices[boneIndex1].values;
260
+ const m2 = worldMatrices[boneIndex2].values;
261
+ const dx = m1[12] - m2[12];
262
+ const dy = m1[13] - m2[13];
263
+ const dz = m1[14] - m2[14];
264
+ return Math.sqrt(dx * dx + dy * dy + dz * dz);
226
265
  }
227
- static getWorldTranslation(boneIndex, worldMatrices) {
228
- const mat = worldMatrices[boneIndex];
229
- return new Vec3(mat.values[12], mat.values[13], mat.values[14]);
230
- }
231
- static extractEulerAngles(quat, order) {
232
- const rotMatrix = Mat4.fromQuat(quat.x, quat.y, quat.z, quat.w);
233
- const m = rotMatrix.values;
266
+ static extractEulerAnglesInto(quat, order, out) {
267
+ Mat4.fromQuatInto(quat.x, quat.y, quat.z, quat.w, _ikMat[2], 0);
268
+ const m = _ikMat[2];
234
269
  switch (order) {
235
270
  case InternalEulerRotationOrder.YXZ: {
236
271
  let rX = Math.asin(-m[9]);
@@ -239,9 +274,10 @@ export class IKSolverSystem {
239
274
  let cosX = Math.cos(rX);
240
275
  if (cosX !== 0)
241
276
  cosX = 1 / cosX;
242
- const rY = Math.atan2(m[8] * cosX, m[10] * cosX);
243
- const rZ = Math.atan2(m[1] * cosX, m[5] * cosX);
244
- return new Vec3(rX, rY, rZ);
277
+ out.x = rX;
278
+ out.y = Math.atan2(m[8] * cosX, m[10] * cosX);
279
+ out.z = Math.atan2(m[1] * cosX, m[5] * cosX);
280
+ return;
245
281
  }
246
282
  case InternalEulerRotationOrder.ZYX: {
247
283
  let rY = Math.asin(-m[2]);
@@ -250,9 +286,10 @@ export class IKSolverSystem {
250
286
  let cosY = Math.cos(rY);
251
287
  if (cosY !== 0)
252
288
  cosY = 1 / cosY;
253
- const rX = Math.atan2(m[6] * cosY, m[10] * cosY);
254
- const rZ = Math.atan2(m[1] * cosY, m[0] * cosY);
255
- return new Vec3(rX, rY, rZ);
289
+ out.x = Math.atan2(m[6] * cosY, m[10] * cosY);
290
+ out.y = rY;
291
+ out.z = Math.atan2(m[1] * cosY, m[0] * cosY);
292
+ return;
256
293
  }
257
294
  case InternalEulerRotationOrder.XZY: {
258
295
  let rZ = Math.asin(-m[4]);
@@ -261,77 +298,105 @@ export class IKSolverSystem {
261
298
  let cosZ = Math.cos(rZ);
262
299
  if (cosZ !== 0)
263
300
  cosZ = 1 / cosZ;
264
- const rX = Math.atan2(m[6] * cosZ, m[5] * cosZ);
265
- const rY = Math.atan2(m[8] * cosZ, m[0] * cosZ);
266
- return new Vec3(rX, rY, rZ);
301
+ out.x = Math.atan2(m[6] * cosZ, m[5] * cosZ);
302
+ out.y = Math.atan2(m[8] * cosZ, m[0] * cosZ);
303
+ out.z = rZ;
304
+ return;
267
305
  }
268
306
  }
269
307
  }
270
- static limitEulerAngles(euler, min, max, useAxis) {
271
- return new Vec3(this.limitAngle(euler.x, min.x, max.x, useAxis), this.limitAngle(euler.y, min.y, max.y, useAxis), this.limitAngle(euler.z, min.z, max.z, useAxis));
308
+ static limitEulerAnglesInto(euler, min, max, useAxis, out) {
309
+ out.x = this.limitAngle(euler.x, min.x, max.x, useAxis);
310
+ out.y = this.limitAngle(euler.y, min.y, max.y, useAxis);
311
+ out.z = this.limitAngle(euler.z, min.z, max.z, useAxis);
272
312
  }
273
- static reconstructQuatFromEuler(euler, order) {
274
- const axes = [
275
- [new Vec3(1, 0, 0), new Vec3(0, 1, 0), new Vec3(0, 0, 1)],
276
- [new Vec3(0, 0, 1), new Vec3(0, 1, 0), new Vec3(1, 0, 0)],
277
- [new Vec3(0, 1, 0), new Vec3(1, 0, 0), new Vec3(0, 0, 1)],
278
- ];
279
- const [axis1, axis2, axis3] = axes[order];
280
- const [angle1, angle2, angle3] = order === InternalEulerRotationOrder.YXZ
281
- ? [euler.y, euler.x, euler.z]
282
- : order === InternalEulerRotationOrder.ZYX
283
- ? [euler.z, euler.y, euler.x]
284
- : [euler.x, euler.z, euler.y];
285
- let result = Quat.fromAxisAngle(axis1, angle1);
286
- result = result.multiply(Quat.fromAxisAngle(axis2, angle2));
287
- result = result.multiply(Quat.fromAxisAngle(axis3, angle3));
288
- return result;
313
+ static reconstructQuatFromEulerInto(euler, order, out) {
314
+ const axes = this.EULER_AXES[order];
315
+ const a1 = axes[0], a2 = axes[1], a3 = axes[2];
316
+ const ang1 = order === InternalEulerRotationOrder.YXZ ? euler.y
317
+ : order === InternalEulerRotationOrder.ZYX ? euler.z
318
+ : euler.x;
319
+ const ang2 = order === InternalEulerRotationOrder.YXZ ? euler.x
320
+ : order === InternalEulerRotationOrder.ZYX ? euler.y
321
+ : euler.z;
322
+ const ang3 = order === InternalEulerRotationOrder.YXZ ? euler.z
323
+ : order === InternalEulerRotationOrder.ZYX ? euler.x
324
+ : euler.y;
325
+ // result = axisAngle(a1, ang1); then *= axisAngle(a2, ang2); then *= axisAngle(a3, ang3)
326
+ Quat.fromAxisAngleInto(a1[0], a1[1], a1[2], ang1, out);
327
+ Quat.fromAxisAngleInto(a2[0], a2[1], a2[2], ang2, _ikQuat[3]);
328
+ Quat.multiplyInto(out, _ikQuat[3], out);
329
+ Quat.fromAxisAngleInto(a3[0], a3[1], a3[2], ang3, _ikQuat[3]);
330
+ Quat.multiplyInto(out, _ikQuat[3], out);
289
331
  }
290
- static getParentWorldRotationMatrix(boneIndex, bones, worldMatrices) {
332
+ // Write parent's world rotation (translation stripped) into out Float32Array.
333
+ static getParentWorldRotationMatrixInto(boneIndex, bones, worldMatrices, out) {
291
334
  const bone = bones[boneIndex];
292
335
  if (bone.parentIndex >= 0) {
293
- const parentMat = worldMatrices[bone.parentIndex];
294
- // Remove translation
295
- const rotMat = Mat4.identity();
296
- const m = parentMat.values;
297
- 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]);
298
- return rotMat;
336
+ Mat4.copyRotationInto(worldMatrices[bone.parentIndex].values, out);
299
337
  }
300
338
  else {
301
- return Mat4.identity();
339
+ // Identity
340
+ out[0] = 1;
341
+ out[1] = 0;
342
+ out[2] = 0;
343
+ out[3] = 0;
344
+ out[4] = 0;
345
+ out[5] = 1;
346
+ out[6] = 0;
347
+ out[7] = 0;
348
+ out[8] = 0;
349
+ out[9] = 0;
350
+ out[10] = 1;
351
+ out[11] = 0;
352
+ out[12] = 0;
353
+ out[13] = 0;
354
+ out[14] = 0;
355
+ out[15] = 1;
302
356
  }
303
357
  }
304
- static transformNormal(normal, matrix) {
305
- const m = matrix.values;
306
- 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);
307
- }
308
358
  static updateWorldMatrix(boneIndex, bones, localRotations, localTranslations, worldMatrices, ikChainInfo) {
309
359
  const bone = bones[boneIndex];
310
360
  const localRot = localRotations[boneIndex];
311
361
  const localTrans = localTranslations[boneIndex];
312
- // Apply IK rotation if available
313
- let finalRot = localRot;
362
+ let fx = localRot.x, fy = localRot.y, fz = localRot.z, fw = localRot.w;
314
363
  if (ikChainInfo) {
315
364
  const chainInfo = ikChainInfo[boneIndex];
316
365
  if (chainInfo && chainInfo.ikRotation) {
317
- finalRot = chainInfo.ikRotation.multiply(localRot).normalize();
366
+ const ik = chainInfo.ikRotation;
367
+ const nx = ik.w * fx + ik.x * fw + ik.y * fz - ik.z * fy;
368
+ const ny = ik.w * fy - ik.x * fz + ik.y * fw + ik.z * fx;
369
+ const nz = ik.w * fz + ik.x * fy - ik.y * fx + ik.z * fw;
370
+ const nw = ik.w * fw - ik.x * fx - ik.y * fy - ik.z * fz;
371
+ const len = Math.sqrt(nx * nx + ny * ny + nz * nz + nw * nw);
372
+ const inv = len > 0 ? 1 / len : 0;
373
+ fx = nx * inv;
374
+ fy = ny * inv;
375
+ fz = nz * inv;
376
+ fw = nw * inv;
318
377
  }
319
378
  }
320
- const rotateM = Mat4.fromQuat(finalRot.x, finalRot.y, finalRot.z, finalRot.w);
321
- const localM = Mat4.identity()
322
- .translateInPlace(bone.bindTranslation[0], bone.bindTranslation[1], bone.bindTranslation[2])
323
- .multiply(rotateM)
324
- .translateInPlace(localTrans.x, localTrans.y, localTrans.z);
379
+ const localMVals = _ikMat[3];
380
+ Mat4.localTransformInto(bone.bindTranslation[0], bone.bindTranslation[1], bone.bindTranslation[2], fx, fy, fz, fw, localTrans.x, localTrans.y, localTrans.z, localMVals);
325
381
  const worldMat = worldMatrices[boneIndex];
326
382
  if (bone.parentIndex >= 0) {
327
383
  const parentMat = worldMatrices[bone.parentIndex];
328
- const result = parentMat.multiply(localM);
329
- worldMat.values.set(result.values);
384
+ Mat4.multiplyArrays(parentMat.values, 0, localMVals, 0, worldMat.values, 0);
330
385
  }
331
386
  else {
332
- worldMat.values.set(localM.values);
387
+ worldMat.values.set(localMVals);
333
388
  }
334
389
  }
335
390
  }
336
391
  IKSolverSystem.EPSILON = 1.0e-8;
337
392
  IKSolverSystem.THRESHOLD = (88 * Math.PI) / 180;
393
+ // Euler axis triples for each rotation order (indexed by order enum).
394
+ // Reused to avoid allocations in reconstructQuatFromEulerInto.
395
+ IKSolverSystem.EULER_AXES = [
396
+ // YXZ: Y, X, Z
397
+ [[0, 1, 0], [1, 0, 0], [0, 0, 1]],
398
+ // ZYX: Z, Y, X
399
+ [[0, 0, 1], [0, 1, 0], [1, 0, 0]],
400
+ // XZY: X, Z, Y
401
+ [[1, 0, 0], [0, 0, 1], [0, 1, 0]],
402
+ ];
package/dist/math.d.ts CHANGED
@@ -13,6 +13,12 @@ export declare class Vec3 {
13
13
  dot(other: Vec3): number;
14
14
  scale(scalar: number): Vec3;
15
15
  set(other: Vec3): Vec3;
16
+ setXYZ(x: number, y: number, z: number): Vec3;
17
+ static subtractInto(a: Vec3, b: Vec3, out: Vec3): Vec3;
18
+ static crossInto(a: Vec3, b: Vec3, out: Vec3): Vec3;
19
+ static setFromMat4Translation(m: Float32Array, out: Vec3): Vec3;
20
+ static transformMat4RotationInto(normal: Vec3, m: Float32Array, out: Vec3): Vec3;
21
+ normalizeInPlace(): Vec3;
16
22
  }
17
23
  export declare class Quat {
18
24
  x: number;
@@ -31,6 +37,11 @@ export declare class Quat {
31
37
  toArray(): [number, number, number, number];
32
38
  set(other: Quat): Quat;
33
39
  static slerp(a: Quat, b: Quat, t: number): Quat;
40
+ static multiplyInto(a: Quat, b: Quat, out: Quat): Quat;
41
+ static fromAxisAngleInto(ax: number, ay: number, az: number, angle: number, out: Quat): Quat;
42
+ static slerpInto(a: Quat, b: Quat, t: number, out: Quat): Quat;
43
+ setXYZW(x: number, y: number, z: number, w: number): Quat;
44
+ setIdentity(): Quat;
34
45
  static fromEuler(rotX: number, rotY: number, rotZ: number): Quat;
35
46
  }
36
47
  export declare class Mat4 {
@@ -43,13 +54,22 @@ export declare class Mat4 {
43
54
  multiply(other: Mat4): Mat4;
44
55
  static multiplyArrays(a: Float32Array, aOffset: number, b: Float32Array, bOffset: number, out: Float32Array, outOffset: number): void;
45
56
  clone(): Mat4;
57
+ static fromQuatInto(x: number, y: number, z: number, w: number, out: Float32Array, offset?: number): void;
58
+ static localTransformInto(bx: number, by: number, bz: number, qx: number, qy: number, qz: number, qw: number, lx: number, ly: number, lz: number, out: Float32Array): void;
59
+ static fromPositionRotationInto(px: number, py: number, pz: number, qx: number, qy: number, qz: number, qw: number, out: Float32Array): void;
60
+ static inverseInto(m: Float32Array, out: Float32Array): boolean;
61
+ static copyRotationInto(src: Float32Array, dst: Float32Array): void;
46
62
  static fromQuat(x: number, y: number, z: number, w: number): Mat4;
47
63
  static fromPositionRotation(position: Vec3, rotation: Quat): Mat4;
48
64
  getPosition(): Vec3;
49
65
  toQuat(): Quat;
66
+ static toQuatFromArrayInto(m: Float32Array, offset: number, out: Quat): Quat;
50
67
  static toQuatFromArray(m: Float32Array, offset: number): Quat;
51
68
  setIdentity(): this;
52
69
  translateInPlace(tx: number, ty: number, tz: number): this;
53
70
  inverse(): Mat4;
54
71
  }
72
+ export declare const scratchMat4Values: Float32Array[];
73
+ export declare const scratchVec3: Vec3[];
74
+ export declare const scratchQuat: Quat[];
55
75
  //# sourceMappingURL=math.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../src/math.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../src/math.ts"],"names":[],"mappings":"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"}