use engine::math::calc_triangle_surface_normal; use engine::mesh::Mesh; use engine::vector::Vec3; use engine::vertex::{Builder as VertexBuilder, Vertex}; pub enum Side { Front, Back, Left, Right, Top, Bottom, } pub enum Corner { TopRight, TopLeft, BottomRight, BottomLeft, } pub fn create_cube_mesh( vertex_builder_cb: impl Fn(VertexBuilder, Side, Corner) -> VertexBuilder, ) -> Mesh { let mut vertices: [Option; VertexIndex::VARIANT_CNT] = [(); VertexIndex::VARIANT_CNT].map(|()| None); let front_top_right_pos = Vec3 { x: 0.5, y: 0.5, z: -0.5 }; let front_bottom_right_pos = Vec3 { x: 0.5, y: -0.5, z: -0.5 }; let front_bottom_left_pos = Vec3 { x: -0.5, y: -0.5, z: -0.5 }; let front_top_left_pos = Vec3 { x: -0.5, y: 0.5, z: -0.5 }; let front_normal = calc_triangle_surface_normal( &front_top_right_pos, &front_bottom_right_pos, &front_top_left_pos, ); vertices[VertexIndex::FrontTopRight as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(front_top_right_pos) .normal(front_normal.clone()), Side::Front, Corner::TopRight, ) .build() .unwrap(), ); vertices[VertexIndex::FrontBottomRight as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(front_bottom_right_pos) .normal(front_normal.clone()), Side::Front, Corner::BottomRight, ) .build() .unwrap(), ); vertices[VertexIndex::FrontBottomLeft as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(front_bottom_left_pos) .normal(front_normal.clone()), Side::Front, Corner::BottomLeft, ) .build() .unwrap(), ); vertices[VertexIndex::FrontTopLeft as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(front_top_left_pos) .normal(front_normal.clone()), Side::Front, Corner::TopLeft, ) .build() .unwrap(), ); let back_top_right_pos = Vec3 { x: 0.5, y: 0.5, z: 0.5 }; let back_bottom_right_pos = Vec3 { x: 0.5, y: -0.5, z: 0.5 }; let back_bottom_left_pos = Vec3 { x: -0.5, y: -0.5, z: 0.5 }; let back_top_left_pos = Vec3 { x: -0.5, y: 0.5, z: 0.5 }; let back_normal = -calc_triangle_surface_normal( &back_top_right_pos, &back_bottom_right_pos, &back_top_left_pos, ); vertices[VertexIndex::BackTopRight as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(back_top_right_pos) .normal(back_normal.clone()), Side::Back, Corner::TopRight, ) .build() .unwrap(), ); vertices[VertexIndex::BackBottomRight as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(back_bottom_right_pos) .normal(back_normal.clone()), Side::Back, Corner::BottomRight, ) .build() .unwrap(), ); vertices[VertexIndex::BackBottomLeft as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(back_bottom_left_pos) .normal(back_normal.clone()), Side::Back, Corner::BottomLeft, ) .build() .unwrap(), ); vertices[VertexIndex::BackTopLeft as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(back_top_left_pos) .normal(back_normal), Side::Back, Corner::TopLeft, ) .build() .unwrap(), ); let right_back_top_pos = Vec3 { x: 0.5, y: 0.5, z: 0.5 }; let right_back_bottom_pos = Vec3 { x: 0.5, y: -0.5, z: 0.5 }; let right_front_top_pos = Vec3 { x: 0.5, y: 0.5, z: -0.5 }; let right_front_bottom_pos = Vec3 { x: 0.5, y: -0.5, z: -0.5 }; let right_normal = calc_triangle_surface_normal( &right_back_top_pos, &right_back_bottom_pos, &right_front_top_pos, ); vertices[VertexIndex::RightBackTop as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(right_back_top_pos) .normal(right_normal.clone()), Side::Right, Corner::TopLeft, ) .build() .unwrap(), ); vertices[VertexIndex::RightBackBottom as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(right_back_bottom_pos) .normal(right_normal.clone()), Side::Right, Corner::BottomLeft, ) .build() .unwrap(), ); vertices[VertexIndex::RightFrontTop as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(right_front_top_pos) .normal(right_normal.clone()), Side::Right, Corner::TopRight, ) .build() .unwrap(), ); vertices[VertexIndex::RightFrontBottom as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(right_front_bottom_pos) .normal(right_normal), Side::Right, Corner::BottomRight, ) .build() .unwrap(), ); let left_back_top_pos = Vec3 { x: -0.5, y: 0.5, z: 0.5 }; let left_back_bottom_pos = Vec3 { x: -0.5, y: -0.5, z: 0.5 }; let left_front_top_pos = Vec3 { x: -0.5, y: 0.5, z: -0.5 }; let left_front_bottom_pos = Vec3 { x: -0.5, y: -0.5, z: -0.5 }; let left_normal = -calc_triangle_surface_normal( &left_back_top_pos, &left_back_bottom_pos, &left_front_top_pos, ); vertices[VertexIndex::LeftBackTop as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(left_back_top_pos) .normal(left_normal.clone()), Side::Left, Corner::TopRight, ) .build() .unwrap(), ); vertices[VertexIndex::LeftBackBottom as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(left_back_bottom_pos) .normal(left_normal.clone()), Side::Left, Corner::BottomRight, ) .build() .unwrap(), ); vertices[VertexIndex::LeftFrontTop as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(left_front_top_pos) .normal(left_normal.clone()), Side::Left, Corner::TopLeft, ) .build() .unwrap(), ); vertices[VertexIndex::LeftFrontBottom as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(left_front_bottom_pos) .normal(left_normal), Side::Left, Corner::BottomLeft, ) .build() .unwrap(), ); let top_back_right_pos = Vec3 { x: 0.5, y: 0.5, z: 0.5 }; let top_back_left_pos = Vec3 { x: -0.5, y: 0.5, z: 0.5 }; let top_front_left_pos = Vec3 { x: -0.5, y: 0.5, z: -0.5 }; let top_front_right_pos = Vec3 { x: 0.5, y: 0.5, z: -0.5 }; let top_normal = -calc_triangle_surface_normal( &top_back_right_pos, &top_back_left_pos, &top_front_right_pos, ); vertices[VertexIndex::TopBackRight as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(top_back_right_pos) .normal(top_normal.clone()), Side::Top, Corner::TopRight, ) .build() .unwrap(), ); vertices[VertexIndex::TopBackLeft as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(top_back_left_pos) .normal(top_normal.clone()), Side::Top, Corner::TopLeft, ) .build() .unwrap(), ); vertices[VertexIndex::TopFrontLeft as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(top_front_left_pos) .normal(top_normal.clone()), Side::Top, Corner::BottomLeft, ) .build() .unwrap(), ); vertices[VertexIndex::TopFrontRight as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(top_front_right_pos) .normal(top_normal), Side::Top, Corner::BottomRight, ) .build() .unwrap(), ); let bottom_back_right_pos = Vec3 { x: 0.5, y: -0.5, z: 0.5 }; let bottom_back_left_pos = Vec3 { x: -0.5, y: -0.5, z: 0.5 }; let bottom_front_right_pos = Vec3 { x: 0.5, y: -0.5, z: -0.5 }; let bottom_front_left_pos = Vec3 { x: -0.5, y: -0.5, z: -0.5 }; let bottom_normal = calc_triangle_surface_normal( &bottom_back_right_pos, &bottom_back_left_pos, &bottom_front_right_pos, ); vertices[VertexIndex::BottomBackRight as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(bottom_back_right_pos) .normal(bottom_normal.clone()), Side::Bottom, Corner::BottomRight, ) .build() .unwrap(), ); vertices[VertexIndex::BottomBackLeft as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(bottom_back_left_pos) .normal(bottom_normal.clone()), Side::Bottom, Corner::BottomLeft, ) .build() .unwrap(), ); vertices[VertexIndex::BottomFrontRight as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(bottom_front_right_pos) .normal(bottom_normal.clone()), Side::Bottom, Corner::TopRight, ) .build() .unwrap(), ); vertices[VertexIndex::BottomFrontLeft as usize] = Some( vertex_builder_cb( VertexBuilder::new() .pos(bottom_front_left_pos) .normal(bottom_normal), Side::Bottom, Corner::TopLeft, ) .build() .unwrap(), ); let front = [ // 🮝 VertexIndex::FrontTopRight, VertexIndex::FrontBottomRight, VertexIndex::FrontTopLeft, // // 🮟 VertexIndex::FrontBottomRight, VertexIndex::FrontBottomLeft, VertexIndex::FrontTopLeft, ]; let back = [ // 🮝 VertexIndex::BackTopRight, VertexIndex::BackBottomRight, VertexIndex::BackTopLeft, // // 🮟 VertexIndex::BackBottomRight, VertexIndex::BackBottomLeft, VertexIndex::BackTopLeft, ]; let right = [ // 🮝 VertexIndex::RightBackTop, VertexIndex::RightBackBottom, VertexIndex::RightFrontTop, // // 🮟 VertexIndex::RightBackBottom, VertexIndex::RightFrontBottom, VertexIndex::RightFrontTop, ]; let left = [ // 🮝 VertexIndex::LeftBackTop, VertexIndex::LeftBackBottom, VertexIndex::LeftFrontTop, // // 🮟 VertexIndex::LeftBackBottom, VertexIndex::LeftFrontBottom, VertexIndex::LeftFrontTop, ]; let top = [ // 🮝 VertexIndex::TopBackRight, VertexIndex::TopBackLeft, VertexIndex::TopFrontRight, // // 🮟 VertexIndex::TopBackLeft, VertexIndex::TopFrontLeft, VertexIndex::TopFrontRight, ]; let bottom = [ // 🮝 VertexIndex::BottomBackRight, VertexIndex::BottomBackLeft, VertexIndex::BottomFrontRight, // // 🮟 VertexIndex::BottomBackLeft, VertexIndex::BottomFrontLeft, VertexIndex::BottomFrontRight, ]; let indices = [front, back, right, left, top, bottom]; Mesh::new( vertices.map(Option::unwrap).to_vec(), Some( indices .into_iter() .flatten() .map(|index| index as u32) .collect(), ), ) } macro_rules! one { ($tt: tt) => { 1 }; } macro_rules! enum_with_variant_cnt { ( $(#[$attr: meta])* enum $name: ident { $($variant: ident,)* } ) => { $(#[$attr])* enum $name { $($variant,)* } impl $name { const VARIANT_CNT: usize = 0 $(+ one!($variant))*; } }; } enum_with_variant_cnt! { #[repr(u32)] enum VertexIndex { FrontTopRight, FrontBottomRight, FrontBottomLeft, FrontTopLeft, BackTopRight, BackBottomRight, BackBottomLeft, BackTopLeft, RightBackTop, RightBackBottom, RightFrontTop, RightFrontBottom, LeftBackTop, LeftBackBottom, LeftFrontTop, LeftFrontBottom, TopBackRight, TopBackLeft, TopFrontRight, TopFrontLeft, BottomBackRight, BottomBackLeft, BottomFrontRight, BottomFrontLeft, } }