Skip to main content

oxide_math/
transform.rs

1//! Transform types for positioning
2
3use glam::{Mat4, Quat, Vec3};
4
5#[derive(Clone, Copy, Debug)]
6pub struct Transform {
7    pub position: Vec3,
8    pub rotation: Quat,
9    pub scale: Vec3,
10}
11
12impl Default for Transform {
13    fn default() -> Self {
14        Self {
15            position: Vec3::ZERO,
16            rotation: Quat::IDENTITY,
17            scale: Vec3::ONE,
18        }
19    }
20}
21
22impl Transform {
23    pub fn new() -> Self {
24        Self::default()
25    }
26
27    pub fn from_position(position: Vec3) -> Self {
28        Self {
29            position,
30            ..Default::default()
31        }
32    }
33
34    pub fn look_at(&mut self, target: Vec3, up: Vec3) {
35        let forward = (target - self.position).normalize_or_zero();
36        if forward != Vec3::ZERO {
37            // Calculate a proper orientation using the provided `up` vector
38            let right = up.cross(forward).normalize_or_zero();
39            let new_up = forward.cross(right).normalize_or_zero();
40
41            if right != Vec3::ZERO && new_up != Vec3::ZERO {
42                let m = glam::Mat3::from_cols(right, new_up, forward);
43                self.rotation = Quat::from_mat3(&m);
44            } else {
45                // Fallback if looking directly along the up vector
46                self.rotation = Quat::from_rotation_arc(Vec3::NEG_Z, forward);
47            }
48        }
49    }
50
51    pub fn forward(&self) -> Vec3 {
52        self.rotation * Vec3::NEG_Z
53    }
54
55    pub fn right(&self) -> Vec3 {
56        self.rotation * Vec3::X
57    }
58
59    pub fn up(&self) -> Vec3 {
60        self.rotation * Vec3::Y
61    }
62
63    pub fn to_matrix(&self) -> Mat4 {
64        Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.position)
65    }
66}