@driftengine/assets 4.6.0 → 4.7.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.
Files changed (49) hide show
  1. package/README.md +1 -1
  2. package/dist/blend.d.ts +25 -0
  3. package/dist/blend.js +43 -0
  4. package/dist/blendAnimation.d.ts +45 -0
  5. package/dist/blendAnimation.js +294 -0
  6. package/dist/blendData.d.ts +114 -0
  7. package/dist/blendData.js +366 -0
  8. package/dist/blendFile.d.ts +69 -0
  9. package/dist/blendFile.js +182 -0
  10. package/dist/blendGeometry.d.ts +45 -0
  11. package/dist/blendGeometry.js +210 -0
  12. package/dist/blendGltf.d.ts +65 -0
  13. package/dist/blendGltf.js +545 -0
  14. package/dist/blendMaterial.d.ts +68 -0
  15. package/dist/blendMaterial.js +545 -0
  16. package/dist/blendMatrix.d.ts +28 -0
  17. package/dist/blendMatrix.js +245 -0
  18. package/dist/blendMesh.d.ts +70 -0
  19. package/dist/blendMesh.js +409 -0
  20. package/dist/blendModifiers.d.ts +25 -0
  21. package/dist/blendModifiers.js +83 -0
  22. package/dist/blendNormals.d.ts +44 -0
  23. package/dist/blendNormals.js +458 -0
  24. package/dist/blendPacked.d.ts +35 -0
  25. package/dist/blendPacked.js +82 -0
  26. package/dist/blendScene.d.ts +50 -0
  27. package/dist/blendScene.js +280 -0
  28. package/dist/gltf.js +8 -2
  29. package/dist/index.d.ts +21 -0
  30. package/dist/index.js +17 -0
  31. package/dist/readModel.d.ts +11 -0
  32. package/dist/readModel.js +29 -0
  33. package/package.json +4 -4
  34. package/src/blend.ts +57 -0
  35. package/src/blendAnimation.ts +328 -0
  36. package/src/blendData.ts +375 -0
  37. package/src/blendFile.ts +233 -0
  38. package/src/blendGeometry.ts +263 -0
  39. package/src/blendGltf.ts +621 -0
  40. package/src/blendMaterial.ts +676 -0
  41. package/src/blendMatrix.ts +257 -0
  42. package/src/blendMesh.ts +496 -0
  43. package/src/blendModifiers.ts +96 -0
  44. package/src/blendNormals.ts +481 -0
  45. package/src/blendPacked.ts +93 -0
  46. package/src/blendScene.ts +307 -0
  47. package/src/gltf.ts +14 -2
  48. package/src/index.ts +41 -0
  49. package/src/readModel.ts +44 -0
