@flighthq/geometry 0.1.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 (125) hide show
  1. package/dist/aabb.d.ts +88 -0
  2. package/dist/aabb.d.ts.map +1 -0
  3. package/dist/aabb.js +230 -0
  4. package/dist/aabb.js.map +1 -0
  5. package/dist/boundingSphere.d.ts +62 -0
  6. package/dist/boundingSphere.d.ts.map +1 -0
  7. package/dist/boundingSphere.js +188 -0
  8. package/dist/boundingSphere.js.map +1 -0
  9. package/dist/capsule.d.ts +38 -0
  10. package/dist/capsule.d.ts.map +1 -0
  11. package/dist/capsule.js +215 -0
  12. package/dist/capsule.js.map +1 -0
  13. package/dist/frustum.d.ts +49 -0
  14. package/dist/frustum.d.ts.map +1 -0
  15. package/dist/frustum.js +149 -0
  16. package/dist/frustum.js.map +1 -0
  17. package/dist/index.d.ts +25 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +25 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/matrix.d.ts +152 -0
  22. package/dist/matrix.d.ts.map +1 -0
  23. package/dist/matrix.js +488 -0
  24. package/dist/matrix.js.map +1 -0
  25. package/dist/matrix3.d.ts +63 -0
  26. package/dist/matrix3.d.ts.map +1 -0
  27. package/dist/matrix3.js +408 -0
  28. package/dist/matrix3.js.map +1 -0
  29. package/dist/matrix3Pool.d.ts +6 -0
  30. package/dist/matrix3Pool.d.ts.map +1 -0
  31. package/dist/matrix3Pool.js +26 -0
  32. package/dist/matrix3Pool.js.map +1 -0
  33. package/dist/matrix4.d.ts +238 -0
  34. package/dist/matrix4.d.ts.map +1 -0
  35. package/dist/matrix4.js +931 -0
  36. package/dist/matrix4.js.map +1 -0
  37. package/dist/matrix4Pool.d.ts +6 -0
  38. package/dist/matrix4Pool.d.ts.map +1 -0
  39. package/dist/matrix4Pool.js +26 -0
  40. package/dist/matrix4Pool.js.map +1 -0
  41. package/dist/matrixPool.d.ts +6 -0
  42. package/dist/matrixPool.d.ts.map +1 -0
  43. package/dist/matrixPool.js +26 -0
  44. package/dist/matrixPool.js.map +1 -0
  45. package/dist/obb.d.ts +44 -0
  46. package/dist/obb.d.ts.map +1 -0
  47. package/dist/obb.js +248 -0
  48. package/dist/obb.js.map +1 -0
  49. package/dist/plane.d.ts +66 -0
  50. package/dist/plane.d.ts.map +1 -0
  51. package/dist/plane.js +140 -0
  52. package/dist/plane.js.map +1 -0
  53. package/dist/quaternion.d.ts +128 -0
  54. package/dist/quaternion.d.ts.map +1 -0
  55. package/dist/quaternion.js +508 -0
  56. package/dist/quaternion.js.map +1 -0
  57. package/dist/quaternionPool.d.ts +6 -0
  58. package/dist/quaternionPool.d.ts.map +1 -0
  59. package/dist/quaternionPool.js +29 -0
  60. package/dist/quaternionPool.js.map +1 -0
  61. package/dist/ray3d.d.ts +69 -0
  62. package/dist/ray3d.d.ts.map +1 -0
  63. package/dist/ray3d.js +264 -0
  64. package/dist/ray3d.js.map +1 -0
  65. package/dist/rectangle.d.ts +56 -0
  66. package/dist/rectangle.d.ts.map +1 -0
  67. package/dist/rectangle.js +235 -0
  68. package/dist/rectangle.js.map +1 -0
  69. package/dist/rectanglePool.d.ts +6 -0
  70. package/dist/rectanglePool.d.ts.map +1 -0
  71. package/dist/rectanglePool.js +29 -0
  72. package/dist/rectanglePool.js.map +1 -0
  73. package/dist/typedarray.d.ts +4 -0
  74. package/dist/typedarray.d.ts.map +1 -0
  75. package/dist/typedarray.js +25 -0
  76. package/dist/typedarray.js.map +1 -0
  77. package/dist/vector2.d.ts +130 -0
  78. package/dist/vector2.d.ts.map +1 -0
  79. package/dist/vector2.js +250 -0
  80. package/dist/vector2.js.map +1 -0
  81. package/dist/vector2Pool.d.ts +6 -0
  82. package/dist/vector2Pool.d.ts.map +1 -0
  83. package/dist/vector2Pool.js +20 -0
  84. package/dist/vector2Pool.js.map +1 -0
  85. package/dist/vector3.d.ts +220 -0
  86. package/dist/vector3.d.ts.map +1 -0
  87. package/dist/vector3.js +380 -0
  88. package/dist/vector3.js.map +1 -0
  89. package/dist/vector3Pool.d.ts +6 -0
  90. package/dist/vector3Pool.d.ts.map +1 -0
  91. package/dist/vector3Pool.js +28 -0
  92. package/dist/vector3Pool.js.map +1 -0
  93. package/dist/vector4.d.ts +180 -0
  94. package/dist/vector4.d.ts.map +1 -0
  95. package/dist/vector4.js +333 -0
  96. package/dist/vector4.js.map +1 -0
  97. package/dist/vector4Pool.d.ts +6 -0
  98. package/dist/vector4Pool.d.ts.map +1 -0
  99. package/dist/vector4Pool.js +29 -0
  100. package/dist/vector4Pool.js.map +1 -0
  101. package/package.json +38 -0
  102. package/src/aabb.test.ts +341 -0
  103. package/src/boundingSphere.test.ts +247 -0
  104. package/src/capsule.test.ts +157 -0
  105. package/src/frustum.test.ts +160 -0
  106. package/src/matrix.test.ts +1111 -0
  107. package/src/matrix3.test.ts +752 -0
  108. package/src/matrix3Pool.test.ts +73 -0
  109. package/src/matrix4.test.ts +1627 -0
  110. package/src/matrix4Pool.test.ts +71 -0
  111. package/src/matrixPool.test.ts +69 -0
  112. package/src/obb.test.ts +183 -0
  113. package/src/plane.test.ts +225 -0
  114. package/src/quaternion.test.ts +531 -0
  115. package/src/quaternionPool.test.ts +64 -0
  116. package/src/ray3d.test.ts +297 -0
  117. package/src/rectangle.test.ts +982 -0
  118. package/src/rectanglePool.test.ts +71 -0
  119. package/src/typedarray.test.ts +118 -0
  120. package/src/vector2.test.ts +958 -0
  121. package/src/vector2Pool.test.ts +65 -0
  122. package/src/vector3.test.ts +749 -0
  123. package/src/vector3Pool.test.ts +68 -0
  124. package/src/vector4.test.ts +660 -0
  125. package/src/vector4Pool.test.ts +71 -0
