Skip to main content

token_value_map/math/
glam_impl.rs

1// AIDEV-NOTE: glam backend -- type aliases and utility functions.
2//
3// ZERO-COST: All utility functions have #[inline(always)] for complete inlining.
4
5pub type Vec2Impl = glam::Vec2;
6pub type Vec3Impl = glam::Vec3;
7pub type Mat3Impl = glam::Mat3;
8pub type Mat4Impl = glam::DMat4; // f64 version.
9
10// AIDEV-NOTE: glam has no separate Point3 type -- Vec3 serves as both.
11pub type Point3Impl = Vec3Impl;
12
13// --- Utility functions ---
14
15/// Create a zero `Vec2`.
16#[inline(always)]
17pub fn vec2_zeros() -> Vec2Impl {
18    Vec2Impl::ZERO
19}
20
21/// Create a zero `Vec3`.
22#[inline(always)]
23pub fn vec3_zeros() -> Vec3Impl {
24    Vec3Impl::ZERO
25}
26
27/// Get `Vec2` data as a `&[f32]` slice.
28#[inline(always)]
29pub fn vec2_as_slice(v: &Vec2Impl) -> &[f32] {
30    v.as_ref()
31}
32
33/// Get `Vec2` data as a `&[f32; 2]` ref.
34#[inline(always)]
35pub fn vec2_as_ref(v: &Vec2Impl) -> &[f32; 2] {
36    v.as_ref()
37}
38
39/// Get `Vec3` data as a `&[f32]` slice.
40#[inline(always)]
41pub fn vec3_as_slice(v: &Vec3Impl) -> &[f32] {
42    v.as_ref()
43}
44
45/// Get `Vec3` data as a `&[f32; 3]` ref.
46#[inline(always)]
47pub fn vec3_as_ref(v: &Vec3Impl) -> &[f32; 3] {
48    v.as_ref()
49}
50
51/// Return a normalized copy of a `Vec3`.
52#[inline(always)]
53pub fn vec3_normalized(v: &Vec3Impl) -> Vec3Impl {
54    v.normalize()
55}
56
57/// Create a `Mat3` from a row-major slice.
58#[inline(always)]
59pub fn mat3_from_row_slice(data: &[f32]) -> Mat3Impl {
60    assert_eq!(data.len(), 9, "Matrix3 requires exactly 9 elements");
61    // glam stores column-major, so transpose from row-major input.
62    Mat3Impl::from_cols_array(&[
63        data[0], data[3], data[6], // Column 0.
64        data[1], data[4], data[7], // Column 1.
65        data[2], data[5], data[8], // Column 2.
66    ])
67}
68
69/// Create a `Mat3` from a column-major slice.
70#[inline(always)]
71pub fn mat3_from_column_slice(data: &[f32]) -> Mat3Impl {
72    assert_eq!(data.len(), 9, "Matrix3 requires exactly 9 elements");
73    // SAFETY: assert_eq!(data.len(), 9) above guarantees the slice is exactly 9 elements.
74    Mat3Impl::from_cols_array(data.try_into().unwrap())
75}
76
77/// Return a zero `Mat3`.
78#[inline(always)]
79pub fn mat3_zeros() -> Mat3Impl {
80    Mat3Impl::ZERO
81}
82
83/// Get `Mat3` data as a `&[f32]` slice (column-major order).
84#[inline(always)]
85pub fn mat3_as_slice(m: &Mat3Impl) -> &[f32] {
86    m.as_ref()
87}
88
89/// Iterate over `Mat3` elements (column-major order).
90#[inline(always)]
91pub fn mat3_iter(m: &Mat3Impl) -> impl Iterator<Item = &f32> {
92    m.as_ref().iter()
93}
94
95/// Extract a row from a `Mat3` as `[f32; 3]`.
96#[inline(always)]
97pub fn mat3_row(m: &Mat3Impl, i: usize) -> [f32; 3] {
98    // glam stores column-major: col[c][r].
99    let cols: &[f32; 9] = m.as_ref();
100    [cols[i], cols[i + 3], cols[i + 6]]
101}
102
103/// Create a `DMat4` from a row-major slice.
104#[inline(always)]
105pub fn mat4_from_row_slice(data: &[f64]) -> Mat4Impl {
106    assert_eq!(data.len(), 16, "Matrix4 requires exactly 16 elements");
107    Mat4Impl::from_cols_array(&[
108        data[0], data[4], data[8], data[12], // Column 0.
109        data[1], data[5], data[9], data[13], // Column 1.
110        data[2], data[6], data[10], data[14], // Column 2.
111        data[3], data[7], data[11], data[15], // Column 3.
112    ])
113}
114
115/// Subtract two `DMat4` matrices element-wise.
116#[inline(always)]
117pub fn mat4_sub(a: Mat4Impl, b: Mat4Impl) -> Mat4Impl {
118    a - b
119}
120
121/// Return a zero `DMat4`.
122#[inline(always)]
123pub fn mat4_zeros() -> Mat4Impl {
124    Mat4Impl::ZERO
125}
126
127/// Iterate over `DMat4` elements (column-major order).
128#[inline(always)]
129pub fn mat4_iter(m: &Mat4Impl) -> impl Iterator<Item = &f64> {
130    m.as_ref().iter()
131}
132
133/// Return `DMat4` data as a `&[f64]` slice.
134#[inline(always)]
135pub fn mat4_as_slice(m: &Mat4Impl) -> &[f64] {
136    m.as_ref()
137}
138
139/// Return the origin point (zero vector).
140#[inline(always)]
141pub fn point3_origin() -> Point3Impl {
142    Vec3Impl::ZERO
143}
144
145/// Get point coordinates as a slice.
146#[inline(always)]
147pub fn point3_as_slice(p: &Point3Impl) -> &[f32] {
148    p.as_ref()
149}
150
151/// Get point coordinates as a `&[f32; 3]` ref.
152#[inline(always)]
153pub fn point3_as_ref(p: &Point3Impl) -> &[f32; 3] {
154    p.as_ref()
155}
156
157/// Return the identity `Mat3`.
158#[inline(always)]
159pub fn mat3_identity() -> Mat3Impl {
160    Mat3Impl::IDENTITY
161}
162
163/// Return the identity `DMat4`.
164#[inline(always)]
165pub fn mat4_identity() -> Mat4Impl {
166    Mat4Impl::IDENTITY
167}
168
169/// Get element at `(row, col)` from a `Mat3`.
170#[inline(always)]
171pub fn mat3(m: &Mat3Impl, row: usize, col: usize) -> f32 {
172    // glam stores column-major.
173    m.col(col)[row]
174}
175
176/// Get element at `(row, col)` from a `DMat4`.
177#[inline(always)]
178pub fn mat4(m: &Mat4Impl, row: usize, col: usize) -> f64 {
179    // glam stores column-major.
180    m.col(col)[row]
181}
182
183/// Subtract two `Mat3` matrices element-wise.
184#[inline(always)]
185pub fn mat3_sub(a: Mat3Impl, b: Mat3Impl) -> Mat3Impl {
186    a - b
187}
188
189/// Create a diagonal `Mat3` with `v` on the diagonal.
190#[inline(always)]
191pub fn mat3_from_diagonal_element(v: f32) -> Mat3Impl {
192    Mat3Impl::from_diagonal(glam::Vec3::splat(v))
193}