@forgeax/engine-math 0.0.0-dev.8d955ade1c79

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 (150) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +294 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/__tests__/_arbs.d.ts +36 -0
  5. package/dist/__tests__/_arbs.d.ts.map +1 -0
  6. package/dist/__tests__/_fixtures.d.ts +61 -0
  7. package/dist/__tests__/_fixtures.d.ts.map +1 -0
  8. package/dist/__tests__/bounds2.test.d.ts +2 -0
  9. package/dist/__tests__/bounds2.test.d.ts.map +1 -0
  10. package/dist/__tests__/box3.test.d.ts +2 -0
  11. package/dist/__tests__/box3.test.d.ts.map +1 -0
  12. package/dist/__tests__/easing.test.d.ts +2 -0
  13. package/dist/__tests__/easing.test.d.ts.map +1 -0
  14. package/dist/__tests__/euler.test-d.d.ts +2 -0
  15. package/dist/__tests__/euler.test-d.d.ts.map +1 -0
  16. package/dist/__tests__/mat3.test-d.d.ts +2 -0
  17. package/dist/__tests__/mat3.test-d.d.ts.map +1 -0
  18. package/dist/__tests__/mat4.property.test.d.ts +2 -0
  19. package/dist/__tests__/mat4.property.test.d.ts.map +1 -0
  20. package/dist/__tests__/mat4.test-d.d.ts +2 -0
  21. package/dist/__tests__/mat4.test-d.d.ts.map +1 -0
  22. package/dist/__tests__/mat4.test.d.ts +2 -0
  23. package/dist/__tests__/mat4.test.d.ts.map +1 -0
  24. package/dist/__tests__/noise.test.d.ts +2 -0
  25. package/dist/__tests__/noise.test.d.ts.map +1 -0
  26. package/dist/__tests__/quat.basis.test.d.ts +2 -0
  27. package/dist/__tests__/quat.basis.test.d.ts.map +1 -0
  28. package/dist/__tests__/quat.interpolation.test.d.ts +2 -0
  29. package/dist/__tests__/quat.interpolation.test.d.ts.map +1 -0
  30. package/dist/__tests__/quat.lookat.test.d.ts +2 -0
  31. package/dist/__tests__/quat.lookat.test.d.ts.map +1 -0
  32. package/dist/__tests__/quat.property.test.d.ts +2 -0
  33. package/dist/__tests__/quat.property.test.d.ts.map +1 -0
  34. package/dist/__tests__/quat.rotateaxis.test.d.ts +2 -0
  35. package/dist/__tests__/quat.rotateaxis.test.d.ts.map +1 -0
  36. package/dist/__tests__/quat.test-d.d.ts +2 -0
  37. package/dist/__tests__/quat.test-d.d.ts.map +1 -0
  38. package/dist/__tests__/ray.property.test.d.ts +2 -0
  39. package/dist/__tests__/ray.property.test.d.ts.map +1 -0
  40. package/dist/__tests__/ray.test.d.ts +2 -0
  41. package/dist/__tests__/ray.test.d.ts.map +1 -0
  42. package/dist/__tests__/types.test-d.d.ts +2 -0
  43. package/dist/__tests__/types.test-d.d.ts.map +1 -0
  44. package/dist/__tests__/vec-catmull-rom.test.d.ts +2 -0
  45. package/dist/__tests__/vec-catmull-rom.test.d.ts.map +1 -0
  46. package/dist/__tests__/vec-smooth-damp.test.d.ts +2 -0
  47. package/dist/__tests__/vec-smooth-damp.test.d.ts.map +1 -0
  48. package/dist/__tests__/vec2.test-d.d.ts +2 -0
  49. package/dist/__tests__/vec2.test-d.d.ts.map +1 -0
  50. package/dist/__tests__/vec3.property.test.d.ts +2 -0
  51. package/dist/__tests__/vec3.property.test.d.ts.map +1 -0
  52. package/dist/__tests__/vec3.test-d.d.ts +2 -0
  53. package/dist/__tests__/vec3.test-d.d.ts.map +1 -0
  54. package/dist/__tests__/vec4.test-d.d.ts +2 -0
  55. package/dist/__tests__/vec4.test-d.d.ts.map +1 -0
  56. package/dist/_internal/epsilon.d.ts +9 -0
  57. package/dist/_internal/epsilon.d.ts.map +1 -0
  58. package/dist/_internal/scalar.d.ts +40 -0
  59. package/dist/_internal/scalar.d.ts.map +1 -0
  60. package/dist/box2.d.ts +35 -0
  61. package/dist/box2.d.ts.map +1 -0
  62. package/dist/box3.d.ts +76 -0
  63. package/dist/box3.d.ts.map +1 -0
  64. package/dist/circle2.d.ts +29 -0
  65. package/dist/circle2.d.ts.map +1 -0
  66. package/dist/color.d.ts +64 -0
  67. package/dist/color.d.ts.map +1 -0
  68. package/dist/easing.d.ts +18 -0
  69. package/dist/easing.d.ts.map +1 -0
  70. package/dist/euler.d.ts +51 -0
  71. package/dist/euler.d.ts.map +1 -0
  72. package/dist/f32-to-f16-bytes.d.ts +10 -0
  73. package/dist/f32-to-f16-bytes.d.ts.map +1 -0
  74. package/dist/frustum.d.ts +49 -0
  75. package/dist/frustum.d.ts.map +1 -0
  76. package/dist/index.d.ts +20 -0
  77. package/dist/index.d.ts.map +1 -0
  78. package/dist/index.mjs +3688 -0
  79. package/dist/index.mjs.map +1 -0
  80. package/dist/mat3.d.ts +70 -0
  81. package/dist/mat3.d.ts.map +1 -0
  82. package/dist/mat4.d.ts +329 -0
  83. package/dist/mat4.d.ts.map +1 -0
  84. package/dist/noise.d.ts +12 -0
  85. package/dist/noise.d.ts.map +1 -0
  86. package/dist/quat.d.ts +312 -0
  87. package/dist/quat.d.ts.map +1 -0
  88. package/dist/ray.d.ts +144 -0
  89. package/dist/ray.d.ts.map +1 -0
  90. package/dist/ray2.d.ts +38 -0
  91. package/dist/ray2.d.ts.map +1 -0
  92. package/dist/sphere.d.ts +41 -0
  93. package/dist/sphere.d.ts.map +1 -0
  94. package/dist/types.d.ts +57 -0
  95. package/dist/types.d.ts.map +1 -0
  96. package/dist/vec2.d.ts +76 -0
  97. package/dist/vec2.d.ts.map +1 -0
  98. package/dist/vec3.d.ts +82 -0
  99. package/dist/vec3.d.ts.map +1 -0
  100. package/dist/vec4.d.ts +61 -0
  101. package/dist/vec4.d.ts.map +1 -0
  102. package/package.json +57 -0
  103. package/src/__tests__/_arbs.ts +149 -0
  104. package/src/__tests__/_fixtures.ts +118 -0
  105. package/src/__tests__/bounds2.test.ts +146 -0
  106. package/src/__tests__/box3.test.ts +277 -0
  107. package/src/__tests__/easing.test.ts +109 -0
  108. package/src/__tests__/euler.test-d.ts +63 -0
  109. package/src/__tests__/mat3.test-d.ts +47 -0
  110. package/src/__tests__/mat4.property.test.ts +256 -0
  111. package/src/__tests__/mat4.test-d.ts +130 -0
  112. package/src/__tests__/mat4.test.ts +162 -0
  113. package/src/__tests__/noise.test.ts +75 -0
  114. package/src/__tests__/quat.basis.test.ts +134 -0
  115. package/src/__tests__/quat.interpolation.test.ts +45 -0
  116. package/src/__tests__/quat.lookat.test.ts +103 -0
  117. package/src/__tests__/quat.property.test.ts +150 -0
  118. package/src/__tests__/quat.rotateaxis.test.ts +149 -0
  119. package/src/__tests__/quat.test-d.ts +138 -0
  120. package/src/__tests__/ray.property.test.ts +105 -0
  121. package/src/__tests__/ray.test.ts +539 -0
  122. package/src/__tests__/types.test-d.ts +64 -0
  123. package/src/__tests__/vec-catmull-rom.test.ts +125 -0
  124. package/src/__tests__/vec-smooth-damp.test.ts +167 -0
  125. package/src/__tests__/vec2.test-d.ts +59 -0
  126. package/src/__tests__/vec3.property.test.ts +72 -0
  127. package/src/__tests__/vec3.test-d.ts +65 -0
  128. package/src/__tests__/vec4.test-d.ts +61 -0
  129. package/src/_internal/epsilon.ts +29 -0
  130. package/src/_internal/scalar.ts +90 -0
  131. package/src/box2.ts +168 -0
  132. package/src/box3.ts +372 -0
  133. package/src/circle2.ts +134 -0
  134. package/src/color.ts +177 -0
  135. package/src/easing.ts +49 -0
  136. package/src/euler.ts +239 -0
  137. package/src/f32-to-f16-bytes.ts +71 -0
  138. package/src/frustum.ts +240 -0
  139. package/src/index.ts +65 -0
  140. package/src/mat3.ts +286 -0
  141. package/src/mat4.ts +1334 -0
  142. package/src/noise.ts +78 -0
  143. package/src/quat.ts +847 -0
  144. package/src/ray.ts +575 -0
  145. package/src/ray2.ts +198 -0
  146. package/src/sphere.ts +138 -0
  147. package/src/types.ts +78 -0
  148. package/src/vec2.ts +229 -0
  149. package/src/vec3.ts +294 -0
  150. package/src/vec4.ts +235 -0
