Skip to main content

mraphics_core/geometry/
instance.rs

1use crate::{
2    GeometryView, Material, MaterialView, MraphicsID,
3    constants::{MODEL_MAT_LABEL, PrimitiveTopology},
4};
5use nalgebra::{Isometry3, Matrix4, Translation3, UnitQuaternion, UnitVector3, Vector3};
6
7#[derive(Debug)]
8pub struct RenderInstance {
9    pub identifier: MraphicsID,
10    pub geometry: GeometryView,
11    pub material: MaterialView,
12
13    pub children: Vec<RenderInstance>,
14
15    pub visible: bool,
16    pub topology: PrimitiveTopology,
17
18    scale: Vector3<f32>,
19    isometry: Isometry3<f32>,
20    matrix: Matrix4<f32>,
21}
22
23impl RenderInstance {
24    pub fn new<M: Material>(identifier: MraphicsID, material: &M) -> Self {
25        Self {
26            identifier,
27            geometry: GeometryView::new(),
28            material: MaterialView::new(material.identifier())
29                .with_code(material.shader_code().to_string()),
30
31            children: Vec::new(),
32
33            visible: true,
34            topology: PrimitiveTopology::TriangleList,
35
36            scale: Vector3::new(1.0, 1.0, 1.0),
37            isometry: Isometry3::new(Vector3::zeros(), Vector3::zeros()),
38            matrix: Matrix4::identity(),
39        }
40    }
41
42    pub fn add_child(&mut self, child: RenderInstance) {
43        self.children.push(child);
44    }
45
46    pub fn remove_child(&mut self, identifier: MraphicsID) {
47        self.children.retain(|child| child.identifier != identifier);
48    }
49
50    pub fn matrix(&self) -> &Matrix4<f32> {
51        &self.matrix
52    }
53
54    pub fn rotation(&self) -> &UnitQuaternion<f32> {
55        &self.isometry.rotation
56    }
57
58    pub fn set_rotation(&mut self, rotation: &UnitQuaternion<f32>) {
59        self.isometry.rotation.clone_from(rotation);
60        self.update_matrix(None);
61    }
62
63    pub fn rotate_x(&mut self, angle_rad: f32) {
64        self.isometry.rotation =
65            UnitQuaternion::from_axis_angle(&UnitVector3::new_normalize(Vector3::x()), angle_rad)
66                * self.isometry.rotation;
67        self.update_matrix(None);
68    }
69
70    pub fn rotate_y(&mut self, angle_rad: f32) {
71        self.isometry.rotation =
72            UnitQuaternion::from_axis_angle(&UnitVector3::new_normalize(Vector3::y()), angle_rad)
73                * self.isometry.rotation;
74        self.update_matrix(None);
75    }
76
77    pub fn rotate_z(&mut self, angle_rad: f32) {
78        self.isometry.rotation =
79            UnitQuaternion::from_axis_angle(&UnitVector3::new_normalize(Vector3::z()), angle_rad)
80                * self.isometry.rotation;
81        self.update_matrix(None);
82    }
83
84    pub fn translation(&self) -> &Translation3<f32> {
85        &self.isometry.translation
86    }
87
88    pub fn move_to(&mut self, position: &Vector3<f32>) {
89        self.isometry.translation.vector = *position;
90        self.update_matrix(None);
91    }
92
93    pub fn move_by(&mut self, offset: &Vector3<f32>) {
94        self.isometry.translation.vector += offset;
95        self.update_matrix(None);
96    }
97
98    pub fn scale(&self) -> &Vector3<f32> {
99        &self.scale
100    }
101
102    pub fn scale_by(&mut self, factor: &Vector3<f32>) {
103        self.scale.component_mul_assign(factor);
104        self.update_matrix(None);
105    }
106
107    pub fn scale_to(&mut self, scale: &Vector3<f32>) {
108        self.scale.copy_from(scale);
109        self.update_matrix(None);
110    }
111
112    pub fn sync_matrix_data(&mut self) {
113        self.geometry
114            .set_uniform(
115                MODEL_MAT_LABEL,
116                bytemuck::cast_slice(self.matrix.as_slice()).to_vec(),
117            )
118            .unwrap();
119    }
120
121    fn update_matrix(&mut self, parent_matrix: Option<&Matrix4<f32>>) {
122        self.matrix = self.isometry.to_homogeneous() * Matrix4::new_nonuniform_scaling(&self.scale);
123
124        if let Some(matrix) = parent_matrix {
125            self.matrix = matrix * self.matrix;
126        }
127
128        self.sync_matrix_data();
129
130        for child in &mut self.children {
131            child.update_matrix(Some(&self.matrix));
132        }
133    }
134}
135
136pub trait InstanceUpdater {
137    fn update_instance(&self, instance: &mut RenderInstance);
138}