@@ -0,0 +1,931 @@
1
+ import { createEntity } from '@flighthq/entity';
2
+ import { acquireIdentityMatrix4, acquireMatrix4, releaseMatrix4 } from './matrix4Pool';
3
+ /**
4
+ * Appends a matrix in world space (post-multiply).
5
+ *
6
+ * out = source · other
7
+ */
8
+ export function appendMatrix4(out, source, other) {
9
+ // world-space append
10
+ multiplyMatrix4(out, source, other);
11
+ }
12
+ /**
13
+ * Applies a world-space rotation to the current matrix.
14
+ *
15
+ * Rotation is applied after all transformations of source are completed.
16
+ *
17
+ * @param radians rotation angle in radians (the @flighthq/geometry convention — convert a
18
+ * designer-facing degree value with `DEG_TO_RAD` from `@flighthq/math`).
19
+ **/
20
+ export function appendRotationMatrix4(out, source, radians, axis, pivotPoint) {
21
+ const m = acquireIdentityMatrix4();
22
+ __getAxisRotation(m, axis.x, axis.y, axis.z, radians);
23
+ if (pivotPoint !== undefined) {
24
+ const p = pivotPoint;
25
+ const t1 = acquireIdentityMatrix4();
26
+ const t2 = acquireIdentityMatrix4();
27
+ appendTranslationMatrix4(t1, t1, -p.x, -p.y, -p.z);
28
+ appendTranslationMatrix4(t2, t2, p.x, p.y, p.z);
29
+ multiplyMatrix4(m, t1, m); // R · T(-p)
30
+ multiplyMatrix4(m, m, t2); // T(p) · (R · T(-p))
31
+ releaseMatrix4(t1);
32
+ releaseMatrix4(t2);
33
+ }
34
+ appendMatrix4(out, source, m);
35
+ releaseMatrix4(m);
36
+ }
37
+ /**
38
+ * Applies a world-space scale value to the source matrix.
39
+ *
40
+ * Scale is applied after all transformations of source are completed.
41
+ **/
42
+ export function appendScaleMatrix4(out, source, xScale, yScale, zScale) {
43
+ const m = acquireMatrix4();
44
+ setMatrix4(m, xScale, 0.0, 0.0, 0.0, 0.0, yScale, 0.0, 0.0, 0.0, 0.0, zScale, 0.0, 0.0, 0.0, 0.0, 1.0);
45
+ appendMatrix4(out, source, m);
46
+ releaseMatrix4(m);
47
+ }
48
+ /**
49
+ * Applies a world-space translation to source matrix.
50
+ *
51
+ * The new translation values are calculated as:
52
+ *
53
+ * out.tx = source.tx + x
54
+ * out.ty = source.ty + y
55
+ * out.tz = source.tz + z
56
+ *
57
+ * Translation is applied after all transformations of source are completed.
58
+ */
59
+ export function appendTranslationMatrix4(out, source, x, y, z) {
60
+ const _out = out.m;
61
+ const _source = source.m;
62
+ if (out !== source)
63
+ out.m.set(source.m);
64
+ _out[12] = _source[12] + x;
65
+ _out[13] = _source[13] + y;
66
+ _out[14] = _source[14] + z;
67
+ }
68
+ export function cloneMatrix4(source) {
69
+ const m = createMatrix4();
70
+ copyMatrix4(m, source);
71
+ return m;
72
+ }
73
+ /**
74
+ * Composes a transform matrix from a translation, a rotation quaternion and a per-axis
75
+ * scale: out = T · R · S. This is the inverse operation of decomposeMatrix4.
76
+ *
77
+ * `rotation` is assumed to be a unit quaternion. Safe when `out` does not alias any input
78
+ * (the inputs are plain vector/quaternion entities, not the matrix itself).
79
+ */
80
+ export function composeMatrix4(out, position, rotation, scale) {
81
+ const x = rotation.x, y = rotation.y, z = rotation.z, w = rotation.w;
82
+ const x2 = x + x, y2 = y + y, z2 = z + z;
83
+ const xx = x * x2, xy = x * y2, xz = x * z2;
84
+ const yy = y * y2, yz = y * z2, zz = z * z2;
85
+ const wx = w * x2, wy = w * y2, wz = w * z2;
86
+ const sx = scale.x, sy = scale.y, sz = scale.z;
87
+ const _out = out.m;
88
+ _out[0] = (1 - (yy + zz)) * sx;
89
+ _out[1] = (xy + wz) * sx;
90
+ _out[2] = (xz - wy) * sx;
91
+ _out[3] = 0;
92
+ _out[4] = (xy - wz) * sy;
93
+ _out[5] = (1 - (xx + zz)) * sy;
94
+ _out[6] = (yz + wx) * sy;
95
+ _out[7] = 0;
96
+ _out[8] = (xz + wy) * sz;
97
+ _out[9] = (yz - wx) * sz;
98
+ _out[10] = (1 - (xx + yy)) * sz;
99
+ _out[11] = 0;
100
+ _out[12] = position.x;
101
+ _out[13] = position.y;
102
+ _out[14] = position.z;
103
+ _out[15] = 1;
104
+ }
105
+ export function copyMatrix4(out, source) {
106
+ out.m.set(source.m);
107
+ }
108
+ /**
109
+ Copies a column of data from a `Vector4Like` instance into the values of the target matrix
110
+ **/
111
+ export function copyMatrix4ColumnFromVector4(out, column, source) {
112
+ const _out = out.m;
113
+ switch (column) {
114
+ case 0:
115
+ _out[0] = source.x;
116
+ _out[1] = source.y;
117
+ _out[2] = source.z;
118
+ _out[3] = source.w;
119
+ break;
120
+ case 1:
121
+ _out[4] = source.x;
122
+ _out[5] = source.y;
123
+ _out[6] = source.z;
124
+ _out[7] = source.w;
125
+ break;
126
+ case 2:
127
+ _out[8] = source.x;
128
+ _out[9] = source.y;
129
+ _out[10] = source.z;
130
+ _out[11] = source.w;
131
+ break;
132
+ case 3:
133
+ _out[12] = source.x;
134
+ _out[13] = source.y;
135
+ _out[14] = source.z;
136
+ _out[15] = source.w;
137
+ break;
138
+ default:
139
+ throw new RangeError('Column ' + column + ' out of bounds [0, ..., 3]');
140
+ }
141
+ }
142
+ /**
143
+ * Copies a column of data from the source matrix into a `Vector4Like` instance
144
+ **/
145
+ export function copyMatrix4ColumnToVector4(out, column, source) {
146
+ const _source = source.m;
147
+ switch (column) {
148
+ case 0:
149
+ out.x = _source[0];
150
+ out.y = _source[1];
151
+ out.z = _source[2];
152
+ out.w = _source[3];
153
+ break;
154
+ case 1:
155
+ out.x = _source[4];
156
+ out.y = _source[5];
157
+ out.z = _source[6];
158
+ out.w = _source[7];
159
+ break;
160
+ case 2:
161
+ out.x = _source[8];
162
+ out.y = _source[9];
163
+ out.z = _source[10];
164
+ out.w = _source[11];
165
+ break;
166
+ case 3:
167
+ out.x = _source[12];
168
+ out.y = _source[13];
169
+ out.z = _source[14];
170
+ out.w = _source[15];
171
+ break;
172
+ default:
173
+ throw new RangeError('Column ' + column + ' out of bounds [0, ..., 3]');
174
+ }
175
+ }
176
+ /**
177
+ * Copies a row of data from a `Vector4Like` instance into the values of the out matrix
178
+ **/
179
+ export function copyMatrix4RowFromVector4(out, row, source) {
180
+ const _out = out.m;
181
+ switch (row) {
182
+ case 0:
183
+ _out[0] = source.x;
184
+ _out[4] = source.y;
185
+ _out[8] = source.z;
186
+ _out[12] = source.w;
187
+ break;
188
+ case 1:
189
+ _out[1] = source.x;
190
+ _out[5] = source.y;
191
+ _out[9] = source.z;
192
+ _out[13] = source.w;
193
+ break;
194
+ case 2:
195
+ _out[2] = source.x;
196
+ _out[6] = source.y;
197
+ _out[10] = source.z;
198
+ _out[14] = source.w;
199
+ break;
200
+ case 3:
201
+ _out[3] = source.x;
202
+ _out[7] = source.y;
203
+ _out[11] = source.z;
204
+ _out[15] = source.w;
205
+ break;
206
+ default:
207
+ throw new RangeError('Row ' + row + ' out of bounds [0, ..., 3]');
208
+ }
209
+ }
210
+ /**
211
+ * Copies a row of data from the source matrix into a `Vector4Like` instance
212
+ **/
213
+ export function copyMatrix4RowToVector4(out, row, source) {
214
+ const _source = source.m;
215
+ switch (row) {
216
+ case 0:
217
+ out.x = _source[0];
218
+ out.y = _source[4];
219
+ out.z = _source[8];
220
+ out.w = _source[12];
221
+ break;
222
+ case 1:
223
+ out.x = _source[1];
224
+ out.y = _source[5];
225
+ out.z = _source[9];
226
+ out.w = _source[13];
227
+ break;
228
+ case 2:
229
+ out.x = _source[2];
230
+ out.y = _source[6];
231
+ out.z = _source[10];
232
+ out.w = _source[14];
233
+ break;
234
+ case 3:
235
+ out.x = _source[3];
236
+ out.y = _source[7];
237
+ out.z = _source[11];
238
+ out.w = _source[15];
239
+ break;
240
+ default:
241
+ throw new RangeError('Row ' + row + ' out of bounds [0, ..., 3]');
242
+ }
243
+ }
244
+ /**
245
+ * A 4×4 homogeneous matrix.
246
+ *
247
+ * [ m00 m10 m20 m30 ]
248
+ * [ m01 m11 m21 m31 ]
249
+ * [ m02 m12 m22 m32 ]
250
+ * [ m03 m13 m23 m33 ]
251
+ *
252
+ * Storage is column-major (OpenGL-compatible).
253
+ *
254
+ * This matrix assumes column vectors, multiplied on the right:
255
+ * v' = M · v
256
+ */
257
+ export function createMatrix4(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
258
+ const m = new Float32Array(__identity);
259
+ const out = createEntity({ m: m });
260
+ if (m00 !== undefined)
261
+ m[0] = m00;
262
+ if (m01 !== undefined)
263
+ m[1] = m01;
264
+ if (m02 !== undefined)
265
+ m[2] = m02;
266
+ if (m03 !== undefined)
267
+ m[3] = m03;
268
+ if (m10 !== undefined)
269
+ m[4] = m10;
270
+ if (m11 !== undefined)
271
+ m[5] = m11;
272
+ if (m12 !== undefined)
273
+ m[6] = m12;
274
+ if (m13 !== undefined)
275
+ m[7] = m13;
276
+ if (m20 !== undefined)
277
+ m[8] = m20;
278
+ if (m21 !== undefined)
279
+ m[9] = m21;
280
+ if (m22 !== undefined)
281
+ m[10] = m22;
282
+ if (m23 !== undefined)
283
+ m[11] = m23;
284
+ if (m30 !== undefined)
285
+ m[12] = m30;
286
+ if (m31 !== undefined)
287
+ m[13] = m31;
288
+ if (m32 !== undefined)
289
+ m[14] = m32;
290
+ if (m33 !== undefined)
291
+ m[15] = m33;
292
+ return out;
293
+ }
294
+ /**
295
+ * Creates a matrix using two-dimensional transform values
296
+ **/
297
+ export function createMatrix4From2D(a, b, c, d, tx, ty) {
298
+ const out = createMatrix4();
299
+ setMatrix4From2D(out, a, b, c, d, tx, ty);
300
+ return out;
301
+ }
302
+ /**
303
+ * Initializes this matrix with values for an orthographic projection, useful in rendering
304
+ **/
305
+ export function createOrthographicMatrix4(left, right, bottom, top, zNear, zFar) {
306
+ const out = createMatrix4();
307
+ setOrthographicMatrix4(out, left, right, bottom, top, zNear, zFar);
308
+ return out;
309
+ }
310
+ /**
311
+ * Initializes this matrix with values for a perspective projection
312
+ **/
313
+ export function createPerspectiveMatrix4(fov, aspect, zNear, zFar) {
314
+ const out = createMatrix4();
315
+ setPerspectiveMatrix4(out, fov, aspect, zNear, zFar);
316
+ return out;
317
+ }
318
+ /**
319
+ * Decomposes a transform matrix into its translation, rotation quaternion and per-axis
320
+ * scale, the inverse of composeMatrix4. Assumes the matrix is a TRS composition (no shear);
321
+ * a negative determinant flips the X scale sign so the extracted rotation stays a proper
322
+ * rotation.
323
+ *
324
+ * Reads the matrix into locals before writing, so it is safe for the outputs to alias
325
+ * fields of unrelated entities; the matrix `m` is read-only.
326
+ */
327
+ export function decomposeMatrix4(outPosition, outRotation, outScale, m) {
328
+ const _m = m.m;
329
+ const m00 = _m[0], m01 = _m[1], m02 = _m[2];
330
+ const m10 = _m[4], m11 = _m[5], m12 = _m[6];
331
+ const m20 = _m[8], m21 = _m[9], m22 = _m[10];
332
+ const tx = _m[12], ty = _m[13], tz = _m[14];
333
+ let sx = Math.sqrt(m00 * m00 + m01 * m01 + m02 * m02);
334
+ const sy = Math.sqrt(m10 * m10 + m11 * m11 + m12 * m12);
335
+ const sz = Math.sqrt(m20 * m20 + m21 * m21 + m22 * m22);
336
+ // A negative determinant means an odd number of mirror flips; fold it into X.
337
+ const det = m00 * (m11 * m22 - m12 * m21) - m10 * (m01 * m22 - m02 * m21) + m20 * (m01 * m12 - m02 * m11);
338
+ if (det < 0)
339
+ sx = -sx;
340
+ outPosition.x = tx;
341
+ outPosition.y = ty;
342
+ outPosition.z = tz;
343
+ outScale.x = sx;
344
+ outScale.y = sy;
345
+ outScale.z = sz;
346
+ const invSx = sx !== 0 ? 1 / sx : 0;
347
+ const invSy = sy !== 0 ? 1 / sy : 0;
348
+ const invSz = sz !== 0 ? 1 / sz : 0;
349
+ // Normalized rotation basis (column-major upper 3×3).
350
+ const r00 = m00 * invSx, r01 = m01 * invSx, r02 = m02 * invSx;
351
+ const r10 = m10 * invSy, r11 = m11 * invSy, r12 = m12 * invSy;
352
+ const r20 = m20 * invSz, r21 = m21 * invSz, r22 = m22 * invSz;
353
+ const trace = r00 + r11 + r22;
354
+ if (trace > 0) {
355
+ const s = 0.5 / Math.sqrt(trace + 1.0);
356
+ outRotation.w = 0.25 / s;
357
+ outRotation.x = (r12 - r21) * s;
358
+ outRotation.y = (r20 - r02) * s;
359
+ outRotation.z = (r01 - r10) * s;
360
+ }
361
+ else if (r00 > r11 && r00 > r22) {
362
+ const s = 2.0 * Math.sqrt(1.0 + r00 - r11 - r22);
363
+ outRotation.w = (r12 - r21) / s;
364
+ outRotation.x = 0.25 * s;
365
+ outRotation.y = (r10 + r01) / s;
366
+ outRotation.z = (r20 + r02) / s;
367
+ }
368
+ else if (r11 > r22) {
369
+ const s = 2.0 * Math.sqrt(1.0 + r11 - r00 - r22);
370
+ outRotation.w = (r20 - r02) / s;
371
+ outRotation.x = (r10 + r01) / s;
372
+ outRotation.y = 0.25 * s;
373
+ outRotation.z = (r21 + r12) / s;
374
+ }
375
+ else {
376
+ const s = 2.0 * Math.sqrt(1.0 + r22 - r00 - r11);
377
+ outRotation.w = (r01 - r10) / s;
378
+ outRotation.x = (r20 + r02) / s;
379
+ outRotation.y = (r21 + r12) / s;
380
+ outRotation.z = 0.25 * s;
381
+ }
382
+ }
383
+ export function equalsMatrix4(a, b) {
384
+ if (a === b)
385
+ return true;
386
+ if (!a || !b)
387
+ return false;
388
+ for (let i = 0; i < 16; i++) {
389
+ if (a.m[i] !== b.m[i])
390
+ return false;
391
+ }
392
+ return true;
393
+ }
394
+ export function getMatrix4Determinant(source) {
395
+ const _source = source.m;
396
+ return (1 *
397
+ ((_source[0] * _source[5] - _source[4] * _source[1]) * (_source[10] * _source[15] - _source[14] * _source[11]) -
398
+ (_source[0] * _source[9] - _source[8] * _source[1]) * (_source[6] * _source[15] - _source[14] * _source[7]) +
399
+ (_source[0] * _source[13] - _source[12] * _source[1]) * (_source[6] * _source[11] - _source[10] * _source[7]) +
400
+ (_source[4] * _source[9] - _source[8] * _source[5]) * (_source[2] * _source[15] - _source[14] * _source[3]) -
401
+ (_source[4] * _source[13] - _source[12] * _source[5]) * (_source[2] * _source[11] - _source[10] * _source[3]) +
402
+ (_source[8] * _source[13] - _source[12] * _source[9]) * (_source[2] * _source[7] - _source[6] * _source[3])));
403
+ }
404
+ export function getMatrix4Element(source, row, column) {
405
+ return source.m[column * 4 + row];
406
+ }
407
+ export function getMatrix4Position(out, source) {
408
+ const _source = source.m;
409
+ out.x = _source[12];
410
+ out.y = _source[13];
411
+ out.z = _source[14];
412
+ }
413
+ /**
414
+ * Interpolates from one `Matrix4Like` instance to another, given a percentage between the two
415
+ **/
416
+ export function interpolateMatrix4(out, a, b, t) {
417
+ const _out = out.m;
418
+ const _a = a.m;
419
+ const _b = b.m;
420
+ for (let i = 0; i < 16; i++) {
421
+ _out[i] = _a[i] + (_b[i] - _a[i]) * t;
422
+ }
423
+ }
424
+ /**
425
+ * Attempts to invert the current matrix, so long as the determinant is greater than zero
426
+ **/
427
+ export function inverseMatrix4(out, source) {
428
+ const _out = out.m;
429
+ const _source = source.m;
430
+ // Calculate determinant
431
+ let d = getMatrix4Determinant(source);
432
+ // Threshold for determining if matrix is invertible
433
+ const EPS = 1e-6;
434
+ const invertable = Math.abs(d) > EPS;
435
+ if (!invertable) {
436
+ // If the matrix is singular, set output to NaN or Identity
437
+ _out.fill(NaN); // Set all elements to NaN (or you could set to the identity matrix, depending on your preference)
438
+ return false;
439
+ }
440
+ // Invertable matrix, proceed with inversion
441
+ d = 1 / d;
442
+ // Decompose the matrix into elements for readability
443
+ const m11 = _source[0], m21 = _source[4], m31 = _source[8], m41 = _source[12];
444
+ const m12 = _source[1], m22 = _source[5], m32 = _source[9], m42 = _source[13];
445
+ const m13 = _source[2], m23 = _source[6], m33 = _source[10], m43 = _source[14];
446
+ const m14 = _source[3], m24 = _source[7], m34 = _source[11], m44 = _source[15];
447
+ // Perform matrix inversion based on the determinant
448
+ _out[0] = d * (m22 * (m33 * m44 - m43 * m34) - m32 * (m23 * m44 - m43 * m24) + m42 * (m23 * m34 - m33 * m24));
449
+ _out[1] = -d * (m12 * (m33 * m44 - m43 * m34) - m32 * (m13 * m44 - m43 * m14) + m42 * (m13 * m34 - m33 * m14));
450
+ _out[2] = d * (m12 * (m23 * m44 - m43 * m24) - m22 * (m13 * m44 - m43 * m14) + m42 * (m13 * m24 - m23 * m14));
451
+ _out[3] = -d * (m12 * (m23 * m34 - m33 * m24) - m22 * (m13 * m34 - m33 * m14) + m32 * (m13 * m24 - m23 * m14));
452
+ _out[4] = -d * (m21 * (m33 * m44 - m43 * m34) - m31 * (m23 * m44 - m43 * m24) + m41 * (m23 * m34 - m33 * m24));
453
+ _out[5] = d * (m11 * (m33 * m44 - m43 * m34) - m31 * (m13 * m44 - m43 * m14) + m41 * (m13 * m34 - m33 * m14));
454
+ _out[6] = -d * (m11 * (m23 * m44 - m43 * m24) - m21 * (m13 * m44 - m43 * m14) + m41 * (m13 * m24 - m23 * m14));
455
+ _out[7] = d * (m11 * (m23 * m34 - m33 * m24) - m21 * (m13 * m34 - m33 * m14) + m31 * (m13 * m24 - m23 * m14));
456
+ _out[8] = d * (m21 * (m32 * m44 - m42 * m34) - m31 * (m22 * m44 - m42 * m24) + m41 * (m22 * m34 - m32 * m24));
457
+ _out[9] = -d * (m11 * (m32 * m44 - m42 * m34) - m31 * (m12 * m44 - m42 * m14) + m41 * (m12 * m34 - m32 * m14));
458
+ _out[10] = d * (m11 * (m22 * m44 - m42 * m24) - m21 * (m12 * m44 - m42 * m14) + m41 * (m12 * m24 - m22 * m14));
459
+ _out[11] = -d * (m11 * (m22 * m34 - m32 * m24) - m21 * (m12 * m34 - m32 * m14) + m31 * (m12 * m24 - m22 * m14));
460
+ _out[12] = -d * (m21 * (m32 * m43 - m42 * m33) - m31 * (m22 * m43 - m42 * m23) + m41 * (m22 * m33 - m32 * m23));
461
+ _out[13] = d * (m11 * (m32 * m43 - m42 * m33) - m31 * (m12 * m43 - m42 * m13) + m41 * (m12 * m33 - m32 * m13));
462
+ _out[14] = -d * (m11 * (m22 * m43 - m42 * m23) - m21 * (m12 * m43 - m42 * m13) + m41 * (m12 * m23 - m22 * m13));
463
+ _out[15] = d * (m11 * (m22 * m33 - m32 * m23) - m21 * (m12 * m33 - m32 * m13) + m31 * (m12 * m23 - m22 * m13));
464
+ return invertable;
465
+ }
466
+ export function isAffineMatrix4(source) {
467
+ const _source = source.m;
468
+ return _source[3] === 0 && _source[7] === 0 && _source[11] === 0 && _source[15] === 1;
469
+ }
470
+ /**
471
+ * Transforms a point using this matrix, including the translation of the matrix.
472
+ **/
473
+ export function matrix4TransformPoint(out, source, point) {
474
+ const _source = source.m;
475
+ const x = point.x, y = point.y, z = point.z;
476
+ out.x = x * _source[0] + y * _source[4] + z * _source[8] + _source[12];
477
+ out.y = x * _source[1] + y * _source[5] + z * _source[9] + _source[13];
478
+ out.z = x * _source[2] + y * _source[6] + z * _source[10] + _source[14];
479
+ }
480
+ /**
481
+ * Transforms a `Vector4Like` instance using this matrix.
482
+ **/
483
+ export function matrix4TransformVector(out, source, vector) {
484
+ const _source = source.m;
485
+ const x = vector.x, y = vector.y, z = vector.z, w = vector.w;
486
+ out.x = x * _source[0] + y * _source[4] + z * _source[8] + w * _source[12];
487
+ out.y = x * _source[1] + y * _source[5] + z * _source[9] + w * _source[13];
488
+ out.z = x * _source[2] + y * _source[6] + z * _source[10] + w * _source[14];
489
+ out.w = x * _source[3] + y * _source[7] + z * _source[11] + w * _source[15];
490
+ }
491
+ /**
492
+ * Transforms a series of [x, y, z] triples at once.
493
+ **/
494
+ export function matrix4TransformVectors(out, source, vectors) {
495
+ const _source = source.m;
496
+ let i = 0;
497
+ let x, y, z;
498
+ while (i + 3 <= vectors.length) {
499
+ x = vectors[i];
500
+ y = vectors[i + 1];
501
+ z = vectors[i + 2];
502
+ out[i] = x * _source[0] + y * _source[4] + z * _source[8] + _source[12];
503
+ out[i + 1] = x * _source[1] + y * _source[5] + z * _source[9] + _source[13];
504
+ out[i + 2] = x * _source[2] + y * _source[6] + z * _source[10] + _source[14];
505
+ i += 3;
506
+ }
507
+ }
508
+ /**
509
+ * Matrix multiplication
510
+ *
511
+ * out = a * b
512
+ **/
513
+ export function multiplyMatrix4(out, a, b) {
514
+ const _a = a.m;
515
+ const _b = b.m;
516
+ const _out = out.m;
517
+ const m111 = _a[0], m121 = _a[4], m131 = _a[8], m141 = _a[12], m112 = _a[1], m122 = _a[5], m132 = _a[9], m142 = _a[13], m113 = _a[2], m123 = _a[6], m133 = _a[10], m143 = _a[14], m114 = _a[3], m124 = _a[7], m134 = _a[11], m144 = _a[15], m211 = _b[0], m221 = _b[4], m231 = _b[8], m241 = _b[12], m212 = _b[1], m222 = _b[5], m232 = _b[9], m242 = _b[13], m213 = _b[2], m223 = _b[6], m233 = _b[10], m243 = _b[14], m214 = _b[3], m224 = _b[7], m234 = _b[11], m244 = _b[15];
518
+ // Note the switched order of matrix a and matrix b
519
+ _out[0] = m211 * m111 + m212 * m121 + m213 * m131 + m214 * m141;
520
+ _out[1] = m211 * m112 + m212 * m122 + m213 * m132 + m214 * m142;
521
+ _out[2] = m211 * m113 + m212 * m123 + m213 * m133 + m214 * m143;
522
+ _out[3] = m211 * m114 + m212 * m124 + m213 * m134 + m214 * m144;
523
+ _out[4] = m221 * m111 + m222 * m121 + m223 * m131 + m224 * m141;
524
+ _out[5] = m221 * m112 + m222 * m122 + m223 * m132 + m224 * m142;
525
+ _out[6] = m221 * m113 + m222 * m123 + m223 * m133 + m224 * m143;
526
+ _out[7] = m221 * m114 + m222 * m124 + m223 * m134 + m224 * m144;
527
+ _out[8] = m231 * m111 + m232 * m121 + m233 * m131 + m234 * m141;
528
+ _out[9] = m231 * m112 + m232 * m122 + m233 * m132 + m234 * m142;
529
+ _out[10] = m231 * m113 + m232 * m123 + m233 * m133 + m234 * m143;
530
+ _out[11] = m231 * m114 + m232 * m124 + m233 * m134 + m234 * m144;
531
+ _out[12] = m241 * m111 + m242 * m121 + m243 * m131 + m244 * m141;
532
+ _out[13] = m241 * m112 + m242 * m122 + m243 * m132 + m244 * m142;
533
+ _out[14] = m241 * m113 + m242 * m123 + m243 * m133 + m244 * m143;
534
+ _out[15] = m241 * m114 + m242 * m124 + m243 * m134 + m244 * m144;
535
+ }
536
+ /**
537
+ * Prepends a matrix in world space (pre-multiply).
538
+ *
539
+ * out = other · source
540
+ */
541
+ export function prependMatrix4(out, source, other) {
542
+ multiplyMatrix4(out, other, source);
543
+ }
544
+ /**
545
+ * Prepends rotation before all local-space transforms.
546
+ *
547
+ * This method first applies the translation (tx, ty, tz) and then applies all the transformations
548
+ * (e.g., rotation, scaling, etc.) from the source matrix.
549
+ *
550
+ * @param radians rotation angle in radians (the @flighthq/geometry convention — convert a
551
+ * designer-facing degree value with `DEG_TO_RAD` from `@flighthq/math`).
552
+ **/
553
+ export function prependRotationMatrix4(out, source, radians, axis, pivotPoint) {
554
+ const m = acquireIdentityMatrix4();
555
+ __getAxisRotation(m, axis.x, axis.y, axis.z, radians);
556
+ if (pivotPoint !== undefined) {
557
+ const p = pivotPoint;
558
+ const t1 = acquireIdentityMatrix4();
559
+ const t2 = acquireIdentityMatrix4();
560
+ appendTranslationMatrix4(t1, t1, -p.x, -p.y, -p.z);
561
+ appendTranslationMatrix4(t2, t2, p.x, p.y, p.z);
562
+ multiplyMatrix4(m, m, t1); // R · T(-p)
563
+ multiplyMatrix4(m, t2, m); // T(p) · (R · T(-p))
564
+ releaseMatrix4(t1);
565
+ releaseMatrix4(t2);
566
+ }
567
+ prependMatrix4(out, source, m);
568
+ releaseMatrix4(m);
569
+ }
570
+ /**
571
+ * Prepends scale before all local-space transforms.
572
+ *
573
+ * This method first applies the translation (tx, ty, tz) and then applies all the transformations
574
+ * (e.g., rotation, scaling, etc.) from the source matrix.
575
+ **/
576
+ export function prependScaleMatrix4(out, source, xScale, yScale, zScale) {
577
+ const m = acquireMatrix4();
578
+ setMatrix4(m, xScale, 0.0, 0.0, 0.0, 0.0, yScale, 0.0, 0.0, 0.0, 0.0, zScale, 0.0, 0.0, 0.0, 0.0, 1.0);
579
+ prependMatrix4(out, source, m);
580
+ releaseMatrix4(m);
581
+ }
582
+ /**
583
+ * Prepends a translation before all local-space transforms.
584
+ *
585
+ * This method first applies the translation (tx, ty, tz) and then applies all the transformations
586
+ * (e.g., rotation, scaling, etc.) from the source matrix.
587
+ */
588
+ export function prependTranslationMatrix4(out, source, x, y, z) {
589
+ const m = acquireIdentityMatrix4();
590
+ translateMatrix4(m, m, x, y, z); // LOCAL translation matrix
591
+ multiplyMatrix4(out, m, source);
592
+ releaseMatrix4(m);
593
+ }
594
+ /**
595
+ * Applies a local-space rotation relative to the matrix's existing orientation.
596
+ *
597
+ * Translation is preserved.
598
+ *
599
+ * @param radians rotation angle in radians (the @flighthq/geometry convention — convert a
600
+ * designer-facing degree value with `DEG_TO_RAD` from `@flighthq/math`).
601
+ */
602
+ export function rotateMatrix4(out, source, axis, radians) {
603
+ const m = acquireIdentityMatrix4();
604
+ __getAxisRotation(m, axis.x, axis.y, axis.z, radians);
605
+ multiplyMatrix4(out, source, m);
606
+ releaseMatrix4(m);
607
+ }
608
+ /**
609
+ * Applies a local-space scale relative to the matrix's existing orientation.
610
+ *
611
+ * Translation is preserved.
612
+ */
613
+ export function scaleMatrix4(out, source, sx, sy, sz) {
614
+ const a = source.m;
615
+ const o = out.m;
616
+ if (out !== source)
617
+ out.m.set(source.m);
618
+ if (sx !== 1) {
619
+ o[0] = a[0] * sx;
620
+ o[4] = a[4] * sx;
621
+ o[8] = a[8] * sx;
622
+ }
623
+ if (sy !== 1) {
624
+ o[1] = a[1] * sy;
625
+ o[5] = a[5] * sy;
626
+ o[9] = a[9] * sy;
627
+ }
628
+ if (sz !== 1) {
629
+ o[2] = a[2] * sz;
630
+ o[6] = a[6] * sz;
631
+ o[10] = a[10] * sz;
632
+ }
633
+ }
634
+ export function setMatrix4(out, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
635
+ const _out = out.m;
636
+ _out[0] = m00;
637
+ _out[1] = m01;
638
+ _out[2] = m02;
639
+ _out[3] = m03;
640
+ _out[4] = m10;
641
+ _out[5] = m11;
642
+ _out[6] = m12;
643
+ _out[7] = m13;
644
+ _out[8] = m20;
645
+ _out[9] = m21;
646
+ _out[10] = m22;
647
+ _out[11] = m23;
648
+ _out[12] = m30;
649
+ _out[13] = m31;
650
+ _out[14] = m32;
651
+ _out[15] = m33;
652
+ }
653
+ export function setMatrix4Element(out, row, column, value) {
654
+ out.m[column * 4 + row] = value;
655
+ }
656
+ /**
657
+ * Resets the current matrix using two-dimensional transform values
658
+ **/
659
+ export function setMatrix4From2D(out, a, b, c, d, tx, ty) {
660
+ const _out = out.m;
661
+ tx = tx ?? 0;
662
+ ty = ty ?? 0;
663
+ _out[0] = a;
664
+ _out[1] = b;
665
+ _out[2] = 0;
666
+ _out[3] = 0;
667
+ _out[4] = c;
668
+ _out[5] = d;
669
+ _out[6] = 0;
670
+ _out[7] = 0;
671
+ _out[8] = 0;
672
+ _out[9] = 0;
673
+ _out[10] = 1;
674
+ _out[11] = 0;
675
+ _out[12] = tx;
676
+ _out[13] = ty;
677
+ _out[14] = 0;
678
+ _out[15] = 1;
679
+ }
680
+ /**
681
+ * Reads 16 elements of a column-major Float32Array at `offset` into a Matrix4Like.
682
+ *
683
+ * Mirrors `writeMatrix4ToFloat32Array` and matches the existing vec2/3/4 and Matrix3 bridges.
684
+ */
685
+ export function setMatrix4FromFloat32Array(out, offset, source) {
686
+ out.m.set(source.subarray(offset, offset + 16));
687
+ }
688
+ export function setMatrix4FromMatrix(out, source) {
689
+ setMatrix4From2D(out, source.a, source.b, source.c, source.d, source.tx, source.ty);
690
+ }
691
+ export function setMatrix4FromMatrix3(out, source) {
692
+ const _out = out.m;
693
+ const _source = source.m;
694
+ setMatrix4From2D(out, _source[0], _source[1], _source[3], _source[4], _source[2], _source[5]);
695
+ _out[2] = _source[6];
696
+ _out[6] = _source[7];
697
+ _out[10] = _source[8];
698
+ }
699
+ /**
700
+ * Writes the rotation described by a unit quaternion into the upper-left 3×3 of an
701
+ * identity matrix (translation cleared, bottom row 0,0,0,1). glTF handedness.
702
+ */
703
+ export function setMatrix4FromQuaternion(out, source) {
704
+ const x = source.x, y = source.y, z = source.z, w = source.w;
705
+ const x2 = x + x, y2 = y + y, z2 = z + z;
706
+ const xx = x * x2, xy = x * y2, xz = x * z2;
707
+ const yy = y * y2, yz = y * z2, zz = z * z2;
708
+ const wx = w * x2, wy = w * y2, wz = w * z2;
709
+ const _out = out.m;
710
+ _out[0] = 1 - (yy + zz);
711
+ _out[1] = xy + wz;
712
+ _out[2] = xz - wy;
713
+ _out[3] = 0;
714
+ _out[4] = xy - wz;
715
+ _out[5] = 1 - (xx + zz);
716
+ _out[6] = yz + wx;
717
+ _out[7] = 0;
718
+ _out[8] = xz + wy;
719
+ _out[9] = yz - wx;
720
+ _out[10] = 1 - (xx + yy);
721
+ _out[11] = 0;
722
+ _out[12] = 0;
723
+ _out[13] = 0;
724
+ _out[14] = 0;
725
+ _out[15] = 1;
726
+ }
727
+ /**
728
+ * Resets the current matrix using default identity values
729
+ **/
730
+ export function setMatrix4Identity(out) {
731
+ setMatrix4(out, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
732
+ }
733
+ /**
734
+ * Builds a right-handed look-at view matrix that positions a camera at `eye` looking toward
735
+ * `target`, with `up` defining the camera roll. The forward axis points from eye to target;
736
+ * the resulting matrix transforms world-space points into view space.
737
+ *
738
+ * Reads all inputs into locals before writing, so it is safe when `out` is unrelated to the
739
+ * vector inputs.
740
+ */
741
+ export function setMatrix4LookAt(out, eye, target, up) {
742
+ const eyeX = eye.x, eyeY = eye.y, eyeZ = eye.z;
743
+ // z axis = normalize(eye - target) (points from target back toward the eye, RH).
744
+ let zx = eyeX - target.x;
745
+ let zy = eyeY - target.y;
746
+ let zz = eyeZ - target.z;
747
+ let zl = Math.sqrt(zx * zx + zy * zy + zz * zz);
748
+ if (zl === 0) {
749
+ zz = 1;
750
+ zl = 1;
751
+ }
752
+ zx /= zl;
753
+ zy /= zl;
754
+ zz /= zl;
755
+ // x axis = normalize(cross(up, z)).
756
+ let xx = up.y * zz - up.z * zy;
757
+ let xy = up.z * zx - up.x * zz;
758
+ let xz = up.x * zy - up.y * zx;
759
+ let xl = Math.sqrt(xx * xx + xy * xy + xz * xz);
760
+ if (xl === 0) {
761
+ xx = 0;
762
+ xy = 0;
763
+ xz = 0;
764
+ }
765
+ else {
766
+ xx /= xl;
767
+ xy /= xl;
768
+ xz /= xl;
769
+ }
770
+ // y axis = cross(z, x) (already orthonormal).
771
+ const yx = zy * xz - zz * xy;
772
+ const yy = zz * xx - zx * xz;
773
+ const yz = zx * xy - zy * xx;
774
+ const _out = out.m;
775
+ _out[0] = xx;
776
+ _out[1] = yx;
777
+ _out[2] = zx;
778
+ _out[3] = 0;
779
+ _out[4] = xy;
780
+ _out[5] = yy;
781
+ _out[6] = zy;
782
+ _out[7] = 0;
783
+ _out[8] = xz;
784
+ _out[9] = yz;
785
+ _out[10] = zz;
786
+ _out[11] = 0;
787
+ _out[12] = -(xx * eyeX + xy * eyeY + xz * eyeZ);
788
+ _out[13] = -(yx * eyeX + yy * eyeY + yz * eyeZ);
789
+ _out[14] = -(zx * eyeX + zy * eyeY + zz * eyeZ);
790
+ _out[15] = 1;
791
+ }
792
+ export function setMatrix4Position(out, source) {
793
+ const _out = out.m;
794
+ _out[12] = source.x;
795
+ _out[13] = source.y;
796
+ _out[14] = source.z;
797
+ }
798
+ /**
799
+ * Initializes a matrix with values for an orthographic projection, useful in rendering
800
+ **/
801
+ export function setOrthographicMatrix4(out, left, right, bottom, top, zNear, zFar) {
802
+ const _out = out.m;
803
+ const sx = 1.0 / (right - left);
804
+ const sy = 1.0 / (top - bottom);
805
+ const sz = 1.0 / (zFar - zNear);
806
+ _out[0] = 2 * sx;
807
+ _out[1] = 0;
808
+ _out[2] = 0;
809
+ _out[3] = 0;
810
+ _out[4] = 0;
811
+ _out[5] = 2 * sy;
812
+ _out[6] = 0;
813
+ _out[7] = 0;
814
+ _out[8] = 0;
815
+ _out[9] = 0;
816
+ _out[10] = -2 * sz;
817
+ _out[11] = 0;
818
+ _out[12] = -(left + right) * sx;
819
+ _out[13] = -(bottom + top) * sy;
820
+ _out[14] = -(zNear + zFar) * sz;
821
+ _out[15] = 1;
822
+ }
823
+ /**
824
+ * Initializes a matrix with values for a perspective projection
825
+ **/
826
+ export function setPerspectiveMatrix4(out, fov, aspect, zNear, zFar) {
827
+ if (aspect > -0.0000001 && aspect < 0.0000001) {
828
+ throw new Error('Aspect ratio may not be 0');
829
+ }
830
+ const _out = out.m;
831
+ const top = fov * zNear;
832
+ const bottom = -top;
833
+ const right = top * aspect;
834
+ const left = -right;
835
+ _out[0] = (2.0 * zNear) / (right - left);
836
+ _out[1] = 0;
837
+ _out[2] = 0;
838
+ _out[3] = 0;
839
+ _out[4] = 0;
840
+ _out[5] = (2.0 * zNear) / (top - bottom);
841
+ _out[6] = 0;
842
+ _out[7] = 0;
843
+ _out[8] = (right + left) / (right - left);
844
+ _out[9] = (top + bottom) / (top - bottom);
845
+ _out[10] = -(zFar + zNear) / (zFar - zNear);
846
+ _out[11] = -1.0;
847
+ _out[12] = 0;
848
+ _out[13] = 0;
849
+ _out[14] = (-2 * zFar * zNear) / (zFar - zNear);
850
+ // Row-3 of a perspective matrix is (0, 0, -1, 0): m[11] = -1 routes -z_eye into clip w, and m[15]
851
+ // MUST be 0 so w = -z (not -z + w_in). A stray 1 here (identity leftover) makes w = -z + 1, which
852
+ // shrinks projected geometry toward the near plane.
853
+ _out[15] = 0;
854
+ }
855
+ /**
856
+ * Applies a local-space translation to the matrix, taking into account the source matrix's rotation and scale.
857
+ *
858
+ * Translation is applied respecting using all other transformations of source.
859
+ */
860
+ export function translateMatrix4(out, source, tx, ty, tz) {
861
+ const a = source.m;
862
+ const o = out.m;
863
+ if (out !== source)
864
+ out.m.set(source.m);
865
+ o[12] = a[0] * tx + a[4] * ty + a[8] * tz + a[12];
866
+ o[13] = a[1] * tx + a[5] * ty + a[9] * tz + a[13];
867
+ o[14] = a[2] * tx + a[6] * ty + a[10] * tz + a[14];
868
+ }
869
+ export function transposeMatrix4(out, source) {
870
+ if (out !== source)
871
+ out.m.set(source.m);
872
+ __swap(out, source, 1, 4);
873
+ __swap(out, source, 2, 8);
874
+ __swap(out, source, 3, 12);
875
+ __swap(out, source, 6, 9);
876
+ __swap(out, source, 7, 13);
877
+ __swap(out, source, 11, 14);
878
+ }
879
+ /**
880
+ * Transposes the matrix (swaps rows and columns).
881
+ *
882
+ * Note:
883
+ * - Storage order (column-major) is unchanged
884
+ * - This is a mathematical transpose, not a memory layout conversion
885
+ *
886
+ * Common uses:
887
+ * - Computing inverse-transpose for normals
888
+ * - Switching between row- and column-vector math conventions
889
+ */
890
+ /**
891
+ * Writes 16 column-major elements of a Matrix4Like into a Float32Array at `offset`.
892
+ *
893
+ * Mirrors `setMatrix4FromFloat32Array` and the existing vec2/3/4 and Matrix3 bridges.
894
+ */
895
+ export function writeMatrix4ToFloat32Array(out, offset, source) {
896
+ out.set(source.m, offset);
897
+ }
898
+ function __getAxisRotation(out, x, y, z, radians) {
899
+ const _out = out.m;
900
+ let ax = x, ay = y, az = z;
901
+ // Negated to preserve the rotation handedness the degrees-based version produced; the caller's
902
+ // angle is already radians (the @flighthq/geometry math-layer convention), so no unit conversion.
903
+ const rad = -radians;
904
+ const c = Math.cos(rad);
905
+ const s = Math.sin(rad);
906
+ const t = 1.0 - c;
907
+ _out[0] = c + ax * ax * t;
908
+ _out[5] = c + ay * ay * t;
909
+ _out[10] = c + az * az * t;
910
+ let tmp1 = ax * ay * t;
911
+ let tmp2 = az * s;
912
+ _out[4] = tmp1 + tmp2;
913
+ _out[1] = tmp1 - tmp2;
914
+ tmp1 = ax * az * t;
915
+ tmp2 = ay * s;
916
+ _out[8] = tmp1 - tmp2;
917
+ _out[2] = tmp1 + tmp2;
918
+ tmp1 = ay * az * t;
919
+ tmp2 = ax * s;
920
+ _out[9] = tmp1 + tmp2;
921
+ _out[6] = tmp1 - tmp2;
922
+ }
923
+ function __swap(out, source, a, b) {
924
+ const temp = source.m[a];
925
+ out.m[a] = source.m[b];
926
+ out.m[b] = temp;
927
+ }
928
+ const __identity = new Float32Array([
929
+ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
930
+ ]);
931
+ //# sourceMappingURL=matrix4.js.map