@@ -0,0 +1,257 @@
1
+ /**
2
+ * The little matrix arithmetic a `.blend` scene needs, in the conventions Blender stores it in.
3
+ *
4
+ * Column-major 4x4 as plain number arrays, which is both how Blender lays out `float[4][4]` in a
5
+ * file and how glTF writes `matrix`, so a matrix read from one is written to the other without a
6
+ * transpose. Doubles throughout: these run once per object at import, and a parent chain composes
7
+ * enough of them that single precision drifts visibly on a deep rig.
8
+ *
9
+ * **Every rotation here is Blender's definition, not a generic one**, because a rotation mode is a
10
+ * claim about order: Blender's `XYZ` turns about X first, so its matrix is `Rz · Ry · Rx`. The
11
+ * fixtures under `scripts/fixtures/blend` hold an object in each of the eight modes and Blender's
12
+ * own export of where they ended up.
13
+ */
14
+
15
+ export type Mat4 = number[];
16
+ export type Mat3 = number[];
17
+
18
+ export const identity = (): Mat4 => [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
19
+
20
+ export function multiply(a: Mat4, b: Mat4): Mat4 {
21
+ const out = new Array<number>(16);
22
+ for (let c = 0; c < 4; c++) {
23
+ for (let r = 0; r < 4; r++) {
24
+ let sum = 0;
25
+ for (let k = 0; k < 4; k++) sum += (a[k * 4 + r] as number) * (b[c * 4 + k] as number);
26
+ out[c * 4 + r] = sum;
27
+ }
28
+ }
29
+ return out;
30
+ }
31
+
32
+ export function multiply3(a: Mat3, b: Mat3): Mat3 {
33
+ const out = new Array<number>(9);
34
+ for (let c = 0; c < 3; c++) {
35
+ for (let r = 0; r < 3; r++) {
36
+ let sum = 0;
37
+ for (let k = 0; k < 3; k++) sum += (a[k * 3 + r] as number) * (b[c * 3 + k] as number);
38
+ out[c * 3 + r] = sum;
39
+ }
40
+ }
41
+ return out;
42
+ }
43
+
44
+ export function invert(m: Mat4): Mat4 {
45
+ const a = m;
46
+ const inv = new Array<number>(16);
47
+ const g = (i: number): number => a[i] as number;
48
+ inv[0] =
49
+ g(5) * g(10) * g(15) -
50
+ g(5) * g(11) * g(14) -
51
+ g(9) * g(6) * g(15) +
52
+ g(9) * g(7) * g(14) +
53
+ g(13) * g(6) * g(11) -
54
+ g(13) * g(7) * g(10);
55
+ inv[4] =
56
+ -g(4) * g(10) * g(15) +
57
+ g(4) * g(11) * g(14) +
58
+ g(8) * g(6) * g(15) -
59
+ g(8) * g(7) * g(14) -
60
+ g(12) * g(6) * g(11) +
61
+ g(12) * g(7) * g(10);
62
+ inv[8] =
63
+ g(4) * g(9) * g(15) -
64
+ g(4) * g(11) * g(13) -
65
+ g(8) * g(5) * g(15) +
66
+ g(8) * g(7) * g(13) +
67
+ g(12) * g(5) * g(11) -
68
+ g(12) * g(7) * g(9);
69
+ inv[12] =
70
+ -g(4) * g(9) * g(14) +
71
+ g(4) * g(10) * g(13) +
72
+ g(8) * g(5) * g(14) -
73
+ g(8) * g(6) * g(13) -
74
+ g(12) * g(5) * g(10) +
75
+ g(12) * g(6) * g(9);
76
+ inv[1] =
77
+ -g(1) * g(10) * g(15) +
78
+ g(1) * g(11) * g(14) +
79
+ g(9) * g(2) * g(15) -
80
+ g(9) * g(3) * g(14) -
81
+ g(13) * g(2) * g(11) +
82
+ g(13) * g(3) * g(10);
83
+ inv[5] =
84
+ g(0) * g(10) * g(15) -
85
+ g(0) * g(11) * g(14) -
86
+ g(8) * g(2) * g(15) +
87
+ g(8) * g(3) * g(14) +
88
+ g(12) * g(2) * g(11) -
89
+ g(12) * g(3) * g(10);
90
+ inv[9] =
91
+ -g(0) * g(9) * g(15) +
92
+ g(0) * g(11) * g(13) +
93
+ g(8) * g(1) * g(15) -
94
+ g(8) * g(3) * g(13) -
95
+ g(12) * g(1) * g(11) +
96
+ g(12) * g(3) * g(9);
97
+ inv[13] =
98
+ g(0) * g(9) * g(14) -
99
+ g(0) * g(10) * g(13) -
100
+ g(8) * g(1) * g(14) +
101
+ g(8) * g(2) * g(13) +
102
+ g(12) * g(1) * g(10) -
103
+ g(12) * g(2) * g(9);
104
+ inv[2] =
105
+ g(1) * g(6) * g(15) -
106
+ g(1) * g(7) * g(14) -
107
+ g(5) * g(2) * g(15) +
108
+ g(5) * g(3) * g(14) +
109
+ g(13) * g(2) * g(7) -
110
+ g(13) * g(3) * g(6);
111
+ inv[6] =
112
+ -g(0) * g(6) * g(15) +
113
+ g(0) * g(7) * g(14) +
114
+ g(4) * g(2) * g(15) -
115
+ g(4) * g(3) * g(14) -
116
+ g(12) * g(2) * g(7) +
117
+ g(12) * g(3) * g(6);
118
+ inv[10] =
119
+ g(0) * g(5) * g(15) -
120
+ g(0) * g(7) * g(13) -
121
+ g(4) * g(1) * g(15) +
122
+ g(4) * g(3) * g(13) +
123
+ g(12) * g(1) * g(7) -
124
+ g(12) * g(3) * g(5);
125
+ inv[14] =
126
+ -g(0) * g(5) * g(14) +
127
+ g(0) * g(6) * g(13) +
128
+ g(4) * g(1) * g(14) -
129
+ g(4) * g(2) * g(13) -
130
+ g(12) * g(1) * g(6) +
131
+ g(12) * g(2) * g(5);
132
+ inv[3] =
133
+ -g(1) * g(6) * g(11) +
134
+ g(1) * g(7) * g(10) +
135
+ g(5) * g(2) * g(11) -
136
+ g(5) * g(3) * g(10) -
137
+ g(9) * g(2) * g(7) +
138
+ g(9) * g(3) * g(6);
139
+ inv[7] =
140
+ g(0) * g(6) * g(11) -
141
+ g(0) * g(7) * g(10) -
142
+ g(4) * g(2) * g(11) +
143
+ g(4) * g(3) * g(10) +
144
+ g(8) * g(2) * g(7) -
145
+ g(8) * g(3) * g(6);
146
+ inv[11] =
147
+ -g(0) * g(5) * g(11) +
148
+ g(0) * g(7) * g(9) +
149
+ g(4) * g(1) * g(11) -
150
+ g(4) * g(3) * g(9) -
151
+ g(8) * g(1) * g(7) +
152
+ g(8) * g(3) * g(5);
153
+ inv[15] =
154
+ g(0) * g(5) * g(10) -
155
+ g(0) * g(6) * g(9) -
156
+ g(4) * g(1) * g(10) +
157
+ g(4) * g(2) * g(9) +
158
+ g(8) * g(1) * g(6) -
159
+ g(8) * g(2) * g(5);
160
+ const det =
161
+ g(0) * (inv[0] as number) +
162
+ g(1) * (inv[4] as number) +
163
+ g(2) * (inv[8] as number) +
164
+ g(3) * (inv[12] as number);
165
+ /* Blender's `invert_m4` leaves a singular matrix as it found it, and so does this. */
166
+ if (Math.abs(det) < 1e-30) return [...m];
167
+ return inv.map((v) => v / det);
168
+ }
169
+
170
+ export function translation(x: number, y: number, z: number): Mat4 {
171
+ return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1];
172
+ }
173
+
174
+ /** Rotation and scale in a 3x3, translation beside it: `T · R · S`. */
175
+ export function compose(
176
+ location: readonly number[],
177
+ rotation: Mat3,
178
+ scale: readonly number[],
179
+ ): Mat4 {
180
+ const out = identity();
181
+ for (let c = 0; c < 3; c++) {
182
+ const s = scale[c] as number;
183
+ for (let r = 0; r < 3; r++) out[c * 4 + r] = (rotation[c * 3 + r] as number) * s;
184
+ }
185
+ out[12] = location[0] as number;
186
+ out[13] = location[1] as number;
187
+ out[14] = location[2] as number;
188
+ return out;
189
+ }
190
+
191
+ function axis(index: 0 | 1 | 2, angle: number): Mat3 {
192
+ const c = Math.cos(angle);
193
+ const s = Math.sin(angle);
194
+ if (index === 0) return [1, 0, 0, 0, c, s, 0, -s, c];
195
+ if (index === 1) return [c, 0, -s, 0, 1, 0, s, 0, c];
196
+ return [c, s, 0, -s, c, 0, 0, 0, 1];
197
+ }
198
+
199
+ /**
200
+ * Blender's Euler rotation modes, by the value `Object.rotmode` stores: 1 `XYZ` to 6 `ZYX`.
201
+ * Each names the axes in the order they are turned about.
202
+ */
203
+ const ORDERS: Record<number, readonly [0 | 1 | 2, 0 | 1 | 2, 0 | 1 | 2]> = {
204
+ 1: [0, 1, 2],
205
+ 2: [0, 2, 1],
206
+ 3: [1, 0, 2],
207
+ 4: [1, 2, 0],
208
+ 5: [2, 0, 1],
209
+ 6: [2, 1, 0],
210
+ };
211
+
212
+ export function eulerMatrix(e: readonly number[], mode: number): Mat3 {
213
+ const order = ORDERS[mode] ?? ORDERS[1];
214
+ const [first, second, third] = order as readonly [0 | 1 | 2, 0 | 1 | 2, 0 | 1 | 2];
215
+ const turn = (i: 0 | 1 | 2): Mat3 => axis(i, e[i] as number);
216
+ return multiply3(turn(third), multiply3(turn(second), turn(first)));
217
+ }
218
+
219
+ /** A quaternion as Blender stores it, `w` first, normalised before use as Blender does. */
220
+ export function quaternionMatrix(q: readonly number[]): Mat3 {
221
+ let [w, x, y, z] = q as [number, number, number, number];
222
+ const length = Math.hypot(w, x, y, z);
223
+ if (length < 1e-12) return [1, 0, 0, 0, 1, 0, 0, 0, 1];
224
+ w /= length;
225
+ x /= length;
226
+ y /= length;
227
+ z /= length;
228
+ return [
229
+ 1 - 2 * (y * y + z * z),
230
+ 2 * (x * y + w * z),
231
+ 2 * (x * z - w * y),
232
+ 2 * (x * y - w * z),
233
+ 1 - 2 * (x * x + z * z),
234
+ 2 * (y * z + w * x),
235
+ 2 * (x * z + w * y),
236
+ 2 * (y * z - w * x),
237
+ 1 - 2 * (x * x + y * y),
238
+ ];
239
+ }
240
+
241
+ export function axisAngleMatrix(direction: readonly number[], angle: number): Mat3 {
242
+ const [x, y, z] = direction as [number, number, number];
243
+ const length = Math.hypot(x, y, z);
244
+ if (length < 1e-12) return [1, 0, 0, 0, 1, 0, 0, 0, 1];
245
+ const s = Math.sin(angle / 2) / length;
246
+ return quaternionMatrix([Math.cos(angle / 2), x * s, y * s, z * s]);
247
+ }
248
+
249
+ /** Transform a point by a column-major 4x4. */
250
+ export function transformPoint(m: Mat4, x: number, y: number, z: number): [number, number, number] {
251
+ const g = (i: number): number => m[i] as number;
252
+ return [
253
+ g(0) * x + g(4) * y + g(8) * z + g(12),
254
+ g(1) * x + g(5) * y + g(9) * z + g(13),
255
+ g(2) * x + g(6) * y + g(10) * z + g(14),
256
+ ];
257
+ }