diff --git a/lib/rbx_loader/src/primitives.rs b/lib/rbx_loader/src/primitives.rs index c2d3319d8..2ce21ae9b 100644 --- a/lib/rbx_loader/src/primitives.rs +++ b/lib/rbx_loader/src/primitives.rs @@ -1,6 +1,6 @@ use crate::rbx::{RobloxPartDescription,RobloxWedgeDescription,RobloxCornerWedgeDescription}; -use strafesnet_common::model::{Color4,TextureCoordinate,Mesh,IndexedGraphicsGroup,IndexedPhysicsGroup,IndexedVertex,PolygonGroupId,PolygonGroup,PolygonList,PositionId,TextureCoordinateId,NormalId,ColorId,VertexId,RenderConfigId}; -use strafesnet_common::integer::{vec3,Planar64Vec3}; +use strafesnet_common::model::{Color4,TextureCoordinate,Mesh,MeshBuilder,IndexedGraphicsGroup,IndexedPhysicsGroup,IndexedVertex,PolygonGroupId,PolygonGroup,PolygonList,PositionId,TextureCoordinateId,NormalId,ColorId,VertexId,RenderConfigId}; +use strafesnet_common::integer::{vec3,Planar64,Planar64Vec3}; #[derive(Debug)] pub enum Primitives{ @@ -480,3 +480,132 @@ pub fn generate_partial_unit_cornerwedge(CornerWedgeFaceDescription(face_descrip physics_groups:vec![physics_group], } } + +pub fn generate_partial_cylinder(face_descriptions:CubeFaceDescription)->Mesh{ + // cylinder is oriented about the x axis + // roblox cylinders use projected grid coordinates + /// how many grid coordinates to use (positive and negative) + const GON:i32=3; + /// grid perimeter + const POINTS:[[i32;2];4*2*GON as usize]=const{ + let mut points=[[0;2];{4*2*GON as usize}]; + let mut i=-GON; + while i<GON{ + points[(i+GON) as usize]=[i,GON]; + points[(i+GON+1*2*GON) as usize]=[GON,-i]; + points[(i+GON+2*2*GON) as usize]=[-i,-GON]; + points[(i+GON+3*2*GON) as usize]=[-GON,i]; + i+=1; + } + points + }; + + let mut mb=MeshBuilder::new(); + let mut polygon_groups=Vec::with_capacity(CubeFaceDescription::FACES); + let mut graphics_groups=Vec::with_capacity(CubeFaceDescription::FACES); + let mut physics_group=IndexedPhysicsGroup{groups:Vec::with_capacity(CubeFaceDescription::FACES)}; + let CubeFaceDescription([right,top,back,left,bottom,front])=face_descriptions; + + macro_rules! end_face{ + ($face_description:expr,$end:expr,$iter:expr)=>{ + let normal=mb.acquire_normal_id($end); + let color=mb.acquire_color_id($face_description.color); + + // single polygon for physics + let polygon:Vec<_>=$iter.map(|[x,y]|{ + let tex=mb.acquire_tex_id( + $face_description.transform.transform_point2( + (glam::vec2(-x as f32,y as f32).normalize()+1.0)/2.0 + ) + ); + let pos=mb.acquire_pos_id($end+vec3::int(0,-x,y).with_length(Planar64::ONE).divide().wrap_1()); + mb.acquire_vertex_id(IndexedVertex{pos,tex,normal,color}) + }).collect(); + + // fanned polygons for graphics + let pos=mb.acquire_pos_id($end); + let tex=mb.acquire_tex_id($face_description.transform.transform_point2(glam::Vec2::ONE/2.0)); + let center=mb.acquire_vertex_id(IndexedVertex{pos,tex,normal,color}); + let polygon_list=(0..POINTS.len()).map(|i| + vec![center,polygon[i],polygon[(i+1)%POINTS.len()]] + ).collect(); + + // end face graphics + let group_id=PolygonGroupId::new(polygon_groups.len() as u32); + polygon_groups.push(PolygonGroup::PolygonList(PolygonList::new(polygon_list))); + graphics_groups.push(IndexedGraphicsGroup{ + render:$face_description.render, + groups:vec![group_id], + }); + + // end face physics + let polygon_list=vec![polygon]; + + let group_id=PolygonGroupId::new(polygon_groups.len() as u32); + polygon_groups.push(PolygonGroup::PolygonList(PolygonList::new(polygon_list))); + physics_group.groups.push(group_id); + } + } + macro_rules! tex{ + ($face_description:expr,$tex:expr)=>{{ + let [x,y]=$tex; + $face_description.transform.transform_point2( + glam::vec2((x+GON) as f32,(y+GON) as f32)/(2*GON) as f32 + ) + }}; + } + macro_rules! barrel_face{ + ($face_description:expr,$loop:ident,$lo_dir:expr,$hi_dir:expr,$tex_0:expr,$tex_1:expr,$tex_2:expr,$tex_3:expr)=>{ + let mut polygon_list=Vec::with_capacity(CubeFaceDescription::FACES); + for $loop in -GON..GON{ + // lo Z + let lz_dir=$lo_dir.with_length(Planar64::ONE).divide().wrap_1(); + // hi Z + let hz_dir=$hi_dir.with_length(Planar64::ONE).divide().wrap_1(); + + // pos + let lx_lz_pos=mb.acquire_pos_id(vec3::NEG_X+lz_dir); + let lx_hz_pos=mb.acquire_pos_id(vec3::NEG_X+hz_dir); + let hx_hz_pos=mb.acquire_pos_id(vec3::X+hz_dir); + let hx_lz_pos=mb.acquire_pos_id(vec3::X+lz_dir); + // tex + let lx_lz_tex=mb.acquire_tex_id(tex!($face_description,$tex_0)); + let lx_hz_tex=mb.acquire_tex_id(tex!($face_description,$tex_1)); + let hx_hz_tex=mb.acquire_tex_id(tex!($face_description,$tex_2)); + let hx_lz_tex=mb.acquire_tex_id(tex!($face_description,$tex_3)); + // norm + let lz_norm=mb.acquire_normal_id(lz_dir); + let hz_norm=mb.acquire_normal_id(hz_dir); + // color + let color=mb.acquire_color_id($face_description.color); + + polygon_list.push(vec![ + mb.acquire_vertex_id(IndexedVertex{pos:lx_lz_pos,tex:lx_lz_tex,normal:lz_norm,color}), + mb.acquire_vertex_id(IndexedVertex{pos:lx_hz_pos,tex:lx_hz_tex,normal:hz_norm,color}), + mb.acquire_vertex_id(IndexedVertex{pos:hx_hz_pos,tex:hx_hz_tex,normal:hz_norm,color}), + mb.acquire_vertex_id(IndexedVertex{pos:hx_lz_pos,tex:hx_lz_tex,normal:lz_norm,color}), + ]); + } + + // push face + let group_id=PolygonGroupId::new(polygon_groups.len() as u32); + polygon_groups.push(PolygonGroup::PolygonList(PolygonList::new(polygon_list))); + graphics_groups.push(IndexedGraphicsGroup{ + render:$face_description.render, + groups:vec![group_id], + }); + physics_group.groups.push(group_id); + }; + } + + end_face!(right, vec3::X,POINTS.into_iter()); + barrel_face!(top, z,vec3::int(0,GON,z),vec3::int(0,GON,z+1), [GON,z],[GON,z+1],[-GON,z+1],[-GON,z]); + barrel_face!(back, y,vec3::int(0,y+1,GON),vec3::int(0,y,GON), [GON,y+1],[GON,y],[-GON,y],[-GON,y+1]); + end_face!(left, vec3::NEG_X,POINTS.into_iter().rev()); + barrel_face!(bottom, z,vec3::int(0,-GON,z+1),vec3::int(0,-GON,z), [-GON,z+1],[-GON,z],[GON,z],[GON,z+1]); + barrel_face!(front, y,vec3::int(0,y,-GON),vec3::int(0,y+1,-GON), [-GON,y],[-GON,y+1],[GON,y+1],[GON,y]); + + let physics_groups=vec![physics_group]; + + mb.build(polygon_groups,graphics_groups,physics_groups) +} diff --git a/lib/rbx_loader/src/rbx.rs b/lib/rbx_loader/src/rbx.rs index 8f2a14b06..11d497b7f 100644 --- a/lib/rbx_loader/src/rbx.rs +++ b/lib/rbx_loader/src/rbx.rs @@ -611,8 +611,8 @@ pub fn convert<'a>( let mesh_id=model::MeshId::new(primitive_meshes.len() as u32); mesh_id_from_description.insert(basepart_description.clone(),mesh_id);//borrow checker going crazy let mesh=match basepart_description{ + RobloxBasePartDescription::Cylinder(part_texture_description)=>primitives::generate_partial_cylinder(CubeFaceDescription::new(part_texture_description,textureless_render_group)), RobloxBasePartDescription::Sphere(part_texture_description) - |RobloxBasePartDescription::Cylinder(part_texture_description) |RobloxBasePartDescription::Part(part_texture_description)=>primitives::generate_partial_unit_cube(CubeFaceDescription::new(part_texture_description,textureless_render_group)), RobloxBasePartDescription::Wedge(wedge_texture_description)=>primitives::generate_partial_unit_wedge(WedgeFaceDescription::new(wedge_texture_description,textureless_render_group)), RobloxBasePartDescription::CornerWedge(cornerwedge_texture_description)=>primitives::generate_partial_unit_cornerwedge(CornerWedgeFaceDescription::new(cornerwedge_texture_description,textureless_render_group)),