use strafesnet_common::model::{Color4,TextureCoordinate,Mesh,IndexedGraphicsGroup,IndexedPhysicsGroup,IndexedVertex,PolygonGroupId,PolygonGroup,PolygonList,IndexedVertexList,PositionId,TextureCoordinateId,NormalId,ColorId,VertexId,RenderConfigId}; use strafesnet_common::integer::Planar64Vec3; #[derive(Debug)] pub enum Primitives{ Sphere, Cube, Cylinder, Wedge, CornerWedge, } #[derive(Hash,PartialEq,Eq)] pub enum CubeFace{ Right, Top, Back, Left, Bottom, Front, } const CUBE_DEFAULT_TEXTURE_COORDS:[TextureCoordinate;4]=[ TextureCoordinate::new(0.0,0.0), TextureCoordinate::new(1.0,0.0), TextureCoordinate::new(1.0,1.0), TextureCoordinate::new(0.0,1.0), ]; const CUBE_DEFAULT_VERTICES:[Planar64Vec3;8]=[ Planar64Vec3::int(-1,-1, 1),//0 left bottom back Planar64Vec3::int( 1,-1, 1),//1 right bottom back Planar64Vec3::int( 1, 1, 1),//2 right top back Planar64Vec3::int(-1, 1, 1),//3 left top back Planar64Vec3::int(-1, 1,-1),//4 left top front Planar64Vec3::int( 1, 1,-1),//5 right top front Planar64Vec3::int( 1,-1,-1),//6 right bottom front Planar64Vec3::int(-1,-1,-1),//7 left bottom front ]; const CUBE_DEFAULT_NORMALS:[Planar64Vec3;6]=[ Planar64Vec3::int( 1, 0, 0),//CubeFace::Right Planar64Vec3::int( 0, 1, 0),//CubeFace::Top Planar64Vec3::int( 0, 0, 1),//CubeFace::Back Planar64Vec3::int(-1, 0, 0),//CubeFace::Left Planar64Vec3::int( 0,-1, 0),//CubeFace::Bottom Planar64Vec3::int( 0, 0,-1),//CubeFace::Front ]; const CUBE_DEFAULT_POLYS:[[[u32;3];4];6]=[ // right (1, 0, 0) [ [6,2,0],//[vertex,tex,norm] [5,1,0], [2,0,0], [1,3,0], ], // top (0, 1, 0) [ [5,3,1], [4,2,1], [3,1,1], [2,0,1], ], // back (0, 0, 1) [ [0,3,2], [1,2,2], [2,1,2], [3,0,2], ], // left (-1, 0, 0) [ [0,2,3], [3,1,3], [4,0,3], [7,3,3], ], // bottom (0,-1, 0) [ [1,1,4], [0,0,4], [7,3,4], [6,2,4], ], // front (0, 0,-1) [ [4,1,5], [5,0,5], [6,3,5], [7,2,5], ], ]; #[derive(Hash,PartialEq,Eq)] pub enum WedgeFace{ Right, TopFront, Back, Left, Bottom, } const WEDGE_DEFAULT_NORMALS:[Planar64Vec3;5]=[ Planar64Vec3::int( 1, 0, 0),//Wedge::Right Planar64Vec3::int( 0, 1,-1),//Wedge::TopFront Planar64Vec3::int( 0, 0, 1),//Wedge::Back Planar64Vec3::int(-1, 0, 0),//Wedge::Left Planar64Vec3::int( 0,-1, 0),//Wedge::Bottom ]; /* local cornerWedgeVerticies = { Vector3.new(-1/2,-1/2,-1/2),7 Vector3.new(-1/2,-1/2, 1/2),0 Vector3.new( 1/2,-1/2,-1/2),6 Vector3.new( 1/2,-1/2, 1/2),1 Vector3.new( 1/2, 1/2,-1/2),5 } */ #[derive(Hash,PartialEq,Eq)] pub enum CornerWedgeFace{ Right, TopBack, TopLeft, Bottom, Front, } const CORNERWEDGE_DEFAULT_NORMALS:[Planar64Vec3;5]=[ Planar64Vec3::int( 1, 0, 0),//CornerWedge::Right Planar64Vec3::int( 0, 1, 1),//CornerWedge::BackTop Planar64Vec3::int(-1, 1, 0),//CornerWedge::LeftTop Planar64Vec3::int( 0,-1, 0),//CornerWedge::Bottom Planar64Vec3::int( 0, 0,-1),//CornerWedge::Front ]; pub fn unit_sphere(render:RenderConfigId)->Mesh{ unit_cube(render) } #[derive(Default)] pub struct CubeFaceDescription([Option;6]); impl CubeFaceDescription{ pub fn insert(&mut self,index:CubeFace,value:FaceDescription){ self.0[index as usize]=Some(value); } pub fn pairs(self)->std::iter::FilterMap,6>>,impl FnMut((usize,Option))->Option<(usize,FaceDescription)>>{ self.0.into_iter().enumerate().filter_map(|v|v.1.map(|u|(v.0,u))) } } pub fn unit_cube(render:RenderConfigId)->Mesh{ let mut t=CubeFaceDescription::default(); t.insert(CubeFace::Right,FaceDescription::new_with_render_id(render)); t.insert(CubeFace::Top,FaceDescription::new_with_render_id(render)); t.insert(CubeFace::Back,FaceDescription::new_with_render_id(render)); t.insert(CubeFace::Left,FaceDescription::new_with_render_id(render)); t.insert(CubeFace::Bottom,FaceDescription::new_with_render_id(render)); t.insert(CubeFace::Front,FaceDescription::new_with_render_id(render)); generate_partial_unit_cube(t) } pub fn unit_cylinder(render:RenderConfigId)->Mesh{ //lmao unit_cube(render) } #[derive(Default)] pub struct WedgeFaceDescription([Option;5]); impl WedgeFaceDescription{ pub fn insert(&mut self,index:WedgeFace,value:FaceDescription){ self.0[index as usize]=Some(value); } pub fn pairs(self)->std::iter::FilterMap,5>>,impl FnMut((usize,Option))->Option<(usize,FaceDescription)>>{ self.0.into_iter().enumerate().filter_map(|v|v.1.map(|u|(v.0,u))) } } pub fn unit_wedge(render:RenderConfigId)->Mesh{ let mut t=WedgeFaceDescription::default(); t.insert(WedgeFace::Right,FaceDescription::new_with_render_id(render)); t.insert(WedgeFace::TopFront,FaceDescription::new_with_render_id(render)); t.insert(WedgeFace::Back,FaceDescription::new_with_render_id(render)); t.insert(WedgeFace::Left,FaceDescription::new_with_render_id(render)); t.insert(WedgeFace::Bottom,FaceDescription::new_with_render_id(render)); generate_partial_unit_wedge(t) } #[derive(Default)] pub struct CornerWedgeFaceDescription([Option;5]); impl CornerWedgeFaceDescription{ pub fn insert(&mut self,index:CornerWedgeFace,value:FaceDescription){ self.0[index as usize]=Some(value); } pub fn pairs(self)->std::iter::FilterMap,5>>,impl FnMut((usize,Option))->Option<(usize,FaceDescription)>>{ self.0.into_iter().enumerate().filter_map(|v|v.1.map(|u|(v.0,u))) } } pub fn unit_cornerwedge(render:RenderConfigId)->Mesh{ let mut t=CornerWedgeFaceDescription::default(); t.insert(CornerWedgeFace::Right,FaceDescription::new_with_render_id(render)); t.insert(CornerWedgeFace::TopBack,FaceDescription::new_with_render_id(render)); t.insert(CornerWedgeFace::TopLeft,FaceDescription::new_with_render_id(render)); t.insert(CornerWedgeFace::Bottom,FaceDescription::new_with_render_id(render)); t.insert(CornerWedgeFace::Front,FaceDescription::new_with_render_id(render)); generate_partial_unit_cornerwedge(t) } #[derive(Clone)] pub struct FaceDescription{ pub render:RenderConfigId, pub transform:glam::Affine2, pub color:Color4, } impl FaceDescription{ pub fn new_with_render_id(render:RenderConfigId)->Self { Self{ render, transform:glam::Affine2::IDENTITY, color:Color4::new(1.0,1.0,1.0,0.0),//zero alpha to hide the default texture } } } pub fn generate_partial_unit_cube(face_descriptions:CubeFaceDescription)->Mesh{ let mut generated_pos=Vec::new(); let mut generated_tex=Vec::new(); let mut generated_normal=Vec::new(); let mut generated_color=Vec::new(); let mut generated_vertices=Vec::new(); let mut polygon_groups=Vec::new(); let mut graphics_groups=Vec::new(); let mut physics_group=IndexedPhysicsGroup::default(); let mut transforms=Vec::new(); //note that on a cube every vertex is guaranteed to be unique, so there's no need to hash them against existing vertices. for (face_id,face_description) in face_descriptions.pairs(){ //assume that scanning short lists is faster than hashing. let transform_index=if let Some(transform_index)=transforms.iter().position(|&transform|transform==face_description.transform){ transform_index }else{ //create new transform_index let transform_index=transforms.len(); transforms.push(face_description.transform); generated_tex.extend(CUBE_DEFAULT_TEXTURE_COORDS.map(|tex| face_description.transform.transform_point2(tex) )); transform_index } as u32; let color_index=if let Some(color_index)=generated_color.iter().position(|&color|color==face_description.color){ color_index }else{ //create new color_index let color_index=generated_color.len(); generated_color.push(face_description.color); color_index } as u32; //always push normal let normal_index=generated_normal.len() as u32; generated_normal.push(CUBE_DEFAULT_NORMALS[face_id]); //push vertices as they are needed let group_id=PolygonGroupId::new(polygon_groups.len() as u32); polygon_groups.push(PolygonGroup::PolygonList(PolygonList::new(vec![ CUBE_DEFAULT_POLYS[face_id].map(|tup|{ let pos=CUBE_DEFAULT_VERTICES[tup[0] as usize]; let pos_index=if let Some(pos_index)=generated_pos.iter().position(|&p|p==pos){ pos_index }else{ //create new pos_index let pos_index=generated_pos.len(); generated_pos.push(pos); pos_index } as u32; //always push vertex let vertex=IndexedVertex{ pos:PositionId::new(pos_index), tex:TextureCoordinateId::new(tup[1]+4*transform_index), normal:NormalId::new(normal_index), color:ColorId::new(color_index), }; let vert_index=generated_vertices.len(); generated_vertices.push(vertex); VertexId::new(vert_index as u32) }).to_vec(), ]))); graphics_groups.push(IndexedGraphicsGroup{ render:face_description.render, groups:vec![group_id], }); physics_group.groups.push(group_id); } Mesh{ unique_pos:generated_pos, unique_tex:generated_tex, unique_normal:generated_normal, unique_color:generated_color, unique_vertices:generated_vertices, polygon_groups, graphics_groups, physics_groups:vec![physics_group], } } //don't think too hard about the copy paste because this is all going into the map tool eventually... pub fn generate_partial_unit_wedge(face_descriptions:WedgeFaceDescription)->Mesh{ let wedge_default_polys=[ // right (1, 0, 0) vec![ [6,2,0],//[vertex,tex,norm] [2,0,0], [1,3,0], ], // FrontTop (0, 1, -1) vec![ [3,1,1], [2,0,1], [6,3,1], [7,2,1], ], // back (0, 0, 1) vec![ [0,3,2], [1,2,2], [2,1,2], [3,0,2], ], // left (-1, 0, 0) vec![ [0,2,3], [3,1,3], [7,3,3], ], // bottom (0,-1, 0) vec![ [1,1,4], [0,0,4], [7,3,4], [6,2,4], ], ]; let mut generated_pos=Vec::new(); let mut generated_tex=Vec::new(); let mut generated_normal=Vec::new(); let mut generated_color=Vec::new(); let mut generated_vertices=Vec::new(); let mut polygon_groups=Vec::new(); let mut graphics_groups=Vec::new(); let mut physics_group=IndexedPhysicsGroup::default(); let mut transforms=Vec::new(); //note that on a cube every vertex is guaranteed to be unique, so there's no need to hash them against existing vertices. for (face_id,face_description) in face_descriptions.pairs(){ //assume that scanning short lists is faster than hashing. let transform_index=if let Some(transform_index)=transforms.iter().position(|&transform|transform==face_description.transform){ transform_index }else{ //create new transform_index let transform_index=transforms.len(); transforms.push(face_description.transform); generated_tex.extend(CUBE_DEFAULT_TEXTURE_COORDS.map(|tex| face_description.transform.transform_point2(tex) )); transform_index } as u32; let color_index=if let Some(color_index)=generated_color.iter().position(|&color|color==face_description.color){ color_index }else{ //create new color_index let color_index=generated_color.len(); generated_color.push(face_description.color); color_index } as u32; //always push normal let normal_index=generated_normal.len() as u32; generated_normal.push(WEDGE_DEFAULT_NORMALS[face_id]); //push vertices as they are needed let group_id=PolygonGroupId::new(polygon_groups.len() as u32); polygon_groups.push(PolygonGroup::PolygonList(PolygonList::new(vec![ wedge_default_polys[face_id].iter().map(|tup|{ let pos=CUBE_DEFAULT_VERTICES[tup[0] as usize]; let pos_index=if let Some(pos_index)=generated_pos.iter().position(|&p|p==pos){ pos_index }else{ //create new pos_index let pos_index=generated_pos.len(); generated_pos.push(pos); pos_index } as u32; //always push vertex let vertex=IndexedVertex{ pos:PositionId::new(pos_index), tex:TextureCoordinateId::new(tup[1]+4*transform_index), normal:NormalId::new(normal_index), color:ColorId::new(color_index), }; let vert_index=generated_vertices.len(); generated_vertices.push(vertex); VertexId::new(vert_index as u32) }).collect() ]))); graphics_groups.push(IndexedGraphicsGroup{ render:face_description.render, groups:vec![group_id], }); physics_group.groups.push(group_id); } Mesh{ unique_pos:generated_pos, unique_tex:generated_tex, unique_normal:generated_normal, unique_color:generated_color, unique_vertices:generated_vertices, polygon_groups, graphics_groups, physics_groups:vec![physics_group], } } pub fn generate_partial_unit_cornerwedge(face_descriptions:CornerWedgeFaceDescription)->Mesh{ let cornerwedge_default_polys=[ // right (1, 0, 0) vec![ [6,2,0],//[vertex,tex,norm] [5,1,0], [1,3,0], ], // BackTop (0, 1, 1) vec![ [5,3,1], [0,1,1], [1,0,1], ], // LeftTop (-1, 1, 0) vec![ [5,3,2], [7,2,2], [0,1,2], ], // bottom (0,-1, 0) vec![ [1,1,3], [0,0,3], [7,3,3], [6,2,3], ], // front (0, 0,-1) vec![ [5,0,4], [6,3,4], [7,2,4], ], ]; let mut generated_pos=Vec::new(); let mut generated_tex=Vec::new(); let mut generated_normal=Vec::new(); let mut generated_color=Vec::new(); let mut generated_vertices=Vec::new(); let mut polygon_groups=Vec::new(); let mut graphics_groups=Vec::new(); let mut physics_group=IndexedPhysicsGroup::default(); let mut transforms=Vec::new(); //note that on a cube every vertex is guaranteed to be unique, so there's no need to hash them against existing vertices. for (face_id,face_description) in face_descriptions.pairs(){ //assume that scanning short lists is faster than hashing. let transform_index=if let Some(transform_index)=transforms.iter().position(|&transform|transform==face_description.transform){ transform_index }else{ //create new transform_index let transform_index=transforms.len(); transforms.push(face_description.transform); generated_tex.extend(CUBE_DEFAULT_TEXTURE_COORDS.map(|tex| face_description.transform.transform_point2(tex) )); transform_index } as u32; let color_index=if let Some(color_index)=generated_color.iter().position(|&color|color==face_description.color){ color_index }else{ //create new color_index let color_index=generated_color.len(); generated_color.push(face_description.color); color_index } as u32; //always push normal let normal_index=generated_normal.len() as u32; generated_normal.push(CORNERWEDGE_DEFAULT_NORMALS[face_id]); //push vertices as they are needed let group_id=PolygonGroupId::new(polygon_groups.len() as u32); polygon_groups.push(PolygonGroup::PolygonList(PolygonList::new(vec![ cornerwedge_default_polys[face_id].iter().map(|tup|{ let pos=CUBE_DEFAULT_VERTICES[tup[0] as usize]; let pos_index=if let Some(pos_index)=generated_pos.iter().position(|&p|p==pos){ pos_index }else{ //create new pos_index let pos_index=generated_pos.len(); generated_pos.push(pos); pos_index } as u32; //always push vertex let vertex=IndexedVertex{ pos:PositionId::new(pos_index), tex:TextureCoordinateId::new(tup[1]+4*transform_index), normal:NormalId::new(normal_index), color:ColorId::new(color_index), }; let vert_index=generated_vertices.len(); generated_vertices.push(vertex); VertexId::new(vert_index as u32) }).collect(), ]))); graphics_groups.push(IndexedGraphicsGroup{ render:face_description.render, groups:vec![group_id], }); physics_group.groups.push(group_id); } Mesh{ unique_pos:generated_pos, unique_tex:generated_tex, unique_normal:generated_normal, unique_color:generated_color, unique_vertices:generated_vertices, polygon_groups, graphics_groups, physics_groups:vec![physics_group], } }