@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.
- package/dist/aabb.d.ts +88 -0
- package/dist/aabb.d.ts.map +1 -0
- package/dist/aabb.js +230 -0
- package/dist/aabb.js.map +1 -0
- package/dist/boundingSphere.d.ts +62 -0
- package/dist/boundingSphere.d.ts.map +1 -0
- package/dist/boundingSphere.js +188 -0
- package/dist/boundingSphere.js.map +1 -0
- package/dist/capsule.d.ts +38 -0
- package/dist/capsule.d.ts.map +1 -0
- package/dist/capsule.js +215 -0
- package/dist/capsule.js.map +1 -0
- package/dist/frustum.d.ts +49 -0
- package/dist/frustum.d.ts.map +1 -0
- package/dist/frustum.js +149 -0
- package/dist/frustum.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/matrix.d.ts +152 -0
- package/dist/matrix.d.ts.map +1 -0
- package/dist/matrix.js +488 -0
- package/dist/matrix.js.map +1 -0
- package/dist/matrix3.d.ts +63 -0
- package/dist/matrix3.d.ts.map +1 -0
- package/dist/matrix3.js +408 -0
- package/dist/matrix3.js.map +1 -0
- package/dist/matrix3Pool.d.ts +6 -0
- package/dist/matrix3Pool.d.ts.map +1 -0
- package/dist/matrix3Pool.js +26 -0
- package/dist/matrix3Pool.js.map +1 -0
- package/dist/matrix4.d.ts +238 -0
- package/dist/matrix4.d.ts.map +1 -0
- package/dist/matrix4.js +931 -0
- package/dist/matrix4.js.map +1 -0
- package/dist/matrix4Pool.d.ts +6 -0
- package/dist/matrix4Pool.d.ts.map +1 -0
- package/dist/matrix4Pool.js +26 -0
- package/dist/matrix4Pool.js.map +1 -0
- package/dist/matrixPool.d.ts +6 -0
- package/dist/matrixPool.d.ts.map +1 -0
- package/dist/matrixPool.js +26 -0
- package/dist/matrixPool.js.map +1 -0
- package/dist/obb.d.ts +44 -0
- package/dist/obb.d.ts.map +1 -0
- package/dist/obb.js +248 -0
- package/dist/obb.js.map +1 -0
- package/dist/plane.d.ts +66 -0
- package/dist/plane.d.ts.map +1 -0
- package/dist/plane.js +140 -0
- package/dist/plane.js.map +1 -0
- package/dist/quaternion.d.ts +128 -0
- package/dist/quaternion.d.ts.map +1 -0
- package/dist/quaternion.js +508 -0
- package/dist/quaternion.js.map +1 -0
- package/dist/quaternionPool.d.ts +6 -0
- package/dist/quaternionPool.d.ts.map +1 -0
- package/dist/quaternionPool.js +29 -0
- package/dist/quaternionPool.js.map +1 -0
- package/dist/ray3d.d.ts +69 -0
- package/dist/ray3d.d.ts.map +1 -0
- package/dist/ray3d.js +264 -0
- package/dist/ray3d.js.map +1 -0
- package/dist/rectangle.d.ts +56 -0
- package/dist/rectangle.d.ts.map +1 -0
- package/dist/rectangle.js +235 -0
- package/dist/rectangle.js.map +1 -0
- package/dist/rectanglePool.d.ts +6 -0
- package/dist/rectanglePool.d.ts.map +1 -0
- package/dist/rectanglePool.js +29 -0
- package/dist/rectanglePool.js.map +1 -0
- package/dist/typedarray.d.ts +4 -0
- package/dist/typedarray.d.ts.map +1 -0
- package/dist/typedarray.js +25 -0
- package/dist/typedarray.js.map +1 -0
- package/dist/vector2.d.ts +130 -0
- package/dist/vector2.d.ts.map +1 -0
- package/dist/vector2.js +250 -0
- package/dist/vector2.js.map +1 -0
- package/dist/vector2Pool.d.ts +6 -0
- package/dist/vector2Pool.d.ts.map +1 -0
- package/dist/vector2Pool.js +20 -0
- package/dist/vector2Pool.js.map +1 -0
- package/dist/vector3.d.ts +220 -0
- package/dist/vector3.d.ts.map +1 -0
- package/dist/vector3.js +380 -0
- package/dist/vector3.js.map +1 -0
- package/dist/vector3Pool.d.ts +6 -0
- package/dist/vector3Pool.d.ts.map +1 -0
- package/dist/vector3Pool.js +28 -0
- package/dist/vector3Pool.js.map +1 -0
- package/dist/vector4.d.ts +180 -0
- package/dist/vector4.d.ts.map +1 -0
- package/dist/vector4.js +333 -0
- package/dist/vector4.js.map +1 -0
- package/dist/vector4Pool.d.ts +6 -0
- package/dist/vector4Pool.d.ts.map +1 -0
- package/dist/vector4Pool.js +29 -0
- package/dist/vector4Pool.js.map +1 -0
- package/package.json +38 -0
- package/src/aabb.test.ts +341 -0
- package/src/boundingSphere.test.ts +247 -0
- package/src/capsule.test.ts +157 -0
- package/src/frustum.test.ts +160 -0
- package/src/matrix.test.ts +1111 -0
- package/src/matrix3.test.ts +752 -0
- package/src/matrix3Pool.test.ts +73 -0
- package/src/matrix4.test.ts +1627 -0
- package/src/matrix4Pool.test.ts +71 -0
- package/src/matrixPool.test.ts +69 -0
- package/src/obb.test.ts +183 -0
- package/src/plane.test.ts +225 -0
- package/src/quaternion.test.ts +531 -0
- package/src/quaternionPool.test.ts +64 -0
- package/src/ray3d.test.ts +297 -0
- package/src/rectangle.test.ts +982 -0
- package/src/rectanglePool.test.ts +71 -0
- package/src/typedarray.test.ts +118 -0
- package/src/vector2.test.ts +958 -0
- package/src/vector2Pool.test.ts +65 -0
- package/src/vector3.test.ts +749 -0
- package/src/vector3Pool.test.ts +68 -0
- package/src/vector4.test.ts +660 -0
- package/src/vector4Pool.test.ts +71 -0
|
@@ -0,0 +1,752 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cloneMatrix3,
|
|
3
|
+
copyMatrix3,
|
|
4
|
+
copyMatrix3ColumnFromVector3,
|
|
5
|
+
copyMatrix3ColumnToVector3,
|
|
6
|
+
copyMatrix3RowFromVector3,
|
|
7
|
+
copyMatrix3RowToVector3,
|
|
8
|
+
createMatrix,
|
|
9
|
+
createMatrix3,
|
|
10
|
+
createMatrix4,
|
|
11
|
+
createVector3,
|
|
12
|
+
equalsMatrix3,
|
|
13
|
+
getMatrix3Determinant,
|
|
14
|
+
getMatrix3Element,
|
|
15
|
+
inverseMatrix3,
|
|
16
|
+
isAffineMatrix3,
|
|
17
|
+
multiplyMatrix3,
|
|
18
|
+
rotateMatrix3,
|
|
19
|
+
scaleMatrix3,
|
|
20
|
+
setMatrix3,
|
|
21
|
+
setMatrix3Element,
|
|
22
|
+
setMatrix3FromFloat32Array,
|
|
23
|
+
setMatrix3FromMatrix,
|
|
24
|
+
setMatrix3FromMatrix4,
|
|
25
|
+
setMatrix3Identity,
|
|
26
|
+
setMatrix3NormalFromMatrix4,
|
|
27
|
+
translateMatrix3,
|
|
28
|
+
transposeMatrix3,
|
|
29
|
+
writeMatrix3ToFloat32Array,
|
|
30
|
+
} from '@flighthq/geometry';
|
|
31
|
+
import type { Matrix3 } from '@flighthq/types';
|
|
32
|
+
|
|
33
|
+
describe('cloneMatrix3', () => {
|
|
34
|
+
it('should clone the matrix correctly', () => {
|
|
35
|
+
const m1 = createMatrix3(2, 3, 4, 5, 6, 7, 8, 9, 10);
|
|
36
|
+
const m2 = cloneMatrix3(m1);
|
|
37
|
+
expect(getMatrix3Element(m2, 0, 0)).toBe(2);
|
|
38
|
+
expect(getMatrix3Element(m2, 0, 1)).toBe(3);
|
|
39
|
+
expect(getMatrix3Element(m2, 0, 2)).toBe(4);
|
|
40
|
+
expect(getMatrix3Element(m2, 1, 0)).toBe(5);
|
|
41
|
+
expect(getMatrix3Element(m2, 1, 1)).toBe(6);
|
|
42
|
+
expect(getMatrix3Element(m2, 1, 2)).toBe(7);
|
|
43
|
+
expect(getMatrix3Element(m2, 2, 0)).toBe(8);
|
|
44
|
+
expect(getMatrix3Element(m2, 2, 1)).toBe(9);
|
|
45
|
+
expect(getMatrix3Element(m2, 2, 2)).toBe(10);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should also clone matrix-like objects', () => {
|
|
49
|
+
const obj = { m: new Float32Array([2, 3, 4, 5, 6, 7, 8, 9, 10]) };
|
|
50
|
+
const m2 = cloneMatrix3(obj);
|
|
51
|
+
expect(getMatrix3Element(m2, 0, 0)).toBe(2);
|
|
52
|
+
expect(getMatrix3Element(m2, 0, 1)).toBe(3);
|
|
53
|
+
expect(getMatrix3Element(m2, 0, 2)).toBe(4);
|
|
54
|
+
expect(getMatrix3Element(m2, 1, 0)).toBe(5);
|
|
55
|
+
expect(getMatrix3Element(m2, 1, 1)).toBe(6);
|
|
56
|
+
expect(getMatrix3Element(m2, 1, 2)).toBe(7);
|
|
57
|
+
expect(getMatrix3Element(m2, 2, 0)).toBe(8);
|
|
58
|
+
expect(getMatrix3Element(m2, 2, 1)).toBe(9);
|
|
59
|
+
expect(getMatrix3Element(m2, 2, 2)).toBe(10);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should return a matrix instance', () => {
|
|
63
|
+
const obj = { m: new Float32Array([2, 3, 4, 5, 6, 7, 8, 9, 10]) };
|
|
64
|
+
const m2: Matrix3 = cloneMatrix3(obj);
|
|
65
|
+
expect(m2).not.toBeNull();
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('copyMatrix3', () => {
|
|
70
|
+
it('should copy matrix values from another matrix', () => {
|
|
71
|
+
const m1 = createMatrix3(2, 3, 4, 5, 6, 7, 8, 9, 10);
|
|
72
|
+
const m2 = createMatrix3();
|
|
73
|
+
copyMatrix3(m2, m1);
|
|
74
|
+
expect(getMatrix3Element(m2, 0, 0)).toBe(2);
|
|
75
|
+
expect(getMatrix3Element(m2, 0, 1)).toBe(3);
|
|
76
|
+
expect(getMatrix3Element(m2, 0, 2)).toBe(4);
|
|
77
|
+
expect(getMatrix3Element(m2, 1, 0)).toBe(5);
|
|
78
|
+
expect(getMatrix3Element(m2, 1, 1)).toBe(6);
|
|
79
|
+
expect(getMatrix3Element(m2, 1, 2)).toBe(7);
|
|
80
|
+
expect(getMatrix3Element(m2, 2, 0)).toBe(8);
|
|
81
|
+
expect(getMatrix3Element(m2, 2, 1)).toBe(9);
|
|
82
|
+
expect(getMatrix3Element(m2, 2, 2)).toBe(10);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe('copyMatrix3ColumnFromVector3', () => {
|
|
87
|
+
it('should copy column from a Vector3 to a Matrix3', () => {
|
|
88
|
+
const m = createMatrix3();
|
|
89
|
+
const v = createVector3(1, 2, 3);
|
|
90
|
+
copyMatrix3ColumnFromVector3(m, 0, v); // column 0
|
|
91
|
+
expect(getMatrix3Element(m, 0, 0)).toBe(1);
|
|
92
|
+
expect(getMatrix3Element(m, 1, 0)).toBe(2);
|
|
93
|
+
expect(getMatrix3Element(m, 2, 0)).toBe(3);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should copy column 1 (c, d)', () => {
|
|
97
|
+
const m = createMatrix3();
|
|
98
|
+
const v = createVector3(3, 4, 5);
|
|
99
|
+
copyMatrix3ColumnFromVector3(m, 1, v);
|
|
100
|
+
expect(getMatrix3Element(m, 0, 1)).toBe(3);
|
|
101
|
+
expect(getMatrix3Element(m, 1, 1)).toBe(4);
|
|
102
|
+
expect(getMatrix3Element(m, 2, 1)).toBe(5);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should copy column 2 (tx, ty)', () => {
|
|
106
|
+
const m = createMatrix3();
|
|
107
|
+
const v = createVector3(5, 6, 7);
|
|
108
|
+
copyMatrix3ColumnFromVector3(m, 2, v);
|
|
109
|
+
expect(getMatrix3Element(m, 0, 2)).toBe(5);
|
|
110
|
+
expect(getMatrix3Element(m, 1, 2)).toBe(6);
|
|
111
|
+
expect(getMatrix3Element(m, 2, 2)).toBe(7);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('should throw when column is greater than 2', () => {
|
|
115
|
+
const m = createMatrix3();
|
|
116
|
+
const v = createVector3();
|
|
117
|
+
expect(() => copyMatrix3ColumnFromVector3(m, 3, v)).toThrow();
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
describe('copyMatrix3ColumnToVector3', () => {
|
|
122
|
+
it('should copy column to a Vector3 from a Matrix3', () => {
|
|
123
|
+
const m = createMatrix3(1, 2, 3, 4, 5, 6, 7, 8, 9);
|
|
124
|
+
const v = createVector3();
|
|
125
|
+
copyMatrix3ColumnToVector3(v, 0, m); // column 0
|
|
126
|
+
expect(v.x).toBe(1);
|
|
127
|
+
expect(v.y).toBe(4);
|
|
128
|
+
expect(v.z).toBe(7);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('should copy column 1 into Vector3', () => {
|
|
132
|
+
const m = createMatrix3(1, 2, 3, 4, 5, 6, 7, 8, 9);
|
|
133
|
+
const v = createVector3();
|
|
134
|
+
copyMatrix3ColumnToVector3(v, 1, m);
|
|
135
|
+
expect(v.x).toBe(2);
|
|
136
|
+
expect(v.y).toBe(5);
|
|
137
|
+
expect(v.z).toBe(8);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('should copy column 2 into Vector3', () => {
|
|
141
|
+
const m = createMatrix3(1, 2, 3, 4, 5, 6, 7, 8, 9);
|
|
142
|
+
const v = createVector3();
|
|
143
|
+
copyMatrix3ColumnToVector3(v, 2, m);
|
|
144
|
+
expect(v.x).toBe(3);
|
|
145
|
+
expect(v.y).toBe(6);
|
|
146
|
+
expect(v.z).toBe(9);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('should throw when column is greater than 2', () => {
|
|
150
|
+
const m = createMatrix3();
|
|
151
|
+
const v = createVector3();
|
|
152
|
+
expect(() => copyMatrix3ColumnToVector3(v, 3, m)).toThrow();
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('should allow matrix-like and vector-like objects', () => {
|
|
156
|
+
const m = { m: new Float32Array([1, 2, 3, 4, 5, 6, 7, 8, 9]) };
|
|
157
|
+
const v = { x: 0, y: 0, z: 0 };
|
|
158
|
+
copyMatrix3ColumnToVector3(v, 0, m); // column 0
|
|
159
|
+
expect(v.x).toBe(1);
|
|
160
|
+
expect(v.y).toBe(4);
|
|
161
|
+
expect(v.z).toBe(7);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
describe('copyMatrix3RowFromVector3', () => {
|
|
166
|
+
it('should copy row from a Vector3 to a Matrix3', () => {
|
|
167
|
+
const m = createMatrix3();
|
|
168
|
+
const v = createVector3(1, 2, 3);
|
|
169
|
+
copyMatrix3RowFromVector3(m, 0, v); // row 0
|
|
170
|
+
expect(getMatrix3Element(m, 0, 0)).toBe(1);
|
|
171
|
+
expect(getMatrix3Element(m, 0, 1)).toBe(2);
|
|
172
|
+
expect(getMatrix3Element(m, 0, 2)).toBe(3);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('should copy row 1 (b, d, ty)', () => {
|
|
176
|
+
const m = createMatrix3();
|
|
177
|
+
const v = createVector3(2, 4, 6);
|
|
178
|
+
copyMatrix3RowFromVector3(m, 1, v);
|
|
179
|
+
expect(getMatrix3Element(m, 1, 0)).toBe(2);
|
|
180
|
+
expect(getMatrix3Element(m, 1, 1)).toBe(4);
|
|
181
|
+
expect(getMatrix3Element(m, 1, 2)).toBe(6);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('should throw when row is greater than 2', () => {
|
|
185
|
+
const m = createMatrix3();
|
|
186
|
+
const v = createVector3();
|
|
187
|
+
expect(() => copyMatrix3RowFromVector3(m, 3, v)).toThrow();
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('should allow matrix-like and vector-like objects', () => {
|
|
191
|
+
const m = { m: new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]) };
|
|
192
|
+
const v = { x: 1, y: 2, z: 3 };
|
|
193
|
+
copyMatrix3RowFromVector3(m, 0, v); // row 0
|
|
194
|
+
expect(m.m[0]).toBe(1);
|
|
195
|
+
expect(m.m[1]).toBe(2);
|
|
196
|
+
expect(m.m[2]).toBe(3);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
describe('copyMatrix3RowToVector3', () => {
|
|
201
|
+
it('should copy row to a Vector3 from a Matrix3', () => {
|
|
202
|
+
const m = createMatrix3(1, 2, 3, 4, 5, 6, 7, 8, 9);
|
|
203
|
+
const v = createVector3();
|
|
204
|
+
copyMatrix3RowToVector3(v, 0, m); // row 0
|
|
205
|
+
expect(v.x).toBe(1); // m.a
|
|
206
|
+
expect(v.y).toBe(2); // m.c
|
|
207
|
+
expect(v.z).toBe(3); // m.tx
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('should copy row 1 (b, d, ty)', () => {
|
|
211
|
+
const m = createMatrix3(1, 2, 3, 4, 5, 6, 7, 8, 9);
|
|
212
|
+
const v = createVector3();
|
|
213
|
+
copyMatrix3RowToVector3(v, 1, m);
|
|
214
|
+
expect(v.x).toBe(4);
|
|
215
|
+
expect(v.y).toBe(5);
|
|
216
|
+
expect(v.z).toBe(6);
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it('should return (0, 0, 1) for row 2', () => {
|
|
220
|
+
const m = createMatrix3();
|
|
221
|
+
const v = createVector3();
|
|
222
|
+
copyMatrix3RowToVector3(v, 2, m);
|
|
223
|
+
expect(v.x).toBe(0);
|
|
224
|
+
expect(v.y).toBe(0);
|
|
225
|
+
expect(v.z).toBe(1);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('should allow matrix-like and vector-like objects', () => {
|
|
229
|
+
const m = { m: new Float32Array([1, 2, 3, 4, 5, 6, 7, 8, 9]) };
|
|
230
|
+
const v = { x: 0, y: 0, z: 0 };
|
|
231
|
+
copyMatrix3RowToVector3(v, 0, m); // row 0
|
|
232
|
+
expect(v.x).toBe(1); // m.a
|
|
233
|
+
expect(v.y).toBe(2); // m.c
|
|
234
|
+
expect(v.z).toBe(3); // m.tx
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
describe('createMatrix3', () => {
|
|
239
|
+
it('should initialize matrix with provided values', () => {
|
|
240
|
+
const m = createMatrix3(2, 3, 4, 5, 6, 7, 8, 9, 10);
|
|
241
|
+
expect(getMatrix3Element(m, 0, 0)).toBe(2);
|
|
242
|
+
expect(getMatrix3Element(m, 0, 1)).toBe(3);
|
|
243
|
+
expect(getMatrix3Element(m, 0, 2)).toBe(4);
|
|
244
|
+
expect(getMatrix3Element(m, 1, 0)).toBe(5);
|
|
245
|
+
expect(getMatrix3Element(m, 1, 1)).toBe(6);
|
|
246
|
+
expect(getMatrix3Element(m, 1, 2)).toBe(7);
|
|
247
|
+
expect(getMatrix3Element(m, 2, 0)).toBe(8);
|
|
248
|
+
expect(getMatrix3Element(m, 2, 1)).toBe(9);
|
|
249
|
+
expect(getMatrix3Element(m, 2, 2)).toBe(10);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it('should default to identity matrix when no values are provided', () => {
|
|
253
|
+
const m = createMatrix3();
|
|
254
|
+
expect(getMatrix3Element(m, 0, 0)).toBe(1);
|
|
255
|
+
expect(getMatrix3Element(m, 0, 1)).toBe(0);
|
|
256
|
+
expect(getMatrix3Element(m, 0, 2)).toBe(0);
|
|
257
|
+
expect(getMatrix3Element(m, 1, 0)).toBe(0);
|
|
258
|
+
expect(getMatrix3Element(m, 1, 1)).toBe(1);
|
|
259
|
+
expect(getMatrix3Element(m, 1, 2)).toBe(0);
|
|
260
|
+
expect(getMatrix3Element(m, 2, 0)).toBe(0);
|
|
261
|
+
expect(getMatrix3Element(m, 2, 1)).toBe(0);
|
|
262
|
+
expect(getMatrix3Element(m, 2, 2)).toBe(1);
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
describe('equalsMatrix3', () => {
|
|
267
|
+
it('should return false if one matrix is null and the other is not', () => {
|
|
268
|
+
const mat1 = createMatrix3();
|
|
269
|
+
expect(equalsMatrix3(mat1, null)).toBe(false);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('should return false if one matrix is undefined and the other is not', () => {
|
|
273
|
+
const mat1 = createMatrix3();
|
|
274
|
+
expect(equalsMatrix3(mat1, undefined)).toBe(false);
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it('should return true if both matrix objects are null', () => {
|
|
278
|
+
expect(equalsMatrix3(null, null)).toBe(true);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it('should return true if both matrix objects are undefined', () => {
|
|
282
|
+
expect(equalsMatrix3(undefined, undefined)).toBe(true);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it('should return true if one matrix object is undefined and the other is null', () => {
|
|
286
|
+
expect(equalsMatrix3(undefined, undefined)).toBe(true);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it('should return false if both matrix objects are defined and have different values', () => {
|
|
290
|
+
const mat1 = createMatrix3();
|
|
291
|
+
const mat2 = createMatrix3();
|
|
292
|
+
mat2.m[0] = 2;
|
|
293
|
+
expect(equalsMatrix3(mat1, mat2)).toBe(false);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it('should return true if one object is matrix-like and one is not', () => {
|
|
297
|
+
const mat1 = createMatrix3(1, 2, 3, 4, 5, 6, 7, 8, 9);
|
|
298
|
+
const mat2 = { m: new Float32Array([1, 2, 3, 4, 5, 6, 7, 8, 9]) };
|
|
299
|
+
expect(equalsMatrix3(mat1, mat2)).toBe(true);
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
it('should return true if both object are matrix-like', () => {
|
|
303
|
+
const mat1 = { m: new Float32Array([1, 2, 3, 4, 5, 6, 7, 8, 9]) };
|
|
304
|
+
const mat2 = { m: new Float32Array([1, 2, 3, 4, 5, 6, 7, 8, 9]) };
|
|
305
|
+
expect(equalsMatrix3(mat1, mat2)).toBe(true);
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
describe('getMatrix3Determinant', () => {
|
|
310
|
+
it('returns 1 for the identity matrix', () => {
|
|
311
|
+
expect(getMatrix3Determinant(createMatrix3())).toBeCloseTo(1, 6);
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it('returns 0 for a singular matrix', () => {
|
|
315
|
+
// Two identical rows → determinant = 0.
|
|
316
|
+
expect(getMatrix3Determinant(createMatrix3(1, 2, 3, 1, 2, 3, 4, 5, 6))).toBeCloseTo(0, 6);
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
it('returns a negative value when a row is negated (sign flip)', () => {
|
|
320
|
+
// Negate one row flips sign of det. Identity det = 1, negate row 0 → -1.
|
|
321
|
+
expect(getMatrix3Determinant(createMatrix3(-1, 0, 0, 0, 1, 0, 0, 0, 1))).toBeCloseTo(-1, 6);
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
describe('getMatrix3Element', () => {
|
|
326
|
+
it('returns the element at the given row and column', () => {
|
|
327
|
+
const m = createMatrix3(1, 2, 3, 4, 5, 6, 7, 8, 9);
|
|
328
|
+
expect(getMatrix3Element(m, 0, 0)).toBe(1);
|
|
329
|
+
expect(getMatrix3Element(m, 0, 1)).toBe(2);
|
|
330
|
+
expect(getMatrix3Element(m, 0, 2)).toBe(3);
|
|
331
|
+
expect(getMatrix3Element(m, 1, 0)).toBe(4);
|
|
332
|
+
expect(getMatrix3Element(m, 2, 2)).toBe(9);
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
describe('inverseMatrix3', () => {
|
|
337
|
+
it('should invert the matrix correctly', () => {
|
|
338
|
+
// Create a matrix with scaling of 2 and translation of (5, 3)
|
|
339
|
+
const m = createMatrix3(2, 0, 5, 0, 2, 3, 0, 0, 1);
|
|
340
|
+
|
|
341
|
+
// Apply inversion
|
|
342
|
+
let out = createMatrix3();
|
|
343
|
+
inverseMatrix3(out, m);
|
|
344
|
+
|
|
345
|
+
// Expected inverse matrix:
|
|
346
|
+
// Scaling should be 0.5 (inverse of 2)
|
|
347
|
+
// Translation should be -2.5 (inverse of 5 scaled by 0.5) and -1.5 (inverse of 3 scaled by 0.5)
|
|
348
|
+
|
|
349
|
+
// Assert the inverse matrix values
|
|
350
|
+
expect(out.m[0]).toBeCloseTo(0.5); // Inverse scaling on x
|
|
351
|
+
expect(out.m[1]).toBeCloseTo(0); // No shear on x
|
|
352
|
+
expect(out.m[3]).toBeCloseTo(0); // No shear on y
|
|
353
|
+
expect(out.m[4]).toBeCloseTo(0.5); // Inverse scaling on y
|
|
354
|
+
expect(out.m[2]).toBeCloseTo(-2.5); // Inverse translation on x
|
|
355
|
+
expect(out.m[5]).toBeCloseTo(-1.5); // Inverse translation on y
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
it('should not depend on initial out matrix values', () => {
|
|
359
|
+
const source = createMatrix3(2, 1, 5, 3, 4, 6, 0, 0, 1);
|
|
360
|
+
const out = createMatrix3(9, 9, 9, 9, 9, 9, 0, 0, 1);
|
|
361
|
+
|
|
362
|
+
inverseMatrix3(out, source);
|
|
363
|
+
|
|
364
|
+
const result = createMatrix3();
|
|
365
|
+
multiplyMatrix3(result, source, out);
|
|
366
|
+
|
|
367
|
+
expect(result.m[0]).toBeCloseTo(1);
|
|
368
|
+
expect(result.m[1]).toBeCloseTo(0);
|
|
369
|
+
expect(result.m[3]).toBeCloseTo(0);
|
|
370
|
+
expect(result.m[4]).toBeCloseTo(1);
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
it('should should allow matrix-like objects', () => {
|
|
374
|
+
const m = { m: new Float32Array([2, 0, 5, 0, 2, 3, 0, 0, 1]) };
|
|
375
|
+
let out = { m: new Float32Array([0, 0, 0, 0, 0, 0, 0, 0, 0]) };
|
|
376
|
+
inverseMatrix3(out, m);
|
|
377
|
+
expect(out.m[0]).toBeCloseTo(0.5); // Inverse scaling on x
|
|
378
|
+
expect(out.m[1]).toBeCloseTo(0); // No shear on x
|
|
379
|
+
expect(out.m[3]).toBeCloseTo(0); // No shear on y
|
|
380
|
+
expect(out.m[4]).toBeCloseTo(0.5); // Inverse scaling on y
|
|
381
|
+
expect(out.m[2]).toBeCloseTo(-2.5); // Inverse translation on x
|
|
382
|
+
expect(out.m[5]).toBeCloseTo(-1.5); // Inverse translation on y
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
it('supports out === source for affine matrices', () => {
|
|
386
|
+
const matrix = createMatrix3(2, 1, 5, 3, 4, 6, 0, 0, 1);
|
|
387
|
+
const expected = createMatrix3();
|
|
388
|
+
inverseMatrix3(expected, matrix);
|
|
389
|
+
|
|
390
|
+
inverseMatrix3(matrix, matrix);
|
|
391
|
+
|
|
392
|
+
expect(equalsMatrix3(matrix, expected)).toBe(true);
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
it('supports out === source for non-affine matrices', () => {
|
|
396
|
+
const matrix = createMatrix3(1, 2, 3, 0, 1, 4, 5, 6, 0);
|
|
397
|
+
const expected = createMatrix3();
|
|
398
|
+
inverseMatrix3(expected, matrix);
|
|
399
|
+
|
|
400
|
+
inverseMatrix3(matrix, matrix);
|
|
401
|
+
|
|
402
|
+
expect(equalsMatrix3(matrix, expected)).toBe(true);
|
|
403
|
+
});
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
describe('isAffineMatrix3', () => {
|
|
407
|
+
it('returns true for identity matrix', () => {
|
|
408
|
+
const m = createMatrix3();
|
|
409
|
+
expect(isAffineMatrix3(m)).toBe(true);
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
it('returns false when last row is not (0, 0, 1)', () => {
|
|
413
|
+
const m = createMatrix3(1, 0, 0, 0, 1, 0, 1, 0, 1);
|
|
414
|
+
expect(isAffineMatrix3(m)).toBe(false);
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
it('returns true for a matrix with translation', () => {
|
|
418
|
+
const m = createMatrix3(1, 0, 5, 0, 1, 10, 0, 0, 1);
|
|
419
|
+
expect(isAffineMatrix3(m)).toBe(true);
|
|
420
|
+
});
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
describe('multiplyMatrix3', () => {
|
|
424
|
+
it('should support out === a', () => {
|
|
425
|
+
const a = createMatrix3(2, 3, 4, 5, 7, 8, 0, 0, 1);
|
|
426
|
+
const b = createMatrix3(11, 13, 17, 19, 23, 29, 0, 0, 1);
|
|
427
|
+
const expected = createMatrix3();
|
|
428
|
+
multiplyMatrix3(expected, a, b);
|
|
429
|
+
|
|
430
|
+
multiplyMatrix3(a, a, b);
|
|
431
|
+
expect(equalsMatrix3(a, expected)).toBe(true);
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
it('should support out === b', () => {
|
|
435
|
+
const a = createMatrix3(2, 3, 4, 5, 7, 8, 0, 0, 1);
|
|
436
|
+
const b = createMatrix3(11, 13, 17, 19, 23, 29, 0, 0, 1);
|
|
437
|
+
const expected = createMatrix3();
|
|
438
|
+
multiplyMatrix3(expected, a, b);
|
|
439
|
+
|
|
440
|
+
multiplyMatrix3(b, a, b);
|
|
441
|
+
expect(equalsMatrix3(b, expected)).toBe(true);
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
it('should multiply identity correctly', () => {
|
|
445
|
+
const a = createMatrix3();
|
|
446
|
+
const b = createMatrix3(2, 3, 4, 5, 6, 7);
|
|
447
|
+
const out = createMatrix3();
|
|
448
|
+
multiplyMatrix3(out, a, b);
|
|
449
|
+
expect(equalsMatrix3(out, b)).toBe(true);
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
it('should allow matrix-like objects', () => {
|
|
453
|
+
const a = { m: new Float32Array([2, 0, 0, 0, 2, 0, 0, 0, 1]) };
|
|
454
|
+
const b = { m: new Float32Array([1, 0, 5, 0, 1, 5, 0, 0, 1]) };
|
|
455
|
+
multiplyMatrix3(a, a, b);
|
|
456
|
+
expect(a.m[2]).toBe(10);
|
|
457
|
+
expect(a.m[5]).toBe(10);
|
|
458
|
+
});
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
describe('rotateMatrix3', () => {
|
|
462
|
+
it('should rotate the matrix correctly', () => {
|
|
463
|
+
const m = createMatrix3(1, 0, 0, 0, 1, 0, 0, 0, 1);
|
|
464
|
+
const out = createMatrix3();
|
|
465
|
+
rotateMatrix3(out, m, Math.PI / 2); // 90 degrees
|
|
466
|
+
expect(out.m[0]).toBeCloseTo(0);
|
|
467
|
+
expect(out.m[1]).toBeCloseTo(-1);
|
|
468
|
+
expect(out.m[3]).toBeCloseTo(1);
|
|
469
|
+
expect(out.m[4]).toBeCloseTo(0);
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
it('should allow a matrix-like object', () => {
|
|
473
|
+
const m = { m: new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]) };
|
|
474
|
+
const out = { m: new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]) };
|
|
475
|
+
|
|
476
|
+
// Apply 90 degrees rotation (π/2 radians)
|
|
477
|
+
rotateMatrix3(out, m, Math.PI / 2);
|
|
478
|
+
|
|
479
|
+
// Check that the resulting matrix corresponds to a 90-degree rotation matrix
|
|
480
|
+
expect(out.m[0]).toBeCloseTo(0); // a = cos(π/2) = 0
|
|
481
|
+
expect(out.m[1]).toBeCloseTo(-1); // b = -sin(π/2) = -1
|
|
482
|
+
expect(out.m[3]).toBeCloseTo(1); // c = sin(π/2) = 1
|
|
483
|
+
expect(out.m[4]).toBeCloseTo(0); // d = cos(π/2) = 0
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
it('supports out === source', () => {
|
|
487
|
+
const matrix = createMatrix3(2, 3, 4, 5, 7, 8, 11, 13, 17);
|
|
488
|
+
const expected = createMatrix3();
|
|
489
|
+
rotateMatrix3(expected, matrix, Math.PI / 2);
|
|
490
|
+
|
|
491
|
+
rotateMatrix3(matrix, matrix, Math.PI / 2);
|
|
492
|
+
expect(equalsMatrix3(matrix, expected)).toBe(true);
|
|
493
|
+
});
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
describe('scaleMatrix3', () => {
|
|
497
|
+
it('should scale the matrix correctly', () => {
|
|
498
|
+
const m = createMatrix3();
|
|
499
|
+
const out = createMatrix3();
|
|
500
|
+
scaleMatrix3(out, m, 2, 3);
|
|
501
|
+
expect(out.m[0]).toBe(2);
|
|
502
|
+
expect(out.m[4]).toBe(3);
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
it('should allow a matrix-like object', () => {
|
|
506
|
+
const m = { m: new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]) };
|
|
507
|
+
const out = createMatrix3();
|
|
508
|
+
scaleMatrix3(out, m, 2, 3);
|
|
509
|
+
expect(out.m[0]).toBe(2); // a
|
|
510
|
+
expect(out.m[4]).toBe(3); // d
|
|
511
|
+
});
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
describe('setMatrix3', () => {
|
|
515
|
+
it('sets all 9 elements in row-major order', () => {
|
|
516
|
+
const m = createMatrix3();
|
|
517
|
+
setMatrix3(m, 1, 2, 3, 4, 5, 6, 7, 8, 9);
|
|
518
|
+
for (let row = 0; row < 3; row++) {
|
|
519
|
+
for (let col = 0; col < 3; col++) {
|
|
520
|
+
expect(getMatrix3Element(m, row, col)).toBe(row * 3 + col + 1);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
describe('setMatrix3Element', () => {
|
|
527
|
+
it('writes the value at the given row and column', () => {
|
|
528
|
+
const m = createMatrix3();
|
|
529
|
+
setMatrix3Element(m, 1, 2, 42);
|
|
530
|
+
expect(getMatrix3Element(m, 1, 2)).toBe(42);
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
it('does not affect other elements', () => {
|
|
534
|
+
const m = createMatrix3();
|
|
535
|
+
setMatrix3Element(m, 0, 1, 7);
|
|
536
|
+
expect(getMatrix3Element(m, 0, 0)).toBe(1);
|
|
537
|
+
expect(getMatrix3Element(m, 1, 1)).toBe(1);
|
|
538
|
+
});
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
describe('setMatrix3FromFloat32Array', () => {
|
|
542
|
+
it('reads 9 values starting at the given offset', () => {
|
|
543
|
+
const data = new Float32Array([99, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
|
544
|
+
const m = createMatrix3();
|
|
545
|
+
setMatrix3FromFloat32Array(m, 1, data);
|
|
546
|
+
expect(Array.from(m.m)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
it('defaults offset to 0', () => {
|
|
550
|
+
const data = new Float32Array([1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
|
551
|
+
const m = createMatrix3();
|
|
552
|
+
setMatrix3FromFloat32Array(m, 0, data);
|
|
553
|
+
expect(Array.from(m.m)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
|
554
|
+
});
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
describe('setMatrix3FromMatrix', () => {
|
|
558
|
+
it('should convert a Matrix3x2 to a Matrix3', () => {
|
|
559
|
+
// Define a matrix (6 values, row-major)
|
|
560
|
+
const mat2D = createMatrix();
|
|
561
|
+
|
|
562
|
+
// Define an empty Matrix3 to store the result
|
|
563
|
+
const mat = createMatrix3();
|
|
564
|
+
|
|
565
|
+
// Call the fromMatrix3x2 function
|
|
566
|
+
setMatrix3FromMatrix(mat, mat2D);
|
|
567
|
+
|
|
568
|
+
// Expected result: Identity matrix for Matrix3
|
|
569
|
+
const expectedMatrix3 = new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
|
|
570
|
+
|
|
571
|
+
// Assert that the result matches the expected outcome
|
|
572
|
+
expect(mat.m).toEqual(expectedMatrix3);
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
it('should handle scaling and translation', () => {
|
|
576
|
+
// Define a matrix with scaling and translation
|
|
577
|
+
const mat2D = createMatrix(2, 0, 0, 3, 5, 10); // Scaling by 2,3 and translation by (5,10)
|
|
578
|
+
|
|
579
|
+
// Define an empty Matrix3 to store the result
|
|
580
|
+
const mat = createMatrix3();
|
|
581
|
+
|
|
582
|
+
// Call the fromMatrix3x2 function
|
|
583
|
+
setMatrix3FromMatrix(mat, mat2D);
|
|
584
|
+
|
|
585
|
+
// Expected result: Scaling and translation in Matrix3
|
|
586
|
+
const expectedMatrix3 = new Float32Array([2, 0, 5, 0, 3, 10, 0, 0, 1]);
|
|
587
|
+
|
|
588
|
+
// Assert that the result matches the expected outcome
|
|
589
|
+
expect(mat.m).toEqual(expectedMatrix3);
|
|
590
|
+
});
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
describe('setMatrix3FromMatrix4', () => {
|
|
594
|
+
it('should convert an identity Matrix4x4 to a Matrix3', () => {
|
|
595
|
+
const Matrix4x4 = {
|
|
596
|
+
m: new Float32Array([
|
|
597
|
+
1,
|
|
598
|
+
0,
|
|
599
|
+
0,
|
|
600
|
+
0, // First column
|
|
601
|
+
0,
|
|
602
|
+
1,
|
|
603
|
+
0,
|
|
604
|
+
0, // Second column
|
|
605
|
+
0,
|
|
606
|
+
0,
|
|
607
|
+
1,
|
|
608
|
+
0, // Third column
|
|
609
|
+
3,
|
|
610
|
+
4,
|
|
611
|
+
5,
|
|
612
|
+
1, // Translation (m[12], m[13], m[14])
|
|
613
|
+
]),
|
|
614
|
+
};
|
|
615
|
+
|
|
616
|
+
const mat = createMatrix3();
|
|
617
|
+
setMatrix3FromMatrix4(mat, Matrix4x4);
|
|
618
|
+
|
|
619
|
+
// Expected result: Identity matrix for Matrix3
|
|
620
|
+
const expectedMatrix3 = new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
|
|
621
|
+
|
|
622
|
+
expect(mat.m).toEqual(expectedMatrix3);
|
|
623
|
+
});
|
|
624
|
+
|
|
625
|
+
it('should handle non-identity Matrix4x4 correctly', () => {
|
|
626
|
+
const Matrix4x4 = {
|
|
627
|
+
m: new Float32Array([
|
|
628
|
+
2,
|
|
629
|
+
0,
|
|
630
|
+
0,
|
|
631
|
+
0, // First column (scaling by 2)
|
|
632
|
+
0,
|
|
633
|
+
3,
|
|
634
|
+
0,
|
|
635
|
+
0, // Second column (scaling by 3)
|
|
636
|
+
0,
|
|
637
|
+
0,
|
|
638
|
+
4,
|
|
639
|
+
0, // Third column (scaling by 4)
|
|
640
|
+
5,
|
|
641
|
+
6,
|
|
642
|
+
7,
|
|
643
|
+
1, // Translation (m[12], m[13], m[14])
|
|
644
|
+
]),
|
|
645
|
+
};
|
|
646
|
+
|
|
647
|
+
const mat = createMatrix3();
|
|
648
|
+
setMatrix3FromMatrix4(mat, Matrix4x4);
|
|
649
|
+
|
|
650
|
+
// Expected result: Upper-left 3x3 part of Matrix4x4
|
|
651
|
+
const expectedMatrix3 = new Float32Array([2, 0, 0, 0, 3, 0, 0, 0, 4]);
|
|
652
|
+
|
|
653
|
+
expect(mat.m).toEqual(expectedMatrix3);
|
|
654
|
+
});
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
describe('setMatrix3Identity', () => {
|
|
658
|
+
it('resets a matrix to the identity', () => {
|
|
659
|
+
const m = createMatrix3(2, 3, 4, 5, 6, 7, 8, 9, 10);
|
|
660
|
+
setMatrix3Identity(m);
|
|
661
|
+
expect(getMatrix3Element(m, 0, 0)).toBe(1);
|
|
662
|
+
expect(getMatrix3Element(m, 1, 1)).toBe(1);
|
|
663
|
+
expect(getMatrix3Element(m, 2, 2)).toBe(1);
|
|
664
|
+
expect(getMatrix3Element(m, 0, 1)).toBe(0);
|
|
665
|
+
expect(getMatrix3Element(m, 1, 0)).toBe(0);
|
|
666
|
+
});
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
describe('setMatrix3NormalFromMatrix4', () => {
|
|
670
|
+
it('equals the rotation basis for an orthonormal matrix', () => {
|
|
671
|
+
// A 90-degree rotation about z (column-major Matrix4): +x -> +y.
|
|
672
|
+
const m4 = createMatrix4(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
|
673
|
+
const out = createMatrix3();
|
|
674
|
+
setMatrix3NormalFromMatrix4(out, m4);
|
|
675
|
+
// For a pure rotation, normal matrix == rotation. Row-major matrix3 of R (+x -> +y):
|
|
676
|
+
// [[0,-1,0],[1,0,0],[0,0,1]].
|
|
677
|
+
expect(out.m[0]).toBeCloseTo(0, 5);
|
|
678
|
+
expect(out.m[1]).toBeCloseTo(-1, 5);
|
|
679
|
+
expect(out.m[3]).toBeCloseTo(1, 5);
|
|
680
|
+
expect(out.m[4]).toBeCloseTo(0, 5);
|
|
681
|
+
expect(out.m[8]).toBeCloseTo(1, 5);
|
|
682
|
+
});
|
|
683
|
+
|
|
684
|
+
it('keeps a normal perpendicular under non-uniform scale', () => {
|
|
685
|
+
// Scale x by 2, y by 1: a surface normal (1,1,0) on a plane should stay perpendicular.
|
|
686
|
+
const m4 = createMatrix4(2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
|
687
|
+
const normalMatrix = createMatrix3();
|
|
688
|
+
setMatrix3NormalFromMatrix4(normalMatrix, m4);
|
|
689
|
+
// Inverse-transpose of diag(2,1,1) = diag(0.5,1,1).
|
|
690
|
+
expect(normalMatrix.m[0]).toBeCloseTo(0.5, 5);
|
|
691
|
+
expect(normalMatrix.m[4]).toBeCloseTo(1, 5);
|
|
692
|
+
expect(normalMatrix.m[8]).toBeCloseTo(1, 5);
|
|
693
|
+
});
|
|
694
|
+
});
|
|
695
|
+
|
|
696
|
+
describe('translateMatrix3', () => {
|
|
697
|
+
it('should translate the matrix correctly', () => {
|
|
698
|
+
const m = createMatrix3();
|
|
699
|
+
const out = createMatrix3();
|
|
700
|
+
translateMatrix3(out, m, 2, 3);
|
|
701
|
+
expect(out.m[2]).toBe(2);
|
|
702
|
+
expect(out.m[5]).toBe(3);
|
|
703
|
+
});
|
|
704
|
+
|
|
705
|
+
it('should allow a matrix-like object', () => {
|
|
706
|
+
const m = { m: new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]) };
|
|
707
|
+
const out = createMatrix3();
|
|
708
|
+
translateMatrix3(out, m, 2, 3);
|
|
709
|
+
expect(out.m[2]).toBe(2); // tx
|
|
710
|
+
expect(out.m[5]).toBe(3); // ty
|
|
711
|
+
});
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
describe('transposeMatrix3', () => {
|
|
715
|
+
it('swaps rows and columns', () => {
|
|
716
|
+
const m = createMatrix3(1, 2, 3, 4, 5, 6, 7, 8, 9);
|
|
717
|
+
const out = createMatrix3();
|
|
718
|
+
transposeMatrix3(out, m);
|
|
719
|
+
expect(Array.from(out.m)).toEqual([1, 4, 7, 2, 5, 8, 3, 6, 9]);
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
it('supports out === source', () => {
|
|
723
|
+
const m = createMatrix3(1, 2, 3, 4, 5, 6, 7, 8, 9);
|
|
724
|
+
transposeMatrix3(m, m);
|
|
725
|
+
expect(Array.from(m.m)).toEqual([1, 4, 7, 2, 5, 8, 3, 6, 9]);
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
it('transpose of identity is identity', () => {
|
|
729
|
+
const m = createMatrix3();
|
|
730
|
+
const out = createMatrix3();
|
|
731
|
+
transposeMatrix3(out, m);
|
|
732
|
+
expect(Array.from(out.m)).toEqual([1, 0, 0, 0, 1, 0, 0, 0, 1]);
|
|
733
|
+
});
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
describe('writeMatrix3ToFloat32Array', () => {
|
|
737
|
+
it('writes 9 values starting at the given offset', () => {
|
|
738
|
+
const m = createMatrix3(1, 2, 3, 4, 5, 6, 7, 8, 9);
|
|
739
|
+
const data = new Float32Array(10);
|
|
740
|
+
writeMatrix3ToFloat32Array(data, 1, m);
|
|
741
|
+
expect(Array.from(data)).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
|
742
|
+
});
|
|
743
|
+
|
|
744
|
+
it('round-trips through setMatrix3FromFloat32Array', () => {
|
|
745
|
+
const m = createMatrix3(9, 8, 7, 6, 5, 4, 3, 2, 1);
|
|
746
|
+
const data = new Float32Array(9);
|
|
747
|
+
writeMatrix3ToFloat32Array(data, 0, m);
|
|
748
|
+
const m2 = createMatrix3();
|
|
749
|
+
setMatrix3FromFloat32Array(m2, 0, data);
|
|
750
|
+
expect(equalsMatrix3(m2, m)).toBe(true);
|
|
751
|
+
});
|
|
752
|
+
});
|