diff options
Diffstat (limited to 'engine/src/mesh.rs')
| -rw-r--r-- | engine/src/mesh.rs | 170 |
1 files changed, 167 insertions, 3 deletions
diff --git a/engine/src/mesh.rs b/engine/src/mesh.rs index de0af70..f26c9c1 100644 --- a/engine/src/mesh.rs +++ b/engine/src/mesh.rs @@ -1,10 +1,12 @@ -use ecs::Component; +use engine_macros::Reflection; +use zerocopy::{Immutable, IntoBytes}; -use crate::vertex::Vertex; +use crate::builder; +use crate::vector::Vec3; pub mod cube; -#[derive(Debug, Clone, Component)] +#[derive(Debug, Clone, Default)] pub struct Mesh { vertices: Vec<Vertex>, @@ -26,8 +28,170 @@ impl Mesh } #[must_use] + pub fn vertices_mut(&mut self) -> &mut [Vertex] + { + &mut self.vertices + } + + #[must_use] pub fn indices(&self) -> Option<&[u32]> { self.indices.as_deref() } + + #[must_use] + pub fn indices_mut(&mut self) -> Option<&mut [u32]> + { + self.indices.as_deref_mut() + } + + /// Finds the vertex positions that are furthest in every 3D direction. Keep in mind + /// that this can be quite time-expensive if the mesh has many vertices. + pub fn find_furthest_vertex_positions(&self) -> DirectionPositions + { + let mut point_iter = self + .vertices() + .iter() + .map(|vertex| Vec3::from(vertex.pos)) + .into_iter(); + + let first_point = point_iter.next().unwrap(); + + point_iter + .fold( + FurthestPosAcc { + up: FurthestPos::new(first_point, &Vec3::UP), + down: FurthestPos::new(first_point, &Vec3::DOWN), + left: FurthestPos::new(first_point, &Vec3::LEFT), + right: FurthestPos::new(first_point, &Vec3::RIGHT), + back: FurthestPos::new(first_point, &Vec3::BACK), + front: FurthestPos::new(first_point, &Vec3::FRONT), + }, + |mut furthest_pos_acc, pos| { + furthest_pos_acc.up.update_if_further(pos); + furthest_pos_acc.down.update_if_further(pos); + furthest_pos_acc.left.update_if_further(pos); + furthest_pos_acc.right.update_if_further(pos); + furthest_pos_acc.back.update_if_further(pos); + furthest_pos_acc.front.update_if_further(pos); + + furthest_pos_acc + }, + ) + .into() + } +} + +builder! { +#[builder(name = VertexBuilder, derives = (Debug, Default, Clone))] +#[derive(Debug, Clone, Default, PartialEq, IntoBytes, Immutable, Reflection)] +#[non_exhaustive] +pub struct Vertex +{ + #[builder(skip_generate_fn)] + pub pos: [f32; 3], + + #[builder(skip_generate_fn)] + pub texture_coords: [f32; 2], + + #[builder(skip_generate_fn)] + pub normal: [f32; 3], +} +} + +impl Vertex +{ + #[must_use] + pub fn builder() -> VertexBuilder + { + VertexBuilder::default() + } +} + +impl VertexBuilder +{ + pub fn pos(mut self, pos: impl Into<[f32; 3]>) -> Self + { + self.pos = pos.into(); + self + } + + pub fn texture_coords(mut self, texture_coords: impl Into<[f32; 2]>) -> Self + { + self.texture_coords = texture_coords.into(); + self + } + + pub fn normal(mut self, normal: impl Into<[f32; 3]>) -> Self + { + self.normal = normal.into(); + self + } +} + +#[derive(Debug, Clone)] +pub struct DirectionPositions +{ + pub up: Vec3<f32>, + pub down: Vec3<f32>, + pub left: Vec3<f32>, + pub right: Vec3<f32>, + pub back: Vec3<f32>, + pub front: Vec3<f32>, +} + +impl<'mesh> From<FurthestPosAcc<'mesh>> for DirectionPositions +{ + fn from(acc: FurthestPosAcc<'mesh>) -> Self + { + Self { + up: acc.up.pos, + down: acc.down.pos, + left: acc.left.pos, + right: acc.right.pos, + back: acc.back.pos, + front: acc.front.pos, + } + } +} + +#[derive(Debug)] +struct FurthestPosAcc<'mesh> +{ + up: FurthestPos<'mesh>, + down: FurthestPos<'mesh>, + left: FurthestPos<'mesh>, + right: FurthestPos<'mesh>, + back: FurthestPos<'mesh>, + front: FurthestPos<'mesh>, +} + +#[derive(Debug)] +struct FurthestPos<'mesh> +{ + pos: Vec3<f32>, + dot_prod: f32, + direction: &'mesh Vec3<f32>, +} + +impl<'mesh> FurthestPos<'mesh> +{ + fn new(pos: Vec3<f32>, direction: &'mesh Vec3<f32>) -> Self + { + Self { + pos, + dot_prod: direction.dot(&pos), + direction, + } + } + + fn update_if_further(&mut self, point: Vec3<f32>) + { + let point_dot_prod = self.direction.dot(&point); + + if point_dot_prod > self.dot_prod { + self.pos = point; + self.dot_prod = point_dot_prod; + } + } } |