package/dist/quat.d.ts ADDED
@@ -0,0 +1,312 @@
1
+ import type { EulerOrder, Mat3Like, Quat, QuatLike, Vec3, Vec3Like } from './types';
2
+ export type { Quat, QuatLike };
3
+ /** Create a Quat (default all zero; callers usually call identity() right after). */
4
+ export declare function create(): Quat;
5
+ /** Allocate a new Quat copy. */
6
+ export declare function clone(a: QuatLike): Quat;
7
+ /** out = identity quaternion [0, 0, 0, 1]. Returns out. */
8
+ export declare function identity(out: Quat): Quat;
9
+ /**
10
+ * out = quaternion representing rotation by angleRadians around axis. Returns out.
11
+ *
12
+ * axis does not have to be pre-normalized; this function normalizes it internally.
13
+ *
14
+ * @degrade axis is the zero vector (lengthSq < EPS_NORMALIZE) → out = identity
15
+ * (no throw, registry #8).
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * quat.fromAxisAngle(out, [0, 1, 0], Math.PI / 2);
20
+ * // Guard: if (vec3.lengthSq(axis) < EPS_NORMALIZE) skip;
21
+ * ```
22
+ */
23
+ export declare function fromAxisAngle(out: Quat, axis: Vec3Like, angleRadians: number): Quat;
24
+ /**
25
+ * out = quaternion from intrinsic Euler angles (x, y, z, order). Returns out.
26
+ *
27
+ * Angle unit = **radians** (aligned with wgpu-matrix / Three.js; research §fact-correction 4
28
+ * deviates from gl-matrix's degrees).
29
+ * 6 orders: XYZ / YXZ / ZXY / ZYX / YZX / XZY (intrinsic rotation: literal order x → y → z).
30
+ * Implementation: split each axis rotation into single-axis quaternions, then Hamilton-multiply
31
+ * in `order`.
32
+ *
33
+ * @degrade order outside the EulerOrder union (only possible via `as any` cast) →
34
+ * **silently computes as if 'XYZ'** (D-P2 + AC-06 no throw; registry #9).
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * quat.fromEuler(out, 0.5, 0.3, 0.1, 'XYZ');
39
+ * quat.fromEuler(out, 0.5, 0.3, 0.1, 'unknown' as any); // silently computed as 'XYZ'
40
+ * // Guard: pass an EulerOrder union literal; the TS layer already blocks unknown strings.
41
+ * ```
42
+ */
43
+ export declare function fromEuler(out: Quat, x: number, y: number, z: number, order: EulerOrder): Quat;
44
+ /**
45
+ * out = quaternion from a 3x3 rotation matrix m (column-major, length 9). Returns out.
46
+ *
47
+ * Implementation: Shepperd's case-split (branch on trace / largest diagonal entry); numerically
48
+ * more stable than the direct trace method (avoids sqrt(0) when trace ≈ -1).
49
+ *
50
+ * Assumption: m is a pure rotation matrix (|det|=1, columns orthogonal). If not, the result is
51
+ * undefined but does not throw.
52
+ *
53
+ * @degrade m is not a pure rotation (contains shear / scale) → numerically undefined but does
54
+ * not throw (AC-06 no throw; callers should normalize column vectors first or avoid
55
+ * introducing non-pure-rotation matrices at the ECS-design layer).
56
+ *
57
+ * @example
58
+ * ```ts
59
+ * quat.fromRotationMatrix(out, mat3InstanceColumnMajor);
60
+ * ```
61
+ */
62
+ export declare function fromRotationMatrix(out: Quat, m: Mat3Like): Quat;
63
+ /**
64
+ * out = orientation quaternion for an object placed at `eye` and facing `target`. Returns out.
65
+ *
66
+ * This is the ergonomic camera/look-at helper: it yields the WORLD-space orientation an entity's
67
+ * Transform.rotation needs so that its local -z axis points from `eye` toward `target` (the camera
68
+ * convention, matching `mat4.lookAt`). Use it instead of hand-wiring
69
+ * `mat4.lookAt → mat4.invert → mat3.fromMat4 → quat.fromRotationMatrix`; that chain is easy to get
70
+ * wrong (notably `fromRotationMatrix` takes a mat3, but `Mat4Like`≡`Mat3Like`≡`ArrayLike<number>`,
71
+ * so passing a mat4 typechecks and silently reads garbage → NaN → nothing renders).
72
+ *
73
+ * Convenience composition (like `mat4.computeViewProj`), not a primitive: it builds the same
74
+ * right/newUp/forward basis as `mat4.lookAt` and reuses `fromRotationMatrix` for the extraction.
75
+ *
76
+ * @degrade eye ≈ target (|eye-target| < EPS_NORMALIZE) → out = identity (same convention as
77
+ * `mat4.lookAt` degenerate #4; no throw, AC-06).
78
+ * @degrade up collinear with the view direction → alternative up auto-selected (same as
79
+ * `mat4.lookAt` #5).
80
+ *
81
+ * @example
82
+ * ```ts
83
+ * // aim a camera at the origin
84
+ * const q = quat.fromLookAt(quat.create(), [-2.5, 4.5, 9], [0, 0, 0], [0, 1, 0]);
85
+ * world.set(cameraEntity, Transform, { pos: [-2.5, 4.5, 9], rot: q });
86
+ * ```
87
+ */
88
+ export declare function fromLookAt(out: Quat, eye: Vec3Like, target: Vec3Like, up: Vec3Like): Quat;
89
+ /**
90
+ * out = quaternion that rotates the unit vector v to w (shortest arc). Returns out.
91
+ *
92
+ * Assumes v and w are normalized; if not, the caller is responsible.
93
+ *
94
+ * @degrade v ≈ w (dot > 1 - EPS_QUAT_PARALLEL) → out = identity (registry #13).
95
+ * @degrade v ≈ -w (dot < -1 + EPS_QUAT_PARALLEL) → pick a perpendicular axis and do a 180°
96
+ * rotation (prefer (0,1,0); fall back to (1,0,0) when collinear with v;
97
+ * registry #12 + D-P18).
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * quat.fromUnitVectors(out, [1,0,0], [0,1,0]); // 90° around Z
102
+ * quat.fromUnitVectors(out, [1,0,0], [-1,0,0]); // 180° opposite: pick (0,1,0) axis
103
+ * ```
104
+ */
105
+ export declare function fromUnitVectors(out: Quat, v: Vec3Like, w: Vec3Like): Quat;
106
+ /**
107
+ * out = a * b (Hamilton product). Returns out.
108
+ *
109
+ * Aliasing-safe: reads all 8 source elements into locals first.
110
+ */
111
+ export declare function multiply(out: Quat, a: QuatLike, b: QuatLike): Quat;
112
+ /**
113
+ * out = the orientation `q` after rotating a further `angleRadians` about world-space `axis`,
114
+ * re-normalized. Returns out.
115
+ *
116
+ * This is the ergonomic *incremental rotate* helper — the per-frame spin/animation move. It folds
117
+ * the three steps every rotating demo otherwise hand-wires: build the delta quaternion
118
+ * (`fromAxisAngle`), **pre**-multiply it onto the current orientation (world-space axis, matching
119
+ * **Bevy `Transform::rotate(r)` = `r * self.rotation`** / `rotate_y(θ)`), and — the step that is
120
+ * silently omitted and makes the naive loop wrong — **normalize** to shed the floating-point error
121
+ * that accumulates over thousands of frames into a non-unit quaternion (skew / scale artefacts).
122
+ *
123
+ * Prefer this over hand-writing `quat.multiply(q, delta, q)` in an update system: that loop drifts,
124
+ * so demos work around it with an absolute-angle accumulator + `fromAxisAngle` (can't compose onto an
125
+ * existing orientation) or raw `sin/cos` quaternion literals. `rotateAxis` composes safely.
126
+ *
127
+ * Convenience composition (like `fromLookAt`), not a primitive: same result as
128
+ * `normalize(out, multiply(out, fromAxisAngle(tmp, axis, angleRadians), q))`, fused + aliasing-safe.
129
+ *
130
+ * @degrade `axis` zero-length → the delta is identity (degenerate registry #8), so out = normalize(q)
131
+ * (no rotation applied; no throw, consistent with the sibling helpers).
132
+ *
133
+ * @example
134
+ * ```ts
135
+ * // in an Update system: spin a cube about +Y at `speed` rad/s using the frame delta
136
+ * const dt = world.getResource(Time).delta;
137
+ * const t = world.get(entity, Transform).unwrap();
138
+ * quat.rotateAxis(t.quat, t.quat, [0, 1, 0], speed * dt); // in-place accumulate, no drift
139
+ * world.set(entity, Transform, t);
140
+ * ```
141
+ */
142
+ export declare function rotateAxis(out: Quat, q: QuatLike, axis: Vec3Like, angleRadians: number): Quat;
143
+ /**
144
+ * out = spherical linear interpolation(a, b, t). Returns out.
145
+ *
146
+ * t is not clamped (extrapolation semantics matches vec.lerp).
147
+ *
148
+ * @degrade dot(a, b) < -EPS_SLERP_DOT_LIMIT (anti-parallel) → **negate b' = -b then slerp**
149
+ * (D-P6; q and -q represent the same rotation; registry #10).
150
+ * @degrade |dot(a, b)| > 1 - EPS_SLERP_DOT_LIMIT (endpoint coincidence or near-coincidence) →
151
+ * falls back to nlerp (avoids acos blow-up; registry #11).
152
+ *
153
+ * @example
154
+ * ```ts
155
+ * quat.slerp(out, a, b, 0.5);
156
+ * // Anti-parallel (dot ≈ -1): caller does not need to pre-process; the negation fall-back
157
+ * // happens internally.
158
+ * ```
159
+ */
160
+ export declare function slerp(out: Quat, a: QuatLike, b: QuatLike, t: number): Quat;
161
+ /**
162
+ * out = normalized lerp(a, b, t). Returns out.
163
+ *
164
+ * Faster than slerp but the angular velocity is non-uniform; use it as a slerp substitute near endpoints.
165
+ * Like slerp, automatically handles dot < 0 by negating b to keep the shortest arc.
166
+ *
167
+ * @degrade lerp result is near zero (very rare) → out = identity.
168
+ *
169
+ * @example
170
+ * ```ts
171
+ * quat.nlerp(out, qA, qB, 0.5);
172
+ * // Very rare: lerp result lengthSq < EPS_NORMALIZE → out = (0, 0, 0, 1)
173
+ * ```
174
+ */
175
+ export declare function nlerp(out: Quat, a: QuatLike, b: QuatLike, t: number): Quat;
176
+ /**
177
+ * out = inverse of a (conjugate / lengthSq). Returns out.
178
+ *
179
+ * For unit quaternions, invert is equivalent to conjugate (and faster); this implementation uses
180
+ * the general a/|a|² form to support non-unit inputs.
181
+ *
182
+ * @degrade lengthSq(a) < EPS_NORMALIZE (zero quaternion) → out = identity (does not return NaN;
183
+ * same convention as mat invert).
184
+ *
185
+ * @example
186
+ * ```ts
187
+ * quat.invert(out, q);
188
+ * quat.invert(out, quat.create(0, 0, 0, 0)); // → out = identity (0, 0, 0, 1), AC-06 no throw
189
+ * ```
190
+ */
191
+ export declare function invert(out: Quat, a: QuatLike): Quat;
192
+ /** out = conjugate quaternion [-x, -y, -z, w] (aliasing-safe). Returns out. */
193
+ export declare function conjugate(out: Quat, a: QuatLike): Quat;
194
+ /** dot(a, b) = ax*bx + ay*by + az*bz + aw*bw (returns scalar). */
195
+ export declare function dot(a: QuatLike, b: QuatLike): number;
196
+ /** sqrt(x² + y² + z² + w²). Delegates to lengthSq + Math.sqrt (canonical pattern; see clone-5-quat-audit.md). */
197
+ export declare function length(a: QuatLike): number;
198
+ /** x² + y² + z² + w² (no sqrt). */
199
+ export declare function lengthSq(a: QuatLike): number;
200
+ /**
201
+ * out = q · v · q⁻¹ (rotate vec3 v by the unit quaternion q). Returns out.
202
+ *
203
+ * Rodrigues optimized form (research Finding 3, 18 mul + 12 add):
204
+ * t = 2 · cross(q.xyz, v)
205
+ * out = v + q.w · t + cross(q.xyz, t)
206
+ *
207
+ * 3-5× faster than going through mat4 (fromQuat → transformVec3); same shape as gl-matrix
208
+ * `vec3.transformQuat` / Three.js `Vector3.applyQuaternion` (industry consensus).
209
+ *
210
+ * Aliasing-safe: reads v.xyz / q.xyzw into locals before writing out.
211
+ *
212
+ * @degrade q must be a unit-length quaternion. A non-unit q introduces implicit scaling
213
+ * (D-4 silent convention; no throw; AI users always get unit-length q from
214
+ * quat.fromAxisAngle / fromEuler / normalize / slerp, so this branch is not hit).
215
+ * When q = (0,0,0,0), t = 0 → out = v (the natural result of the formula; matches
216
+ * gl-matrix / Three.js; non-NaN, no throw).
217
+ *
218
+ * @example
219
+ * ```ts
220
+ * const q = quat.fromAxisAngle(quat.create(), [0, 1, 0], Math.PI / 2);
221
+ * const out = vec3.create();
222
+ * quat.transformVec3(out, q, [1, 0, 0]); // → out ≈ (0, 0, -1)
223
+ * // Guard: q derived from the quat surface is always unit-length; callers do not need to normalize.
224
+ * ```
225
+ */
226
+ export declare function transformVec3(out: Vec3, q: QuatLike, v: Vec3Like): Vec3;
227
+ /**
228
+ * out = a / length(a). Returns out.
229
+ *
230
+ * @degrade lengthSq(a) < EPS_NORMALIZE → out = [0, 0, 0, 0] (same convention as vec.normalize;
231
+ * does not write identity, preserving the "zero quaternion" semantics; if the caller
232
+ * needs identity it should use fromAxisAngle with 0-axis).
233
+ *
234
+ * @example
235
+ * ```ts
236
+ * quat.normalize(out, q);
237
+ * quat.normalize(out, quat.create(0, 0, 0, 0)); // → out = (0, 0, 0, 0); zero-quaternion semantics preserved
238
+ * ```
239
+ */
240
+ export declare function normalize(out: Quat, a: QuatLike): Quat;
241
+ /**
242
+ * Convenience: quaternion representing rotation `theta` radians around the
243
+ * Y axis. Equivalent to `quat.fromEuler(out, 0, theta, 0, 'YXZ')` but
244
+ * allocates its own output `Quat`.
245
+ *
246
+ * Formula: `(0, sin(theta/2), 0, cos(theta/2))`.
247
+ *
248
+ * @degrade eulerY(0) → identity, eulerY(2pi) → identity within epsilon.
249
+ *
250
+ * @example
251
+ * ```ts
252
+ * const yaw45 = quat.eulerY(Math.PI / 4);
253
+ * // yaw45 ≈ [0, 0.3826834, 0, 0.9238795]
254
+ * ```
255
+ *
256
+ * @example Equivalent to the verbose form:
257
+ * ```ts
258
+ * const q1 = quat.eulerY(theta);
259
+ * const q2 = quat.fromEuler(quat.create(), 0, theta, 0, 'YXZ');
260
+ * // q1 === q2 (within epsilon)
261
+ * ```
262
+ */
263
+ export declare function eulerY(theta: number): Quat;
264
+ /**
265
+ * Local right axis: the world-space direction the rotation's own +X axis points.
266
+ * `right(out, q) = quat.transformVec3(out, q, [1, 0, 0])`. Mirrors
267
+ * `mat4.getRight`; matches Bevy `Transform::local_x` / `Transform::right`.
268
+ *
269
+ * @degrade q must be unit-length (guaranteed by the quat surface); a unit q
270
+ * yields a unit result. q = (0,0,0,0) → out = (1,0,0) (the natural
271
+ * transformVec3 result; non-NaN, no throw).
272
+ *
273
+ * @example
274
+ * ```ts
275
+ * const q = quat.eulerY(Math.PI / 2); // 90° about +Y
276
+ * quat.right(vec3.create(), q); // → (0, 0, -1): +X yawed a quarter-turn
277
+ * ```
278
+ */
279
+ export declare function right(out: Vec3, q: QuatLike): Vec3;
280
+ /**
281
+ * Local up axis: the world-space direction the rotation's own +Y axis points.
282
+ * `up(out, q) = quat.transformVec3(out, q, [0, 1, 0])`. Mirrors `mat4.getUp`;
283
+ * matches Bevy `Transform::local_y` / `Transform::up`.
284
+ *
285
+ * @degrade q must be unit-length (guaranteed by the quat surface); a unit q
286
+ * yields a unit result. q = (0,0,0,0) → out = (0,1,0).
287
+ *
288
+ * @example
289
+ * ```ts
290
+ * const q = quat.fromAxisAngle(quat.create(), [1, 0, 0], Math.PI / 2); // pitch 90°
291
+ * quat.up(vec3.create(), q); // → (0, 0, 1): +Y pitched onto +Z
292
+ * ```
293
+ */
294
+ export declare function up(out: Vec3, q: QuatLike): Vec3;
295
+ /**
296
+ * Local forward axis: the world-space direction the rotation's own −Z axis
297
+ * points (−Z look convention, RL-4). `forward(out, q) =
298
+ * quat.transformVec3(out, q, [0, 0, -1])`. Mirrors `mat4.getForward`; matches
299
+ * Bevy `Transform::forward` (Bevy also uses −Z). A quat from `fromLookAt(eye,
300
+ * target, up)` has `forward(q)` ≈ normalize(target − eye).
301
+ *
302
+ * @degrade q must be unit-length (guaranteed by the quat surface); a unit q
303
+ * yields a unit result. q = (0,0,0,0) → out = (0,0,-1).
304
+ *
305
+ * @example
306
+ * ```ts
307
+ * const q = quat.eulerY(Math.PI / 2); // 90° about +Y
308
+ * quat.forward(vec3.create(), q); // → (-1, 0, 0): -Z yawed a quarter-turn
309
+ * ```
310
+ */
311
+ export declare function forward(out: Vec3, q: QuatLike): Vec3;
312
+ //# sourceMappingURL=quat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quat.d.ts","sourceRoot":"","sources":["../src/quat.ts"],"names":[],"mappings":"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"}
package/dist/ray.d.ts ADDED
@@ -0,0 +1,144 @@
1
+ import type { Box3Like } from './box3';
2
+ import type { Mat4Like, Vec2, Vec3, Vec3Like } from './types';
3
+ /**
4
+ * Result of a ray-triangle intersection test (Moller-Trumbore).
5
+ * `t` = ray parameter, `u`/`v` = barycentric coordinates.
6
+ */
7
+ export interface RayTriResult {
8
+ hit: boolean;
9
+ t: number;
10
+ u: number;
11
+ v: number;
12
+ }
13
+ /**
14
+ * Ray storage: Float32Array length 6 [ox, oy, oz, dx, dy, dz], direction normalized.
15
+ * Local brand (not part of the seven-piece SSOT; same rationale as Box3).
16
+ */
17
+ export type Ray = Float32Array & {
18
+ readonly __ray: void;
19
+ };
20
+ /**
21
+ * Ray readable input: ArrayLike<number> of length 6 (ordering identical to Ray).
22
+ */
23
+ export type RayLike = ArrayLike<number>;
24
+ /**
25
+ * Create a Ray. Defaults to origin=(0,0,0), direction=(0,0,-1) normalized.
26
+ *
27
+ * When `out` is not provided, a new Float32Array is allocated.
28
+ * When `origin` / `direction` are provided, direction is normalized
29
+ * (zero-length direction falls back to (0,0,0) per gl-matrix style).
30
+ */
31
+ export declare function create(out?: Float32Array, origin?: Vec3Like, direction?: Vec3Like): Ray;
32
+ /**
33
+ * Copy the origin of `r` into `out`. Returns `out`.
34
+ */
35
+ export declare function getOrigin(out: Vec3, r: RayLike): Vec3;
36
+ /**
37
+ * Copy the direction of `r` into `out`. Returns `out`.
38
+ */
39
+ export declare function getDirection(out: Vec3, r: RayLike): Vec3;
40
+ /**
41
+ * Overwrite the origin of `r` with `o`. Returns `r`.
42
+ */
43
+ export declare function setOrigin(r: Ray, o: Vec3Like): Ray;
44
+ /**
45
+ * Overwrite the direction of `r` with `d` and normalize it.
46
+ * Zero-length direction falls back to (0,0,0) (gl-matrix style).
47
+ * Returns `r`.
48
+ */
49
+ export declare function setDirection(r: Ray, d: Vec3Like): Ray;
50
+ /**
51
+ * Result of a ray-AABB intersection test.
52
+ */
53
+ export interface RayAabbResult {
54
+ hit: boolean;
55
+ /** Entry distance along the ray (clamped to 0 when origin is inside the box). */
56
+ tmin: number;
57
+ }
58
+ /**
59
+ * Test whether a ray intersects an axis-aligned bounding box using the
60
+ * slab (Kay-Kajiya) method.
61
+ *
62
+ * Six degenerate cases per research Finding 2:
63
+ * 1. hit from outside → `tmin > 0`
64
+ * 2. hit from inside → `tmin = 0`
65
+ * 3. miss (ray away) → `hit = false`
66
+ * 4. parallel-axis miss → natural via ±Inf propagation
67
+ * 5. edge/corner NaN-safe → guard `t1 > t2` NaN scenarios with `Number.isNaN`
68
+ * 6. thin box (1D/2D) → correct via interval shrink
69
+ *
70
+ * Algorithm: precompute `inv = 1/D`, use `inv[i] < 0` (not direction[i] < 0)
71
+ * to handle `-0` direction correctly. On each axis compute `(min - O)*inv` and
72
+ * `(max - O)*inv`, swap when `inv < 0`, then accumulate `t_near = max(t_near, t1)`,
73
+ * `t_far = min(t_far, t2)`. Hit when `t_far >= max(t_near, 0)`.
74
+ *
75
+ * Input: `r` (Ray with normalized direction) + `aabb` (Box3Like, 6 floats).
76
+ * Output: `{ hit: boolean, tmin: number }`.
77
+ */
78
+ export declare function rayAabbIntersects(r: RayLike, aabb: Box3Like): RayAabbResult;
79
+ /**
80
+ * Project a screen-space coordinate into a world-space Ray.
81
+ *
82
+ * `screenX` / `screenY` are in pixels relative to the top-left corner of the viewport
83
+ * (DOM convention: y-down). They are clamped to `[0, vpWidth]` / `[0, vpHeight]` and
84
+ * sanitized against NaN/Inf.
85
+ *
86
+ * `kind` discriminates the projection type so callers can branch on the result if needed;
87
+ * both paths use the same two-point unproject algorithm.
88
+ *
89
+ * @param out The Ray to write into.
90
+ * @param screenX Horizontal pixel coordinate (y-down origin, top-left).
91
+ * @param screenY Vertical pixel coordinate.
92
+ * @param vpWidth Viewport width in pixels.
93
+ * @param vpHeight Viewport height in pixels.
94
+ * @param view Camera view matrix (world→eye).
95
+ * @param proj Camera projection matrix (eye→clip).
96
+ * @param kind `'perspective'` or `'orthographic'`.
97
+ * @returns `out` (same Ray instance).
98
+ */
99
+ export declare function screenToRay(out: Ray, screenX: number, screenY: number, vpWidth: number, vpHeight: number, view: Mat4Like, proj: Mat4Like, _kind: 'perspective' | 'orthographic'): Ray;
100
+ /** Result of projecting a world-space point to screen-space pixel coordinates. */
101
+ export interface WorldToScreenResult {
102
+ /** True if the NDC coordinates are within clip-space bounds. */
103
+ onScreen: boolean;
104
+ /** True if the original world-space point is behind the camera (w < 0).
105
+ * When true, `out` is meaningless (requirements §7). */
106
+ behind: boolean;
107
+ }
108
+ /**
109
+ * Project a world-space point to screen-space pixel coordinates.
110
+ *
111
+ * Performs a full mat4 * vec4 internally to capture the pre-divide `w` component
112
+ * (projectPoint discards `w`, so it cannot report `behind`).
113
+ *
114
+ * Pixel mapping: top-left origin, y-down (DOM convention).
115
+ * px = (ndc.x * 0.5 + 0.5) * canvasW
116
+ * py = (1 - (ndc.y * 0.5 + 0.5)) * canvasH
117
+ *
118
+ * Degenerate viewport (canvasW <= 0 || canvasH <= 0): returns { onScreen: false, behind: false },
119
+ * leaves `out` untouched.
120
+ *
121
+ * @param out Vec2 to write pixel coordinates into (y-down, top-left origin).
122
+ * @param worldPos World-space point (3 floats).
123
+ * @param viewProj Combined view-projection matrix (proj * view, 16 floats).
124
+ * @param canvasW Canvas width in pixels.
125
+ * @param canvasH Canvas height in pixels.
126
+ * @returns { onScreen: boolean, behind: boolean } — pure data flags, no allocation.
127
+ */
128
+ export declare function worldToScreen(out: Vec2, worldPos: Vec3Like, viewProj: Mat4Like, canvasW: number, canvasH: number): WorldToScreenResult;
129
+ /**
130
+ * Test whether a ray intersects a triangle using the Moller-Trumbore algorithm.
131
+ *
132
+ * Double-sided: both front and back faces are checked (abs(det) < epsilon).
133
+ * Degenerate triangles (collinear / zero-area) return hit=false.
134
+ * Ray origin behind the triangle (t <= 0) is rejected.
135
+ * NaN inputs are guarded against — any NaN input returns hit=false.
136
+ *
137
+ * @param r Ray (RayLike, 6 floats: ox,oy,oz,dx,dy,dz with normalized direction).
138
+ * @param a Triangle vertex A (Vec3Like, 3 floats).
139
+ * @param b Triangle vertex B (Vec3Like, 3 floats).
140
+ * @param c Triangle vertex C (Vec3Like, 3 floats).
141
+ * @returns RayTriResult with hit flag, t (ray parameter), and u/v (barycentric coordinates).
142
+ */
143
+ export declare function rayTriangleIntersects(r: RayLike, a: Vec3Like, b: Vec3Like, c: Vec3Like): RayTriResult;
144
+ //# sourceMappingURL=ray.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ray.d.ts","sourceRoot":"","sources":["../src/ray.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAEvC,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE9D;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,OAAO,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED;;;GAGG;AACH,MAAM,MAAM,GAAG,GAAG,YAAY,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAA;CAAE,CAAC;AAE1D;;GAEG;AACH,MAAM,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AAExC;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,GAAG,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,GAAG,CAgCvF;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,GAAG,IAAI,CAKrD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,GAAG,IAAI,CAKxD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,QAAQ,GAAG,GAAG,CAKlD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,QAAQ,GAAG,GAAG,CAgBrD;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,OAAO,CAAC;IACb,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,GAAG,aAAa,CAgE3E;AA0BD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,aAAa,GAAG,cAAc,GACpC,GAAG,CAoEL;AAaD,kFAAkF;AAClF,MAAM,WAAW,mBAAmB;IAClC,gEAAgE;IAChE,QAAQ,EAAE,OAAO,CAAC;IAClB;6DACyD;IACzD,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,IAAI,EACT,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,mBAAmB,CAkDrB;AAmBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CACnC,CAAC,EAAE,OAAO,EACV,CAAC,EAAE,QAAQ,EACX,CAAC,EAAE,QAAQ,EACX,CAAC,EAAE,QAAQ,GACV,YAAY,CAiFd"}
package/dist/ray2.d.ts ADDED
@@ -0,0 +1,38 @@
1
+ import type { Box2Like } from './box2';
2
+ import type { Circle2Like } from './circle2';
3
+ import type { Vec2, Vec2Like } from './types';
4
+ /** 2D ray storage: [originX, originY, directionX, directionY, maxDistance]. */
5
+ export type Ray2 = Float32Array & {
6
+ readonly __ray2: void;
7
+ };
8
+ /** Readable 2D ray input. */
9
+ export type Ray2Like = ArrayLike<number>;
10
+ /** Result shared by AABB, circle, and swept-volume intersection tests. */
11
+ export interface Ray2Intersection {
12
+ hit: boolean;
13
+ /** Entry distance along the normalized ray, clamped to zero when inside. */
14
+ t: number;
15
+ }
16
+ /** Create a normalized finite 2D ray. `maxDistance` defaults to infinity. */
17
+ export declare function create(out?: Float32Array, origin?: Vec2Like, direction?: Vec2Like, maxDistance?: number): Ray2;
18
+ /** Copy the ray origin to out. */
19
+ export declare function getOrigin(out: Vec2, ray: Ray2Like): Vec2;
20
+ /** Copy the normalized ray direction to out. */
21
+ export declare function getDirection(out: Vec2, ray: Ray2Like): Vec2;
22
+ /** Return the ray's finite travel limit. */
23
+ export declare function getMaxDistance(ray: Ray2Like): number;
24
+ /** Set the ray origin. */
25
+ export declare function setOrigin(ray: Ray2, origin: Vec2Like): Ray2;
26
+ /** Set and normalize the ray direction. */
27
+ export declare function setDirection(ray: Ray2, direction: Vec2Like): Ray2;
28
+ /** Set the ray's non-negative travel limit. */
29
+ export declare function setMaxDistance(ray: Ray2, maxDistance: number): Ray2;
30
+ /** Intersect a finite ray with an AABB using the 2D slab method. */
31
+ export declare function rayAabbIntersects(ray: Ray2Like, box: Box2Like): Ray2Intersection;
32
+ /** Intersect a finite ray with a bounding circle. */
33
+ export declare function rayCircleIntersects(ray: Ray2Like, circle: Circle2Like): Ray2Intersection;
34
+ /** Sweep an AABB along a finite ray and intersect it with a target AABB. */
35
+ export declare function aabbCastIntersects(ray: Ray2Like, moving: Box2Like, target: Box2Like): Ray2Intersection;
36
+ /** Sweep a circle along a finite ray and intersect it with a target circle. */
37
+ export declare function circleCastIntersects(ray: Ray2Like, moving: Circle2Like, target: Circle2Like): Ray2Intersection;
38
+ //# sourceMappingURL=ray2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ray2.d.ts","sourceRoot":"","sources":["../src/ray2.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE9C,+EAA+E;AAC/E,MAAM,MAAM,IAAI,GAAG,YAAY,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;CAAE,CAAC;AAE5D,6BAA6B;AAC7B,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AAEzC,0EAA0E;AAC1E,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,OAAO,CAAC;IACb,4EAA4E;IAC5E,CAAC,EAAE,MAAM,CAAC;CACX;AAED,6EAA6E;AAC7E,wBAAgB,MAAM,CACpB,GAAG,CAAC,EAAE,YAAY,EAClB,MAAM,CAAC,EAAE,QAAQ,EACjB,SAAS,CAAC,EAAE,QAAQ,EACpB,WAAW,SAA2B,GACrC,IAAI,CAiBN;AAED,kCAAkC;AAClC,wBAAgB,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI,CAIxD;AAED,gDAAgD;AAChD,wBAAgB,YAAY,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI,CAI3D;AAED,4CAA4C;AAC5C,wBAAgB,cAAc,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAEpD;AAED,0BAA0B;AAC1B,wBAAgB,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI,CAI3D;AAED,2CAA2C;AAC3C,wBAAgB,YAAY,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,GAAG,IAAI,CAajE;AAED,+CAA+C;AAC/C,wBAAgB,cAAc,CAAC,GAAG,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAGnE;AAED,oEAAoE;AACpE,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,GAAG,gBAAgB,CAEhF;AAED,qDAAqD;AACrD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,GAAG,gBAAgB,CAExF;AAED,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,QAAQ,EACb,MAAM,EAAE,QAAQ,EAChB,MAAM,EAAE,QAAQ,GACf,gBAAgB,CAUlB;AAED,+EAA+E;AAC/E,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,QAAQ,EACb,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,WAAW,GAClB,gBAAgB,CAOlB"}
@@ -0,0 +1,41 @@
1
+ import * as box3 from './box3';
2
+ import type { Vec3Like } from './types';
3
+ /**
4
+ * Sphere storage: Float32Array length 4 [cx, cy, cz, radius].
5
+ * Local brand (not part of the seven-piece SSOT); see box3.ts rationale.
6
+ */
7
+ export type Sphere = Float32Array & {
8
+ readonly __sphere: void;
9
+ };
10
+ /**
11
+ * Sphere readable input: ArrayLike<number> of length 4 (ordering identical to Sphere).
12
+ */
13
+ export type SphereLike = ArrayLike<number>;
14
+ /**
15
+ * Create a Sphere. Defaults to a zero-radius sphere at the origin.
16
+ */
17
+ export declare function create(cx?: number, cy?: number, cz?: number, radius?: number): Sphere;
18
+ /**
19
+ * Grow the sphere so `point` lies inside (boundary inclusive). Returns `out`.
20
+ *
21
+ * If the sphere was empty (radius < 0) the call re-seeds the center to `point`
22
+ * with radius 0. Otherwise the radius is set to max(current, distance(center, point)).
23
+ */
24
+ export declare function expandByPoint(out: Sphere, point: Vec3Like): Sphere;
25
+ /**
26
+ * True when `point` is inside `sphere` (boundary inclusive). Empty sphere
27
+ * (radius < 0) contains nothing.
28
+ */
29
+ export declare function containsPoint(s: SphereLike, point: Vec3Like): boolean;
30
+ /**
31
+ * True when `sphere` overlaps `box` (boundary inclusive). Uses the standard
32
+ * closest-point-on-AABB distance test.
33
+ */
34
+ export declare function intersectsBox(s: SphereLike, b: box3.Box3Like): boolean;
35
+ /**
36
+ * Build an enclosing sphere from `points` via AABB-center + max-distance
37
+ * approximation. Empty `points` leaves the negative-radius empty sphere at
38
+ * the origin.
39
+ */
40
+ export declare function fromPoints(out: Sphere, points: readonly Vec3Like[]): Sphere;
41
+ //# sourceMappingURL=sphere.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sphere.d.ts","sourceRoot":"","sources":["../src/sphere.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,IAAI,MAAM,QAAQ,CAAC;AAC/B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC;;;GAGG;AACH,MAAM,MAAM,MAAM,GAAG,YAAY,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAA;CAAE,CAAC;AAEhE;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AAE3C;;GAEG;AACH,wBAAgB,MAAM,CAAC,EAAE,SAAI,EAAE,EAAE,SAAI,EAAE,EAAE,SAAI,EAAE,MAAM,SAAI,GAAG,MAAM,CAEjE;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,MAAM,CAkBlE;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAOrE;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,IAAI,CAAC,QAAQ,GAAG,OAAO,CAmBtE;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,QAAQ,EAAE,GAAG,MAAM,CA6B3E"}
@@ -0,0 +1,57 @@
1
+ /** 2D vector storage: Float32Array length 2, brand=__vec2. */
2
+ export type Vec2 = Float32Array & {
3
+ readonly __vec2: void;
4
+ };
5
+ /** 3D vector storage: Float32Array length 3, brand=__vec3. */
6
+ export type Vec3 = Float32Array & {
7
+ readonly __vec3: void;
8
+ };
9
+ /** 4D vector / homogeneous coordinate storage: Float32Array length 4, brand=__vec4. */
10
+ export type Vec4 = Float32Array & {
11
+ readonly __vec4: void;
12
+ };
13
+ /** Quaternion storage: Float32Array length 4 [x,y,z,w], brand=__quat (mutually exclusive with Vec4). */
14
+ export type Quat = Float32Array & {
15
+ readonly __quat: void;
16
+ };
17
+ /** 3x3 matrix storage: Float32Array length 9 packed layout (D-P4); column-major (toGpuLayout hook reserved). */
18
+ export type Mat3 = Float32Array & {
19
+ readonly __mat3: void;
20
+ };
21
+ /** 4x4 matrix storage: Float32Array length 16 column-major, brand=__mat4. */
22
+ export type Mat4 = Float32Array & {
23
+ readonly __mat4: void;
24
+ };
25
+ /** Linear-space RGBA color: Float32Array length 4 [r,g,b,a] ∈ [0,1], brand=__color (mutually exclusive with Vec4). */
26
+ export type Color = Float32Array & {
27
+ readonly __color: void;
28
+ };
29
+ /** Euler angle: enum of six intrinsic rotation orders (D-P19). */
30
+ export type EulerOrder = 'XYZ' | 'YXZ' | 'ZXY' | 'ZYX' | 'YZX' | 'XZY';
31
+ /**
32
+ * Euler angle interface: x/y/z radians + order rotation order.
33
+ *
34
+ * Not a Float32Array because length=3 plus a string order needs plain-object storage;
35
+ * performance-insensitive (euler is only used at editor/IO boundary; runtime always converts to Quat).
36
+ */
37
+ export interface Euler {
38
+ x: number;
39
+ y: number;
40
+ z: number;
41
+ order: EulerOrder;
42
+ }
43
+ /** Vec2 readable input: ArrayLike<number> of length 2. */
44
+ export type Vec2Like = ArrayLike<number>;
45
+ /** Vec3 readable input: ArrayLike<number> of length 3. */
46
+ export type Vec3Like = ArrayLike<number>;
47
+ /** Vec4 readable input: ArrayLike<number> of length 4. */
48
+ export type Vec4Like = ArrayLike<number>;
49
+ /** Quat readable input: ArrayLike<number> of length 4. */
50
+ export type QuatLike = ArrayLike<number>;
51
+ /** Mat3 readable input: ArrayLike<number> of length 9. */
52
+ export type Mat3Like = ArrayLike<number>;
53
+ /** Mat4 readable input: ArrayLike<number> of length 16. */
54
+ export type Mat4Like = ArrayLike<number>;
55
+ /** Color readable input: ArrayLike<number> of length 4. */
56
+ export type ColorLike = ArrayLike<number>;
57
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAmBA,8DAA8D;AAC9D,MAAM,MAAM,IAAI,GAAG,YAAY,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;CAAE,CAAC;AAE5D,8DAA8D;AAC9D,MAAM,MAAM,IAAI,GAAG,YAAY,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;CAAE,CAAC;AAE5D,uFAAuF;AACvF,MAAM,MAAM,IAAI,GAAG,YAAY,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;CAAE,CAAC;AAE5D,wGAAwG;AACxG,MAAM,MAAM,IAAI,GAAG,YAAY,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;CAAE,CAAC;AAE5D,gHAAgH;AAChH,MAAM,MAAM,IAAI,GAAG,YAAY,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;CAAE,CAAC;AAE5D,6EAA6E;AAC7E,MAAM,MAAM,IAAI,GAAG,YAAY,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;CAAE,CAAC;AAE5D,sHAAsH;AACtH,MAAM,MAAM,KAAK,GAAG,YAAY,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAA;CAAE,CAAC;AAI9D,kEAAkE;AAClE,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAEvE;;;;;GAKG;AACH,MAAM,WAAW,KAAK;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,UAAU,CAAC;CACnB;AAQD,0DAA0D;AAC1D,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AACzC,0DAA0D;AAC1D,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AACzC,0DAA0D;AAC1D,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AACzC,0DAA0D;AAC1D,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AACzC,0DAA0D;AAC1D,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AACzC,2DAA2D;AAC3D,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AACzC,2DAA2D;AAC3D,MAAM,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC"}