mraphics_core/geometry/
instance.rs

1use crate::{
2    GadgetData, GeometryView, Material, MaterialView,
3    constants::{MODEL_MAT_INDEX, MODEL_MAT_LABEL},
4};
5use nalgebra::{Isometry3, Matrix4, Translation3, UnitQuaternion, UnitVector3, Vector3};
6
7pub struct RenderInstance {
8    pub identifier: String,
9    pub geometry: GeometryView,
10    pub material: MaterialView,
11
12    scale: Vector3<f32>,
13    isometry: Isometry3<f32>,
14    matrix: Matrix4<f32>,
15}
16
17impl RenderInstance {
18    pub fn new<M: Material>(identifier: String, material: &M) -> Self {
19        Self {
20            identifier,
21            geometry: GeometryView::new(),
22            material: MaterialView::new(material.identifier())
23                .with_code(material.shader_code().to_string()),
24            scale: Vector3::new(1.0, 1.0, 1.0),
25            isometry: Isometry3::new(Vector3::zeros(), Vector3::zeros()),
26            matrix: Matrix4::identity(),
27        }
28    }
29
30    pub fn matrix(&self) -> &Matrix4<f32> {
31        &self.matrix
32    }
33
34    pub fn rotation(&self) -> &UnitQuaternion<f32> {
35        &self.isometry.rotation
36    }
37
38    pub fn set_rotation(&mut self, rotation: &UnitQuaternion<f32>) {
39        self.isometry.rotation.clone_from(rotation);
40        self.update_matrix();
41    }
42
43    pub fn rotate_x(&mut self, angle_rad: f32) {
44        self.isometry.rotation =
45            UnitQuaternion::from_axis_angle(&UnitVector3::new_normalize(Vector3::x()), angle_rad)
46                * self.isometry.rotation;
47        self.update_matrix();
48    }
49
50    pub fn rotate_y(&mut self, angle_rad: f32) {
51        self.isometry.rotation =
52            UnitQuaternion::from_axis_angle(&UnitVector3::new_normalize(Vector3::y()), angle_rad)
53                * self.isometry.rotation;
54        self.update_matrix();
55    }
56
57    pub fn rotate_z(&mut self, angle_rad: f32) {
58        self.isometry.rotation =
59            UnitQuaternion::from_axis_angle(&UnitVector3::new_normalize(Vector3::z()), angle_rad)
60                * self.isometry.rotation;
61        self.update_matrix();
62    }
63
64    pub fn translation(&self) -> &Translation3<f32> {
65        &self.isometry.translation
66    }
67
68    pub fn move_to(&mut self, position: &Vector3<f32>) {
69        self.isometry.translation.vector = *position;
70        self.update_matrix();
71    }
72
73    pub fn move_by(&mut self, offset: &Vector3<f32>) {
74        self.isometry.translation.vector += offset;
75        self.update_matrix();
76    }
77
78    pub fn scale(&self) -> &Vector3<f32> {
79        &self.scale
80    }
81
82    pub fn scale_by(&mut self, factor: &Vector3<f32>) {
83        self.scale.component_mul_assign(factor);
84        self.update_matrix();
85    }
86
87    pub fn scale_to(&mut self, scale: &Vector3<f32>) {
88        self.scale.copy_from(scale);
89        self.update_matrix();
90    }
91
92    fn update_matrix(&mut self) {
93        self.matrix = self.isometry.to_homogeneous() * Matrix4::new_nonuniform_scaling(&self.scale);
94
95        self.geometry.reset_uniforms();
96        self.geometry.uniforms.push(GadgetData {
97            label: MODEL_MAT_LABEL.to_string(),
98            index: MODEL_MAT_INDEX,
99            data: bytemuck::cast_slice(self.matrix.as_slice()).to_vec(),
100            needs_update_value: true,
101            needs_update_buffer: true,
102        })
103    }
104}
105
106pub trait Renderable {
107    fn identifier(&self) -> usize;
108    fn build_instance(&self) -> RenderInstance;
109}