summaryrefslogtreecommitdiff
path: root/engine/src/mesh.rs
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/mesh.rs')
-rw-r--r--engine/src/mesh.rs170
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;
+ }
+ }
}