@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,297 @@
1
+ import { createAabb } from './aabb';
2
+ import { createBoundingSphere } from './boundingSphere';
3
+ import { createPlane } from './plane';
4
+ import {
5
+ createRay3D,
6
+ getClosestPointBetweenRay3Ds,
7
+ getClosestPointOnRay3D,
8
+ getRay3DPointAt,
9
+ intersectRay3DAabb,
10
+ intersectRay3DPlane,
11
+ intersectRay3DSphere,
12
+ intersectRay3DTriangle,
13
+ setRay3D,
14
+ } from './ray3d';
15
+ import { createVector3 } from './vector3';
16
+
17
+ describe('createRay3D', () => {
18
+ it('creates a ray at the origin pointing in +Z by default', () => {
19
+ const ray = createRay3D();
20
+ expect(ray.origin.x).toBe(0);
21
+ expect(ray.origin.y).toBe(0);
22
+ expect(ray.origin.z).toBe(0);
23
+ expect(ray.direction.x).toBe(0);
24
+ expect(ray.direction.y).toBe(0);
25
+ expect(ray.direction.z).toBe(1);
26
+ });
27
+
28
+ it('creates a ray with explicit origin and direction', () => {
29
+ const ray = createRay3D(1, 2, 3, 0, 1, 0);
30
+ expect(ray.origin.x).toBe(1);
31
+ expect(ray.origin.y).toBe(2);
32
+ expect(ray.origin.z).toBe(3);
33
+ expect(ray.direction.x).toBe(0);
34
+ expect(ray.direction.y).toBe(1);
35
+ expect(ray.direction.z).toBe(0);
36
+ });
37
+ });
38
+
39
+ describe('getClosestPointBetweenRay3Ds', () => {
40
+ it('finds the closest points between two skew rays', () => {
41
+ // Ray a along +X at the origin; ray b along +Y crossing x=2 at z=1.
42
+ const a = createRay3D(0, 0, 0, 1, 0, 0);
43
+ const b = createRay3D(2, 0, 1, 0, 1, 0);
44
+ const pa = createVector3();
45
+ const pb = createVector3();
46
+ getClosestPointBetweenRay3Ds(pa, pb, a, b);
47
+ expect(pa.x).toBeCloseTo(2, 6);
48
+ expect(pa.y).toBeCloseTo(0, 6);
49
+ expect(pa.z).toBeCloseTo(0, 6);
50
+ expect(pb.x).toBeCloseTo(2, 6);
51
+ expect(pb.y).toBeCloseTo(0, 6);
52
+ expect(pb.z).toBeCloseTo(1, 6);
53
+ });
54
+
55
+ it('clamps to the origins when both rays point away from each other', () => {
56
+ const a = createRay3D(0, 0, 0, 1, 0, 0);
57
+ const b = createRay3D(-1, 1, 0, -1, 0, 0);
58
+ const pa = createVector3();
59
+ const pb = createVector3();
60
+ getClosestPointBetweenRay3Ds(pa, pb, a, b);
61
+ expect(pa.x).toBeCloseTo(0, 6);
62
+ expect(pa.y).toBeCloseTo(0, 6);
63
+ expect(pb.x).toBeCloseTo(-1, 6);
64
+ expect(pb.y).toBeCloseTo(1, 6);
65
+ });
66
+
67
+ it('handles parallel rays by anchoring on ray a', () => {
68
+ const a = createRay3D(0, 0, 0, 1, 0, 0);
69
+ const b = createRay3D(0, 2, 0, 1, 0, 0);
70
+ const pa = createVector3();
71
+ const pb = createVector3();
72
+ getClosestPointBetweenRay3Ds(pa, pb, a, b);
73
+ // Gap between the parallel rays is 2 along Y.
74
+ expect(Math.hypot(pa.x - pb.x, pa.y - pb.y, pa.z - pb.z)).toBeCloseTo(2, 6);
75
+ });
76
+ });
77
+
78
+ describe('getClosestPointOnRay3D', () => {
79
+ it('projects a point onto the ray', () => {
80
+ const ray = createRay3D(0, 0, 0, 1, 0, 0);
81
+ const out = createVector3();
82
+ getClosestPointOnRay3D(out, ray, createVector3(3, 4, 0));
83
+ expect(out.x).toBeCloseTo(3, 6);
84
+ expect(out.y).toBeCloseTo(0, 6);
85
+ expect(out.z).toBeCloseTo(0, 6);
86
+ });
87
+
88
+ it('clamps to the origin when the point projects behind it', () => {
89
+ const ray = createRay3D(0, 0, 0, 1, 0, 0);
90
+ const out = createVector3();
91
+ getClosestPointOnRay3D(out, ray, createVector3(-5, 2, 0));
92
+ expect(out.x).toBeCloseTo(0, 6);
93
+ expect(out.y).toBeCloseTo(0, 6);
94
+ expect(out.z).toBeCloseTo(0, 6);
95
+ });
96
+
97
+ it('works with a non-normalized direction', () => {
98
+ const ray = createRay3D(0, 0, 0, 2, 0, 0);
99
+ const out = createVector3();
100
+ getClosestPointOnRay3D(out, ray, createVector3(3, 7, 0));
101
+ expect(out.x).toBeCloseTo(3, 6);
102
+ expect(out.y).toBeCloseTo(0, 6);
103
+ });
104
+
105
+ it('supports out === point', () => {
106
+ const ray = createRay3D(0, 0, 0, 0, 1, 0);
107
+ const p = createVector3(5, 4, 1);
108
+ getClosestPointOnRay3D(p, ray, p);
109
+ expect(p.x).toBeCloseTo(0, 6);
110
+ expect(p.y).toBeCloseTo(4, 6);
111
+ expect(p.z).toBeCloseTo(0, 6);
112
+ });
113
+ });
114
+
115
+ describe('getRay3DPointAt', () => {
116
+ it('returns the origin when t=0', () => {
117
+ const ray = createRay3D(1, 2, 3, 0, 0, 1);
118
+ const out = createVector3();
119
+ getRay3DPointAt(out, ray, 0);
120
+ expect(out.x).toBe(1);
121
+ expect(out.y).toBe(2);
122
+ expect(out.z).toBe(3);
123
+ });
124
+
125
+ it('advances along the direction by t', () => {
126
+ const ray = createRay3D(0, 0, 0, 1, 0, 0);
127
+ const out = createVector3();
128
+ getRay3DPointAt(out, ray, 5);
129
+ expect(out.x).toBe(5);
130
+ expect(out.y).toBe(0);
131
+ expect(out.z).toBe(0);
132
+ });
133
+
134
+ it('is safe when out aliases ray.origin', () => {
135
+ const ray = createRay3D(1, 2, 3, 0, 1, 0);
136
+ getRay3DPointAt(ray.origin, ray, 3);
137
+ expect(ray.origin.x).toBe(1);
138
+ expect(ray.origin.y).toBe(5);
139
+ expect(ray.origin.z).toBe(3);
140
+ });
141
+ });
142
+
143
+ describe('intersectRay3DAabb', () => {
144
+ it('returns t=0 when the ray origin is inside the box', () => {
145
+ const ray = createRay3D(0, 0, 0, 0, 0, 1);
146
+ const aabb = createAabb(-1, -1, -1, 1, 1, 1);
147
+ expect(intersectRay3DAabb(ray, aabb)).toBe(0);
148
+ });
149
+
150
+ it('returns the entry t for a ray hitting the box from outside', () => {
151
+ const ray = createRay3D(0, 0, -5, 0, 0, 1);
152
+ const aabb = createAabb(-1, -1, -1, 1, 1, 1);
153
+ const t = intersectRay3DAabb(ray, aabb);
154
+ expect(t).toBeCloseTo(4);
155
+ });
156
+
157
+ it('returns -1 when the ray misses the box', () => {
158
+ const ray = createRay3D(5, 0, -5, 0, 0, 1);
159
+ const aabb = createAabb(-1, -1, -1, 1, 1, 1);
160
+ expect(intersectRay3DAabb(ray, aabb)).toBe(-1);
161
+ });
162
+
163
+ it('returns -1 when the ray points away from the box', () => {
164
+ const ray = createRay3D(0, 0, 5, 0, 0, 1);
165
+ const aabb = createAabb(-1, -1, -1, 1, 1, 1);
166
+ expect(intersectRay3DAabb(ray, aabb)).toBe(-1);
167
+ });
168
+
169
+ it('handles axis-aligned rays', () => {
170
+ const ray = createRay3D(-5, 0, 0, 1, 0, 0);
171
+ const aabb = createAabb(-1, -1, -1, 1, 1, 1);
172
+ const t = intersectRay3DAabb(ray, aabb);
173
+ expect(t).toBeCloseTo(4);
174
+ });
175
+ });
176
+
177
+ describe('intersectRay3DPlane', () => {
178
+ it('returns the t of a simple XY-plane intersection', () => {
179
+ // Plane z=0, i.e. 0x + 0y + 1z + 0 = 0
180
+ const plane = createPlane(0, 0, 1, 0);
181
+ const ray = createRay3D(0, 0, -3, 0, 0, 1);
182
+ expect(intersectRay3DPlane(ray, plane)).toBeCloseTo(3);
183
+ });
184
+
185
+ it('returns -1 when ray is parallel to the plane', () => {
186
+ const plane = createPlane(0, 0, 1, 0);
187
+ const ray = createRay3D(0, 0, 1, 1, 0, 0);
188
+ expect(intersectRay3DPlane(ray, plane)).toBe(-1);
189
+ });
190
+
191
+ it('returns -1 when intersection is behind the origin', () => {
192
+ const plane = createPlane(0, 0, 1, 0);
193
+ const ray = createRay3D(0, 0, 3, 0, 0, 1); // pointing away from z=0
194
+ expect(intersectRay3DPlane(ray, plane)).toBe(-1);
195
+ });
196
+ });
197
+
198
+ describe('intersectRay3DSphere', () => {
199
+ it('returns the near t for a ray hitting the sphere', () => {
200
+ const sphere = createBoundingSphere(0, 0, 0, 1);
201
+ const ray = createRay3D(0, 0, -5, 0, 0, 1);
202
+ const t = intersectRay3DSphere(ray, sphere);
203
+ expect(t).toBeCloseTo(4);
204
+ });
205
+
206
+ it('returns 0 when the ray origin is inside the sphere', () => {
207
+ const sphere = createBoundingSphere(0, 0, 0, 2);
208
+ const ray = createRay3D(0, 0, 0, 0, 0, 1);
209
+ expect(intersectRay3DSphere(ray, sphere)).toBe(0);
210
+ });
211
+
212
+ it('returns -1 when the ray misses the sphere', () => {
213
+ const sphere = createBoundingSphere(0, 0, 0, 1);
214
+ const ray = createRay3D(5, 0, -5, 0, 0, 1);
215
+ expect(intersectRay3DSphere(ray, sphere)).toBe(-1);
216
+ });
217
+
218
+ it('returns -1 for an empty sphere (radius < 0)', () => {
219
+ const sphere = createBoundingSphere(0, 0, 0, -1);
220
+ const ray = createRay3D(0, 0, -5, 0, 0, 1);
221
+ expect(intersectRay3DSphere(ray, sphere)).toBe(-1);
222
+ });
223
+ });
224
+
225
+ describe('intersectRay3DTriangle', () => {
226
+ const a = { x: -1, y: 0, z: 0 };
227
+ const b = { x: 1, y: 0, z: 0 };
228
+ const c = { x: 0, y: 1, z: 0 };
229
+
230
+ it('returns the t for a ray hitting the triangle', () => {
231
+ const ray = createRay3D(0, 0.3, -3, 0, 0, 1);
232
+ const t = intersectRay3DTriangle(ray, a, b, c);
233
+ expect(t).toBeCloseTo(3);
234
+ });
235
+
236
+ it('returns -1 when the ray misses the triangle', () => {
237
+ const ray = createRay3D(5, 5, -3, 0, 0, 1);
238
+ expect(intersectRay3DTriangle(ray, a, b, c)).toBe(-1);
239
+ });
240
+
241
+ it('returns -1 when the ray hits behind the origin', () => {
242
+ const ray = createRay3D(0, 0.3, 3, 0, 0, 1); // pointing away
243
+ expect(intersectRay3DTriangle(ray, a, b, c)).toBe(-1);
244
+ });
245
+
246
+ it('tests both sides of the triangle (no back-face culling)', () => {
247
+ // From behind the triangle
248
+ const ray = createRay3D(0, 0.3, 3, 0, 0, -1);
249
+ const t = intersectRay3DTriangle(ray, a, b, c);
250
+ expect(t).toBeCloseTo(3);
251
+ });
252
+
253
+ it('returns -1 for a degenerate (zero-area) triangle', () => {
254
+ const p = { x: 0, y: 0, z: 0 };
255
+ const ray = createRay3D(0, 0, -1, 0, 0, 1);
256
+ expect(intersectRay3DTriangle(ray, p, p, p)).toBe(-1);
257
+ });
258
+ });
259
+
260
+ describe('setRay3D', () => {
261
+ it('writes origin and direction into an existing ray', () => {
262
+ const ray = createRay3D();
263
+ const origin = { x: 4, y: 5, z: 6 };
264
+ const direction = { x: 0, y: 0, z: -1 };
265
+ setRay3D(ray, origin, direction);
266
+ expect(ray.origin.x).toBe(4);
267
+ expect(ray.origin.y).toBe(5);
268
+ expect(ray.origin.z).toBe(6);
269
+ expect(ray.direction.x).toBe(0);
270
+ expect(ray.direction.y).toBe(0);
271
+ expect(ray.direction.z).toBe(-1);
272
+ });
273
+
274
+ it('is safe when origin aliases the ray origin', () => {
275
+ const ray = createRay3D(1, 2, 3, 0, 1, 0);
276
+ const direction = { x: 1, y: 0, z: 0 };
277
+ setRay3D(ray, ray.origin, direction);
278
+ expect(ray.origin.x).toBe(1);
279
+ expect(ray.origin.y).toBe(2);
280
+ expect(ray.origin.z).toBe(3);
281
+ expect(ray.direction.x).toBe(1);
282
+ expect(ray.direction.y).toBe(0);
283
+ expect(ray.direction.z).toBe(0);
284
+ });
285
+
286
+ it('is safe when direction aliases the ray direction', () => {
287
+ const ray = createRay3D(0, 0, 0, 0, 1, 0);
288
+ const origin = { x: 5, y: 6, z: 7 };
289
+ setRay3D(ray, origin, ray.direction);
290
+ expect(ray.origin.x).toBe(5);
291
+ expect(ray.origin.y).toBe(6);
292
+ expect(ray.origin.z).toBe(7);
293
+ expect(ray.direction.x).toBe(0);
294
+ expect(ray.direction.y).toBe(1);
295
+ expect(ray.direction.z).toBe(0);
296
+ });
297
+ });