diff options
Diffstat (limited to 'engine')
| -rw-r--r-- | engine/src/mesh.rs | 76 | ||||
| -rw-r--r-- | engine/src/mesh/cube.rs | 443 | ||||
| -rw-r--r-- | engine/src/mesh/vertex_buffer.rs | 20 |
3 files changed, 94 insertions, 445 deletions
diff --git a/engine/src/mesh.rs b/engine/src/mesh.rs index 82e2877..c0120a2 100644 --- a/engine/src/mesh.rs +++ b/engine/src/mesh.rs @@ -1,9 +1,11 @@ use std::alloc::Layout; -use crate::mesh::vertex_buffer::VertexLabel; +use zerocopy::IntoBytes; + +use crate::data_types::dimens::Dimens3; +use crate::mesh::vertex_buffer::{VertexAttrProperties, VertexLabel}; use crate::vector::Vec3; -pub mod cube; pub mod vertex_buffer; #[derive(Debug, Clone)] @@ -15,6 +17,76 @@ pub struct Mesh impl Mesh { + pub fn cube(size: Dimens3<f32>) -> Self + { + let half_w = size.width / 2.0; + let half_h = size.height / 2.0; + let half_d = size.depth / 2.0; + + let vertices = [ + // pos.x, pos.y, pos.z, texture_coords.x, texture_coords.y, normal.x, + // normal.y, normal.z + [half_w, half_h, half_d, 1.00, 1.00, 0.0, 1.00, 0.0], + [-half_w, half_h, half_d, 0.0, 1.00, 0.0, 1.00, 0.0], + [half_w, half_h, -half_d, 1.00, 0.0, 0.0, 1.00, 0.0], + [-half_w, half_h, -half_d, 0.0, 0.0, 0.0, 1.00, 0.0], + [half_w, -half_h, half_d, 1.00, 1.00, 0.0, -1.00, 0.0], + [-half_w, -half_h, half_d, 0.0, 1.00, 0.0, -1.00, 0.0], + [half_w, -half_h, -half_d, 1.00, 0.0, 0.0, -1.00, 0.0], + [-half_w, -half_h, -half_d, 0.0, 0.0, 0.0, -1.00, 0.0], + [-half_w, half_h, half_d, 1.00, 1.00, -1.00, 0.0, 0.0], + [-half_w, half_h, -half_d, 0.0, 1.00, -1.00, 0.0, 0.0], + [-half_w, -half_h, half_d, 1.00, 0.0, -1.00, 0.0, 0.0], + [-half_w, -half_h, -half_d, 0.0, 0.0, -1.00, 0.0, 0.0], + [half_w, half_h, half_d, 1.00, 1.00, 1.00, 0.0, 0.0], + [half_w, half_h, -half_d, 0.0, 1.00, 1.00, 0.0, 0.0], + [half_w, -half_h, half_d, 1.00, 0.0, 1.00, 0.0, 0.0], + [half_w, -half_h, -half_d, 0.0, 0.0, 1.00, 0.0, 0.0], + [half_w, half_h, -half_d, 1.00, 1.00, 0.0, 0.0, -1.00], + [-half_w, half_h, -half_d, 0.0, 1.00, 0.0, 0.0, -1.00], + [half_w, -half_h, -half_d, 1.00, 0.0, 0.0, 0.0, -1.00], + [-half_w, -half_h, -half_d, 0.0, 0.0, 0.0, 0.0, -1.00], + [half_w, half_h, half_d, 1.00, 1.00, 0.0, 0.0, 1.00], + [-half_w, half_h, half_d, 0.0, 1.00, 0.0, 0.0, 1.00], + [half_w, -half_h, half_d, 1.00, 0.0, 0.0, 0.0, 1.00], + [-half_w, -half_h, half_d, 0.0, 0.0, 0.0, 0.0, 1.00], + ]; + + let elements = [ + 0, 1, 2, 1, 3, 2, 4, 5, 6, 5, 7, 6, 8, 9, 10, 9, 11, 10, 12, 13, 14, 13, 15, + 14, 16, 17, 18, 17, 19, 18, 20, 21, 22, 21, 23, 22, + ]; + + Mesh::builder() + .vertices(unsafe { + vertex_buffer::VertexBuffer::from_raw( + &[ + VertexAttrProperties { + label: VertexLabel::Position, + ty: VertexAttrType::Float32Array { length: 3 }, + layout: Layout::new::<[f32; 3]>(), + byte_offset: 0, + }, + VertexAttrProperties { + label: VertexLabel::Uv, + ty: VertexAttrType::Float32Array { length: 2 }, + layout: Layout::new::<[f32; 2]>(), + byte_offset: size_of::<[f32; 3]>(), + }, + VertexAttrProperties { + label: VertexLabel::Normal, + ty: VertexAttrType::Float32Array { length: 3 }, + layout: Layout::new::<[f32; 3]>(), + byte_offset: size_of::<[f32; 3]>() + size_of::<[f32; 2]>(), + }, + ], + vertices.as_bytes().to_vec(), + ) + }) + .indices(elements) + .build() + } + pub fn builder() -> Builder { Builder::default() diff --git a/engine/src/mesh/cube.rs b/engine/src/mesh/cube.rs deleted file mode 100644 index a89466a..0000000 --- a/engine/src/mesh/cube.rs +++ /dev/null @@ -1,443 +0,0 @@ -use std::collections::HashMap; - -use crate::builder; -use crate::data_types::dimens::Dimens3; -use crate::math::calc_triangle_surface_normal; -use crate::mesh::vertex_buffer::{ - NamedVertexAttr, - VertexAttrInfo, - VertexBuffer as MeshVertexBuffer, - VertexLabel, -}; -use crate::mesh::{Mesh, VertexAttrType}; -use crate::vector::{Vec2, Vec3}; - -builder! { -/// Cube mesh creation specification. -#[builder(name = CreationSpecBuilder, derives = (Debug, Default))] -#[derive(Debug, Default)] -#[non_exhaustive] -pub struct CreationSpec -{ - pub width: f32, - pub height: f32, - pub depth: f32, -} -} - -impl CreationSpec -{ - /// Returns a new `CreationSpec` builder. - #[must_use] - pub fn builder() -> CreationSpecBuilder - { - CreationSpecBuilder::default() - } -} - -impl CreationSpecBuilder -{ - pub fn dimens(mut self, dimens: Dimens3<f32>) -> Self - { - self.width = dimens.width; - self.height = dimens.height; - self.depth = dimens.depth; - - self - } -} - -/// Describes what location on a side of a cube a face is. -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub enum FaceLocation -{ - /// 🮝 - RightUp, - - /// 🮟 - LeftDown, -} - -/// Creates a cube mesh. -/// -/// By default, the texture coordinates are arranged so that the full texture is visible -/// on every side. This can be changed inside of the `face_cb` function. -pub fn create(creation_spec: CreationSpec) -> Mesh -{ - // TODO: Reimplement this mess - - let mut data = Data::default(); - - create_side(&SidePositions::new_top(&creation_spec), &mut data); - create_side(&SidePositions::new_bottom(&creation_spec), &mut data); - create_side(&SidePositions::new_left(&creation_spec), &mut data); - create_side(&SidePositions::new_right(&creation_spec), &mut data); - create_side(&SidePositions::new_back(&creation_spec), &mut data); - create_side(&SidePositions::new_front(&creation_spec), &mut data); - - data.into_mesh() -} - -#[derive(Debug, Default)] -struct Data -{ - faces: Vec<Face>, - vertex_data: VertexData, -} - -#[derive(Debug, Default)] -struct VertexData -{ - vertex_positions: Vec<Vec3<f32>>, - vertex_normals: Vec<Vec3<f32>>, -} - -impl Data -{ - fn into_mesh(self) -> Mesh - { - let mut vertex_buf = MeshVertexBuffer::with_capacity( - &[ - VertexAttrInfo { - label: VertexLabel::Position, - ty: VertexAttrType::Float32Array { length: 3 }, - }, - VertexAttrInfo { - label: VertexLabel::Uv, - ty: VertexAttrType::Float32Array { length: 2 }, - }, - VertexAttrInfo { - label: VertexLabel::Normal, - ty: VertexAttrType::Float32Array { length: 3 }, - }, - ], - self.faces.len() * 3, - ); - - let mut indices = Vec::<u32>::with_capacity(self.faces.len() * 3); - - let mut added_face_vertices = HashMap::<FaceVertex, u32>::new(); - - let mut face_location = FaceLocation::RightUp; - - let Self { faces, vertex_data } = self; - - for face in faces { - let face_texture_coords = match face_location { - FaceLocation::RightUp => [ - Vec2 { x: 1.0, y: 1.0 }, - Vec2 { x: 0.0, y: 1.0 }, - Vec2 { x: 1.0, y: 0.0 }, - ], - FaceLocation::LeftDown => [ - Vec2 { x: 0.0, y: 1.0 }, - Vec2 { x: 0.0, y: 0.0 }, - Vec2 { x: 1.0, y: 0.0 }, - ], - }; - - for (face_vertex, vertex_uv) in face.vertices.iter().zip(face_texture_coords) - { - if let Some(vertex_index) = added_face_vertices.get(face_vertex) { - indices.push(*vertex_index); - continue; - } - - let vertex_pos = vertex_data - .vertex_positions - .get(face_vertex.pos_index as usize) - .expect("Vertex position index is out of bounds") - .clone(); - - let vertex_normal = vertex_data - .vertex_normals - .get(face_vertex.normal_index as usize) - .expect("Vertex normal index is out of bounds") - .clone(); - - vertex_buf.push(( - NamedVertexAttr { - label: VertexLabel::Position, - value: vertex_pos.into_array(), - }, - NamedVertexAttr { - label: VertexLabel::Uv, - value: vertex_uv.into_array(), - }, - NamedVertexAttr { - label: VertexLabel::Normal, - value: vertex_normal.into_array(), - }, - )); - - let vertex_index = u32::try_from(vertex_buf.len() - 1) - .expect("Vertex index does not fit into 32-bit unsigned int"); - - indices.push(vertex_index); - - added_face_vertices.insert(face_vertex.clone(), vertex_index); - } - - match face_location { - FaceLocation::RightUp => face_location = FaceLocation::LeftDown, - FaceLocation::LeftDown => face_location = FaceLocation::RightUp, - } - } - - Mesh::builder() - .vertices(vertex_buf) - .indices(indices) - .build() - } -} - -#[derive(Debug)] -struct Face -{ - vertices: [FaceVertex; 3], -} - -#[derive(Debug, PartialEq, Eq, Hash, Clone)] -struct FaceVertex -{ - pos_index: u32, - normal_index: u32, -} - -#[derive(Debug)] -struct SidePositions -{ - up_left: Vec3<f32>, - up_right: Vec3<f32>, - down_left: Vec3<f32>, - down_right: Vec3<f32>, - normal_calc_order: NormalCalcOrder, -} - -impl SidePositions -{ - fn new_top(creation_spec: &CreationSpec) -> Self - { - let up_left = Vec3 { - x: -(creation_spec.width / 2.0), - y: creation_spec.height / 2.0, - z: creation_spec.depth / 2.0, - }; - - let down_right = Vec3 { - x: creation_spec.width / 2.0, - y: creation_spec.height / 2.0, - z: -(creation_spec.depth / 2.0), - }; - - Self { - up_left, - up_right: Vec3 { x: down_right.x, ..up_left.clone() }, - down_left: Vec3 { x: up_left.x, ..down_right.clone() }, - down_right, - normal_calc_order: NormalCalcOrder::Clockwise, - } - } - - fn new_bottom(creation_spec: &CreationSpec) -> Self - { - let up_left = Vec3 { - x: -(creation_spec.width / 2.0), - y: -creation_spec.height / 2.0, - z: creation_spec.depth / 2.0, - }; - - let down_right = Vec3 { - x: creation_spec.width / 2.0, - y: -creation_spec.height / 2.0, - z: -(creation_spec.depth / 2.0), - }; - - Self { - up_left, - up_right: Vec3 { x: down_right.x, ..up_left.clone() }, - down_left: Vec3 { x: up_left.x, ..down_right.clone() }, - down_right, - normal_calc_order: NormalCalcOrder::CounterClockwise, - } - } - - fn new_left(creation_spec: &CreationSpec) -> Self - { - let up_left = Vec3 { - x: -(creation_spec.width / 2.0), - y: creation_spec.height / 2.0, - z: -(creation_spec.depth / 2.0), - }; - - let down_right = Vec3 { - x: -(creation_spec.width / 2.0), - y: -(creation_spec.height / 2.0), - z: creation_spec.depth / 2.0, - }; - - Self { - up_left, - up_right: Vec3 { z: down_right.z, ..up_left.clone() }, - down_left: Vec3 { z: up_left.z, ..down_right.clone() }, - down_right, - normal_calc_order: NormalCalcOrder::CounterClockwise, - } - } - - fn new_right(creation_spec: &CreationSpec) -> Self - { - let up_left = Vec3 { - x: (creation_spec.width / 2.0), - y: creation_spec.height / 2.0, - z: -(creation_spec.depth / 2.0), - }; - - let down_right = Vec3 { - x: (creation_spec.width / 2.0), - y: -(creation_spec.height / 2.0), - z: creation_spec.depth / 2.0, - }; - - Self { - up_left, - up_right: Vec3 { z: down_right.z, ..up_left.clone() }, - down_left: Vec3 { z: up_left.z, ..down_right.clone() }, - down_right, - normal_calc_order: NormalCalcOrder::Clockwise, - } - } - - fn new_back(creation_spec: &CreationSpec) -> Self - { - let up_left = Vec3 { - x: -(creation_spec.width / 2.0), - y: creation_spec.height / 2.0, - z: -creation_spec.depth / 2.0, - }; - - let down_right = Vec3 { - x: creation_spec.width / 2.0, - y: -(creation_spec.height / 2.0), - z: -creation_spec.depth / 2.0, - }; - - Self { - up_left, - up_right: Vec3 { x: down_right.x, ..up_left.clone() }, - down_left: Vec3 { x: up_left.x, ..down_right.clone() }, - down_right, - normal_calc_order: NormalCalcOrder::Clockwise, - } - } - - fn new_front(creation_spec: &CreationSpec) -> Self - { - let up_left = Vec3 { - x: -(creation_spec.width / 2.0), - y: creation_spec.height / 2.0, - z: creation_spec.depth / 2.0, - }; - - let down_right = Vec3 { - x: creation_spec.width / 2.0, - y: -(creation_spec.height / 2.0), - z: creation_spec.depth / 2.0, - }; - - Self { - up_left, - up_right: Vec3 { x: down_right.x, ..up_left.clone() }, - down_left: Vec3 { x: up_left.x, ..down_right.clone() }, - down_right, - normal_calc_order: NormalCalcOrder::CounterClockwise, - } - } -} - -#[derive(Debug)] -enum NormalCalcOrder -{ - Clockwise, - CounterClockwise, -} - -fn create_side(side_positions: &SidePositions, data: &mut Data) -{ - let normal = match side_positions.normal_calc_order { - NormalCalcOrder::Clockwise => calc_triangle_surface_normal( - side_positions.up_left, - side_positions.up_right, - side_positions.down_left, - ), - NormalCalcOrder::CounterClockwise => calc_triangle_surface_normal( - side_positions.up_left, - side_positions.down_left, - side_positions.up_right, - ), - }; - - data.vertex_data.vertex_normals.push(normal); - - let top_normal_index = data.vertex_data.vertex_normals.len() - 1; - - data.vertex_data - .vertex_positions - .push(side_positions.up_right); - - let up_right_pos_index = data.vertex_data.vertex_positions.len() - 1; - - data.vertex_data - .vertex_positions - .push(side_positions.up_left); - - let up_left_pos_index = data.vertex_data.vertex_positions.len() - 1; - - data.vertex_data - .vertex_positions - .push(side_positions.down_left); - - let down_left_pos_index = data.vertex_data.vertex_positions.len() - 1; - - data.vertex_data - .vertex_positions - .push(side_positions.down_right); - - let down_right_pos_index = data.vertex_data.vertex_positions.len() - 1; - - // 🮝 - data.faces.push(Face { - vertices: [ - FaceVertex { - pos_index: up_right_pos_index as u32, - normal_index: top_normal_index as u32, - }, - FaceVertex { - pos_index: up_left_pos_index as u32, - normal_index: top_normal_index as u32, - }, - FaceVertex { - pos_index: down_right_pos_index as u32, - normal_index: top_normal_index as u32, - }, - ], - }); - - // 🮟 - data.faces.push(Face { - vertices: [ - FaceVertex { - pos_index: up_left_pos_index as u32, - normal_index: top_normal_index as u32, - }, - FaceVertex { - pos_index: down_left_pos_index as u32, - normal_index: top_normal_index as u32, - }, - FaceVertex { - pos_index: down_right_pos_index as u32, - normal_index: top_normal_index as u32, - }, - ], - }); -} diff --git a/engine/src/mesh/vertex_buffer.rs b/engine/src/mesh/vertex_buffer.rs index 4df3ffc..90e5752 100644 --- a/engine/src/mesh/vertex_buffer.rs +++ b/engine/src/mesh/vertex_buffer.rs @@ -73,6 +73,26 @@ pub struct VertexBuffer impl VertexBuffer { + pub unsafe fn from_raw( + vertex_attr_props: &[VertexAttrProperties], + buffer: Vec<u8>, + ) -> Self + { + let last_vertex_attr_props = vertex_attr_props + .iter() + .max_by_key(|props| props.byte_offset) + .expect("No vertex attribute properties are given"); + + let vertex_size = + last_vertex_attr_props.byte_offset + last_vertex_attr_props.layout.size(); + + Self { + buf: buffer, + vertex_size, + vertex_attr_props: vertex_attr_props.to_vec(), + } + } + pub fn with_capacity(vertex_attrs: &[VertexAttrInfo], capacity: usize) -> Self { let mut vertex_attr_props = vertex_attrs |
