Skip to main content

enigma_3d/
geometry.rs

1use std::fmt::{Debug, Display, Formatter};
2use glium::implement_vertex;
3use nalgebra::Vector3;
4use serde::{Deserialize, Serialize};
5
6#[repr(C, align(16))]
7#[derive(Copy, Clone)]
8pub struct BoneTransforms {
9    pub bone_transforms: [[[f32; 4]; 4]; 128]
10}
11impl glium::uniforms::UniformBlock for BoneTransforms {
12    fn matches(_layout: &glium::program::BlockLayout, _base_offset: usize) -> Result<(), glium::uniforms::LayoutMismatchError> {
13        Ok(())
14    }
15    fn build_layout(base_offset: usize) -> glium::program::BlockLayout {
16        glium::program::BlockLayout::Struct {
17            members: vec![
18                ("bone_transforms".to_owned(), glium::program::BlockLayout::Array {
19                    content: Box::new(glium::program::BlockLayout::BasicType {
20                        ty: glium::uniforms::UniformType::FloatMat4,
21                        offset_in_buffer: base_offset,
22                    }),
23                    length: 128,
24                }),
25            ],
26        }
27    }
28}
29
30#[derive(Copy, Clone)]
31pub struct InstanceAttribute {
32    pub model_matrix: [[f32; 4]; 4],
33}
34implement_vertex!(InstanceAttribute, model_matrix);
35
36#[derive(Copy, Clone, Serialize, Deserialize)]
37pub struct Vertex {
38    pub position: [f32; 3],
39    pub texcoord: [f32; 2],
40    pub color: [f32; 3],
41    pub normal: [f32; 3],
42    pub bone_indices: [u32; 4],
43    pub bone_weights: [f32; 4],
44}
45
46glium::implement_vertex!(Vertex, position, texcoord, color, normal, bone_indices, bone_weights);
47
48
49#[derive(Serialize, Deserialize)]
50pub struct BoundingBoxSerializer {
51    pub center: [f32; 3],
52    pub width: f32,
53    pub height: f32,
54    pub depth: f32,
55}
56
57#[derive(Copy, Clone)]
58pub struct BoundingBox {
59    pub center: Vector3<f32>,
60    //relative to the objects position
61    pub width: f32,
62    pub height: f32,
63    pub depth: f32,
64}
65
66#[derive(Serialize, Deserialize)]
67pub struct BoundingBoxMesh {
68    pub vertices: Vec<Vertex>,
69    pub indices: Vec<u32>,
70}
71
72impl Debug for Vertex {
73    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74        f.debug_struct("Vertex")
75            .field("position", &self.position)
76            .field("texcoord", &self.texcoord)
77            .field("color", &self.color)
78            .field("normal", &self.normal)
79            .field("bone_indices", &self.bone_indices)
80            .field("bone_weights", &self.bone_weights)
81            .finish()
82    }
83}
84
85impl Display for Vertex {
86    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
87        f.debug_struct("Vertex")
88            .field("position", &self.position)
89            .field("texcoord", &self.texcoord)
90            .field("color", &self.color)
91            .field("normal", &self.normal)
92            .field("bone_indices", &self.bone_indices)
93            .field("bone_weights", &self.bone_weights)
94            .finish()
95    }
96}
97
98impl BoundingBoxMesh {
99    pub fn new(bounding_box: &BoundingBox) -> Self {
100        let half_width = bounding_box.width / 2.0;
101        let half_height = bounding_box.height / 2.0;
102        let half_depth = bounding_box.depth / 2.0;
103
104        let corners = [
105            bounding_box.center + Vector3::new(-half_width, -half_height, -half_depth),
106            bounding_box.center + Vector3::new(half_width, -half_height, -half_depth),
107            bounding_box.center + Vector3::new(half_width, half_height, -half_depth),
108            bounding_box.center + Vector3::new(-half_width, half_height, -half_depth),
109            bounding_box.center + Vector3::new(-half_width, -half_height, half_depth),
110            bounding_box.center + Vector3::new(half_width, -half_height, half_depth),
111            bounding_box.center + Vector3::new(half_width, half_height, half_depth),
112            bounding_box.center + Vector3::new(-half_width, half_height, half_depth),
113        ];
114
115        let mut vertices = Vec::new();
116
117        for i in 0..corners.len() {
118            let corner = corners[i];
119            vertices.push(Vertex {
120                position: [corner.x, corner.y, corner.z],
121                texcoord: [0.0, 0.0],
122                color: [1.0, 1.0, 1.0],
123                normal: [0.0, 0.0, 0.0],
124                bone_indices: [0, 0, 0, 0],
125                bone_weights: [0.0, 0.0, 0.0, 0.0],
126            });
127        }
128        let indices = vec![
129            0, 1, 2, 2, 3, 0, // Front face
130            1, 5, 6, 6, 2, 1, // Right face
131            5, 4, 7, 7, 6, 5, // Back face
132            4, 0, 3, 3, 7, 4, // Left face
133            3, 2, 6, 6, 7, 3, // Top face
134            4, 5, 1, 1, 0, 4, // Bottom face
135        ];
136
137        Self {
138            vertices,
139            indices,
140        }
141    }
142}
143
144impl BoundingBox {
145    pub fn new(min_point: [f32; 3], max_point: [f32; 3]) -> Self {
146        let min = Vector3::from(min_point);
147        let max = Vector3::from(max_point);
148
149        // Calculate the center point
150        let center = (min + max) / 2.0;
151
152        // Calculate dimensions
153        let width = max.x - min.x;
154        let height = max.y - min.y;
155        let depth = max.z - min.z;
156
157        BoundingBox {
158            center,
159            width,
160            height,
161            depth,
162        }
163    }
164
165    // Returns the minimum point of the bounding box
166    pub fn min_point(&self) -> Vector3<f32> {
167        Vector3::new(
168            self.center.x - self.width / 2.0,
169            self.center.y - self.height / 2.0,
170            self.center.z - self.depth / 2.0,
171        )
172    }
173
174    // Returns the maximum point of the bounding box
175    pub fn max_point(&self) -> Vector3<f32> {
176        Vector3::new(
177            self.center.x + self.width / 2.0,
178            self.center.y + self.height / 2.0,
179            self.center.z + self.depth / 2.0,
180        )
181    }
182
183    pub fn to_serializer(&self) -> BoundingBoxSerializer {
184        BoundingBoxSerializer {
185            center: [self.center.x, self.center.y, self.center.z],
186            width: self.width,
187            height: self.height,
188            depth: self.depth,
189        }
190    }
191
192    pub fn from_serializer(serializer: BoundingBoxSerializer) -> Self {
193        Self {
194            center: Vector3::new(serializer.center[0], serializer.center[1], serializer.center[2]),
195            width: serializer.width,
196            height: serializer.height,
197            depth: serializer.depth,
198        }
199    }
200}