mraphics_core/geometry/
instance.rs1use 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}