Skip to main content

mraphics_core/geometry/
cube.rs

1use crate::{Geometry, GeometryIndices, Material, Mesh, Representable, Transformable, Vertices};
2use nalgebra::Vector3;
3
4#[derive(Clone)]
5pub struct Cube {
6    pub width: f32,
7    pub height: f32,
8    pub depth: f32,
9
10    pub vertices: Vertices,
11}
12
13impl Cube {
14    pub fn new() -> Self {
15        Self::default()
16    }
17}
18
19impl Default for Cube {
20    fn default() -> Self {
21        Self {
22            width: 1.0,
23            height: 1.0,
24            depth: 1.0,
25
26            vertices: Vertices::new(),
27        }
28    }
29}
30
31impl Geometry for Cube {
32    fn init_view(&self, view: &mut super::GeometryView) {
33        view.add_attribute(
34            crate::constants::POSITION_ATTR_LABEL,
35            crate::constants::POSITION_ATTR_INDEX,
36            bytemuck::cast_slice::<f32, u8>(&self.vertices.data.concat()).to_vec(),
37        );
38    }
39
40    fn update_view(&self, view: &mut super::GeometryView) {
41        self.vertices.update_geometry_view(view);
42        view.indices = GeometryIndices::Sequential(self.vertices.data.len() as u32);
43    }
44
45    fn update(&mut self) {
46        let vertices = &mut self.vertices.data;
47
48        fn to_homogeneous(point: &Vector3<f32>, w: f32) -> [f32; 4] {
49            std::array::from_fn(|i| if i < 3 { point[i] } else { w })
50        }
51
52        let mut build_plane =
53            |position: Vector3<f32>, width_len: f32, height_len: f32, normal: Vector3<f32>| {
54                let mut height = normal.yzx();
55                height.set_magnitude(height_len);
56
57                let mut width = height.cross(&normal);
58                width.set_magnitude(width_len);
59
60                vertices.push(to_homogeneous(&position, 1.0));
61                vertices.push(to_homogeneous(&(position + width), 1.0));
62                vertices.push(to_homogeneous(&(position + width + height), 1.0));
63                vertices.push(to_homogeneous(&(position + height), 1.0));
64                vertices.push(to_homogeneous(&position, 1.0));
65                vertices.push(to_homogeneous(&(position + width + height), 1.0));
66            };
67
68        let w = self.width;
69        let h = self.height;
70        let d = self.depth;
71
72        build_plane(
73            Vector3::new(-w / 2.0, -h / 2.0, -d / 2.0),
74            w,
75            h,
76            Vector3::z(),
77        );
78        build_plane(
79            Vector3::new(-w / 2.0, -h / 2.0, d / 2.0),
80            w,
81            h,
82            Vector3::z(),
83        );
84        build_plane(
85            Vector3::new(w / 2.0, -h / 2.0, -d / 2.0),
86            h,
87            d,
88            Vector3::x(),
89        );
90        build_plane(
91            Vector3::new(-w / 2.0, -h / 2.0, d / 2.0),
92            h,
93            d,
94            -Vector3::x(),
95        );
96        build_plane(
97            Vector3::new(-w / 2.0, h / 2.0, -d / 2.0),
98            d,
99            w,
100            Vector3::y(),
101        );
102        build_plane(
103            Vector3::new(w / 2.0, -h / 2.0, -d / 2.0),
104            d,
105            w,
106            -Vector3::y(),
107        );
108    }
109}
110
111impl<M: Material> Representable for Mesh<Cube, M> {
112    type Intermediate = Vertices;
113
114    fn as_intermediate(&self) -> Self::Intermediate {
115        self.geometry.vertices.clone()
116    }
117
118    fn update_from_intermediate(&mut self, repr: &Self::Intermediate) {
119        self.geometry.vertices = repr.clone();
120    }
121}
122
123impl<M: Material> Transformable for Mesh<Cube, M> {
124    fn apply_transform<Trans: Fn(&[f32; 3]) -> [f32; 3]>(
125        &self,
126        transform: Trans,
127    ) -> Self::Intermediate {
128        self.geometry.vertices.apply_transform(|vertex| {
129            let transformed = transform(&[vertex[0], vertex[1], vertex[2]]);
130            [transformed[0], transformed[1], transformed[2], 1.0]
131        })
132    }
133}