Skip to main content

classicube_sys\vectors\vec/
mod.rs

1mod ops;
2
3use crate::{
4    Vec3_IsZero, Vec3_Set,
5    bindings::{IVec3, Matrix, Vec3},
6    std_types::{c_float, cosf, floorf, sinf, sqrtf},
7};
8
9impl Vec3 {
10    #[must_use]
11    pub const fn new(x: c_float, y: c_float, z: c_float) -> Self {
12        Self { x, y, z }
13    }
14
15    #[must_use]
16    pub const fn zero() -> Self {
17        Self {
18            x: 0.0,
19            y: 0.0,
20            z: 0.0,
21        }
22    }
23
24    #[must_use]
25    pub const fn big_pos() -> Self {
26        Vec3_BigPos()
27    }
28
29    #[must_use]
30    pub const fn create(x: c_float, y: c_float, z: c_float) -> Self {
31        Vec3_Create3(x, y, z)
32    }
33
34    pub fn set(&mut self, x: c_float, y: c_float, z: c_float) {
35        Vec3_Set!(self, x, y, z);
36    }
37
38    #[must_use]
39    pub fn is_zero(&self) -> bool {
40        Vec3_IsZero!(self)
41    }
42
43    #[must_use]
44    pub fn length_squared(&self) -> c_float {
45        Vec3_LengthSquared(self)
46    }
47
48    #[must_use]
49    pub fn lerp(&self, b: Vec3, blend: c_float) -> Self {
50        let mut result = Self::zero();
51        Vec3_Lerp(&mut result, self, &b, blend);
52        result
53    }
54
55    #[must_use]
56    pub fn normalize(&self) -> Self {
57        let mut result = Self::zero();
58        Vec3_Normalize(&mut result, self);
59        result
60    }
61
62    #[must_use]
63    pub fn transform(&self, mat: Matrix) -> Self {
64        let mut result = Self::zero();
65        Vec3_Transform(&mut result, self, &mat);
66        result
67    }
68
69    #[must_use]
70    pub fn transform_y(y: c_float, mat: Matrix) -> Self {
71        let mut result = Self::zero();
72        Vec3_TransformY(&mut result, y, &mat);
73        result
74    }
75
76    #[must_use]
77    pub fn rotate_x(v: Vec3, angle: c_float) -> Self {
78        Vec3_RotateX(v, angle)
79    }
80
81    #[must_use]
82    pub fn rotate_y(v: Vec3, angle: c_float) -> Self {
83        Vec3_RotateY(v, angle)
84    }
85
86    #[must_use]
87    pub fn rotate_y3(x: c_float, y: c_float, z: c_float, angle: c_float) -> Self {
88        Vec3_RotateY3(x, y, z, angle)
89    }
90
91    #[must_use]
92    pub fn rotate_z(v: Vec3, angle: c_float) -> Self {
93        Vec3_RotateZ(v, angle)
94    }
95
96    #[must_use]
97    pub fn floor(&self) -> IVec3 {
98        let mut result = IVec3::zero();
99        IVec3_Floor(&mut result, self);
100        result
101    }
102
103    #[must_use]
104    pub fn get_dir_vector(yawRad: c_float, pitchRad: c_float) -> Self {
105        Vec3_GetDirVector(yawRad, pitchRad)
106    }
107}
108
109#[must_use]
110pub const fn Vec3_BigPos() -> Vec3 {
111    Vec3 {
112        x: 1e25_f32,
113        y: 1e25_f32,
114        z: 1e25_f32,
115    }
116}
117
118#[must_use]
119pub const fn Vec3_Create3(x: c_float, y: c_float, z: c_float) -> Vec3 {
120    Vec3 { x, y, z }
121}
122
123/// Returns the squared length of the vector.
124/// Squared length can be used for comparison, to avoid a costly `sqrt()`
125/// However, you must `sqrt()` this when adding lengths.
126#[must_use]
127pub fn Vec3_LengthSquared(v: &Vec3) -> c_float {
128    v.x * v.x + v.y * v.y + v.z * v.z
129}
130
131/// Linearly interpolates components of two vectors.
132pub fn Vec3_Lerp(result: &mut Vec3, a: &Vec3, b: &Vec3, blend: c_float) {
133    result.x = blend * (b.x - a.x) + a.x;
134    result.y = blend * (b.y - a.y) + a.y;
135    result.z = blend * (b.z - a.z) + a.z;
136}
137
138/// Scales all components of a vector to lie in [-1, 1]
139pub fn Vec3_Normalize(result: &mut Vec3, a: &Vec3) {
140    let lenSquared = a.x * a.x + a.y * a.y + a.z * a.z;
141    let scale = 1.0 / sqrtf(lenSquared);
142    result.x = a.x * scale;
143    result.y = a.y * scale;
144    result.z = a.z * scale;
145}
146
147/// Transforms a vector by the given matrix.
148pub fn Vec3_Transform(result: &mut Vec3, a: &Vec3, mat: &Matrix) {
149    // a could be pointing to result - can't directly assign x/y/z therefore
150    let x = a.x * mat.row1.x + a.y * mat.row2.x + a.z * mat.row3.x + mat.row4.x;
151    let y = a.x * mat.row1.y + a.y * mat.row2.y + a.z * mat.row3.y + mat.row4.y;
152    let z = a.x * mat.row1.z + a.y * mat.row2.z + a.z * mat.row3.z + mat.row4.z;
153    result.x = x;
154    result.y = y;
155    result.z = z;
156}
157
158/// Same as `Vec3_Transform`, but faster since x and z are assumed as 0.
159pub fn Vec3_TransformY(result: &mut Vec3, y: c_float, mat: &Matrix) {
160    result.x = y * mat.row2.x + mat.row4.x;
161    result.y = y * mat.row2.y + mat.row4.y;
162    result.z = y * mat.row2.z + mat.row4.z;
163}
164
165#[must_use]
166pub fn Vec3_RotateX(v: Vec3, angle: c_float) -> Vec3 {
167    let cosA = cosf(angle);
168    let sinA = sinf(angle);
169    Vec3_Create3(v.x, cosA * v.y + sinA * v.z, -sinA * v.y + cosA * v.z)
170}
171
172#[must_use]
173pub fn Vec3_RotateY(v: Vec3, angle: c_float) -> Vec3 {
174    let cosA = cosf(angle);
175    let sinA = sinf(angle);
176    Vec3_Create3(cosA * v.x - sinA * v.z, v.y, sinA * v.x + cosA * v.z)
177}
178
179#[must_use]
180pub fn Vec3_RotateY3(x: c_float, y: c_float, z: c_float, angle: c_float) -> Vec3 {
181    let cosA = cosf(angle);
182    let sinA = sinf(angle);
183    Vec3_Create3(cosA * x - sinA * z, y, sinA * x + cosA * z)
184}
185
186#[must_use]
187pub fn Vec3_RotateZ(v: Vec3, angle: c_float) -> Vec3 {
188    let cosA = cosf(angle);
189    let sinA = sinf(angle);
190    Vec3_Create3(cosA * v.x + sinA * v.y, -sinA * v.x + cosA * v.y, v.z)
191}
192
193/// Whether all of the components of the two vectors are equal.
194#[must_use]
195pub fn Vec3_Equals(a: &Vec3, b: &Vec3) -> bool {
196    #[allow(clippy::float_cmp)]
197    {
198        a.x == b.x && a.y == b.y && a.z == b.z
199    }
200}
201
202#[expect(
203    clippy::cast_possible_truncation,
204    reason = "floor result is intentionally narrowed to i32"
205)]
206pub fn IVec3_Floor(result: &mut IVec3, a: &Vec3) {
207    result.x = floorf(a.x) as _;
208    result.y = floorf(a.y) as _;
209    result.z = floorf(a.z) as _;
210}
211
212/// Returns a normalised vector facing in the direction described by the given yaw and pitch.
213#[must_use]
214pub fn Vec3_GetDirVector(yawRad: c_float, pitchRad: c_float) -> Vec3 {
215    let x = -cosf(pitchRad) * -sinf(yawRad);
216    let y = -sinf(pitchRad);
217    let z = -cosf(pitchRad) * cosf(yawRad);
218    Vec3_Create3(x, y, z)
219}