diff --git a/src/mesh.rs b/src/mesh.rs index c6a2196..8cda1fb 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -1,4 +1,177 @@ -pub fn convert(roblox_mesh_bytes:crate::data::RobloxMeshBytes)->Result{ - let versioned_mesh=rbx_mesh::read_versioned(roblox_mesh_bytes.cursor())?; +use std::collections::HashMap; + +use rbx_mesh::mesh::{Vertex2, Vertex2Truncated}; +use strafesnet_common::{integer::Planar64Vec3,model::{self,ColorId,IndexedVertex,NormalId,PolygonList,PositionId,TextureCoordinateId,VertexId}}; + +pub enum Error{ + Planar64Vec3(strafesnet_common::integer::Planar64TryFromFloatError), + RbxMesh(rbx_mesh::mesh::Error) +} + +fn ingest_vertices2< + AcquirePosId, + AcquireTexId, + AcquireNormalId, + AcquireColorId, + AcquireVertexId, +>( + vertices:Vec, + mut acquire_pos_id:AcquirePosId, + mut acquire_tex_id:AcquireTexId, + mut acquire_normal_id:AcquireNormalId, + mut acquire_color_id:AcquireColorId, + mut acquire_vertex_id:AcquireVertexId, +)->Result,Error> +where + AcquirePosId:FnMut([f32;3])->Result, + AcquireTexId:FnMut([f32;2])->TextureCoordinateId, + AcquireNormalId:FnMut([f32;3])->Result, + AcquireColorId:FnMut([f32;4])->ColorId, + AcquireVertexId:FnMut(IndexedVertex)->VertexId, +{ + //this monster is collecting a map of old_vertices_index -> unique_vertices_index + //while also doing the inserting unique entries into lists simultaneously + Ok(vertices.into_iter().enumerate().map(|(vertex_id,vertex)|Ok(( + VertexId::new(vertex_id as u32), + acquire_vertex_id(IndexedVertex{ + pos:acquire_pos_id(vertex.pos)?, + tex:acquire_tex_id(vertex.tex), + normal:acquire_normal_id(vertex.norm)?, + color:acquire_color_id(vertex.color.map(|f|f as f32)) + }), + ))).collect::>()?) +} +fn ingest_vertices_truncated2< + AcquirePosId, + AcquireTexId, + AcquireNormalId, + AcquireVertexId, +>( + vertices:Vec, + mut acquire_pos_id:AcquirePosId, + mut acquire_tex_id:AcquireTexId, + mut acquire_normal_id:AcquireNormalId, + static_color_id:ColorId,//pick one color and fill everything with it + mut acquire_vertex_id:AcquireVertexId, +)->Result,Error> +where + AcquirePosId:FnMut([f32;3])->Result, + AcquireTexId:FnMut([f32;2])->TextureCoordinateId, + AcquireNormalId:FnMut([f32;3])->Result, + AcquireVertexId:FnMut(IndexedVertex)->VertexId, +{ + //this monster is collecting a map of old_vertices_index -> unique_vertices_index + //while also doing the inserting unique entries into lists simultaneously + Ok(vertices.into_iter().enumerate().map(|(vertex_id,vertex)|Ok(( + VertexId::new(vertex_id as u32), + acquire_vertex_id(IndexedVertex{ + pos:acquire_pos_id(vertex.pos)?, + tex:acquire_tex_id(vertex.tex), + normal:acquire_normal_id(vertex.norm)?, + color:static_color_id + }), + ))).collect::>()?) +} + +pub fn convert(roblox_mesh_bytes:crate::data::RobloxMeshBytes)->Result{ //generate that mesh boi + let mut unique_pos=Vec::new(); + let mut pos_id_from=HashMap::new(); + let mut unique_tex=Vec::new(); + let mut tex_id_from=HashMap::new(); + let mut unique_normal=Vec::new(); + let mut normal_id_from=HashMap::new(); + let mut unique_color=Vec::new(); + let mut color_id_from=HashMap::new(); + let mut unique_vertices=Vec::new(); + let mut vertex_id_from=HashMap::new(); + let mut polygon_groups=Vec::new();//only one group is created + let mut acquire_pos_id=|pos|{ + let p=Planar64Vec3::try_from(pos).map_err(Error::Planar64Vec3)?; + Ok(PositionId::new(*pos_id_from.entry(p).or_insert_with(||{ + let pos_id=unique_pos.len(); + unique_pos.push(p); + pos_id + }) as u32)) + }; + let mut acquire_tex_id=|tex|{ + let h=bytemuck::cast::<[f32;2],[u32;2]>(tex); + TextureCoordinateId::new(*tex_id_from.entry(h).or_insert_with(||{ + let tex_id=unique_tex.len(); + unique_tex.push(glam::Vec2::from_array(tex)); + tex_id + }) as u32) + }; + let mut acquire_normal_id=|normal|{ + let n=Planar64Vec3::try_from(normal).map_err(Error::Planar64Vec3)?; + Ok(NormalId::new(*normal_id_from.entry(n).or_insert_with(||{ + let normal_id=unique_normal.len(); + unique_normal.push(n); + normal_id + }) as u32)) + }; + let mut acquire_color_id=|color|{ + let h=bytemuck::cast::<[f32;4],[u32;4]>(color); + ColorId::new(*color_id_from.entry(h).or_insert_with(||{ + let color_id=unique_color.len(); + unique_color.push(glam::Vec4::from_array(color)); + color_id + }) as u32) + }; + let mut acquire_vertex_id=|vertex:IndexedVertex|{ + VertexId::new(*vertex_id_from.entry(vertex.clone()).or_insert_with(||{ + let vertex_id=unique_vertices.len(); + unique_vertices.push(vertex); + vertex_id + }) as u32) + }; + match rbx_mesh::read_versioned(roblox_mesh_bytes.cursor()).map_err(Error::RbxMesh)?{ + rbx_mesh::mesh::VersionedMesh::Version1(mesh)=>{ + let color_id=acquire_color_id([1.0f32;4]); + polygon_groups.push(model::PolygonGroup::PolygonList(PolygonList::new(mesh.vertices.chunks_exact(3).map(|trip|{ + let mut ingest_vertex1=|vertex:rbx_mesh::mesh::Vertex1|Ok(acquire_vertex_id(IndexedVertex{ + pos:acquire_pos_id(vertex.pos)?, + tex:acquire_tex_id([vertex.tex[0],vertex.tex[1]]), + normal:acquire_normal_id(vertex.norm)?, + color:color_id, + })); + Ok(vec![ingest_vertex1(trip[0])?,ingest_vertex1(trip[1])?,ingest_vertex1(trip[2])?]) + }).collect::>()?))); + }, + rbx_mesh::mesh::VersionedMesh::Version2(mesh)=>{ + let vertex_id_map=match mesh.header.sizeof_vertex{ + rbx_mesh::mesh::SizeOfVertex2::Truncated=>{ + //pick white and make all the vertices white + let color_id=acquire_color_id([1.0f32;4]); + ingest_vertices_truncated2(mesh.vertices_truncated,acquire_pos_id,acquire_tex_id,acquire_normal_id,color_id,acquire_vertex_id)? + }, + rbx_mesh::mesh::SizeOfVertex2::Full=>ingest_vertices2(mesh.vertices,acquire_pos_id,acquire_tex_id,acquire_normal_id,acquire_color_id,acquire_vertex_id)?, + }; + }, + rbx_mesh::mesh::VersionedMesh::Version3(mesh)=>{ + let vertex_id_map=match mesh.header.sizeof_vertex{ + rbx_mesh::mesh::SizeOfVertex2::Truncated=>{ + let color_id=acquire_color_id([1.0f32;4]); + ingest_vertices_truncated2(mesh.vertices_truncated,acquire_pos_id,acquire_tex_id,acquire_normal_id,color_id,acquire_vertex_id)? + }, + rbx_mesh::mesh::SizeOfVertex2::Full=>ingest_vertices2(mesh.vertices,acquire_pos_id,acquire_tex_id,acquire_normal_id,acquire_color_id,acquire_vertex_id)?, + }; + }, + rbx_mesh::mesh::VersionedMesh::Version4(mesh)=>{ + let vertex_id_map=ingest_vertices2(mesh.vertices,acquire_pos_id,acquire_tex_id,acquire_normal_id,acquire_color_id,acquire_vertex_id)?; + }, + rbx_mesh::mesh::VersionedMesh::Version5(mesh)=>{ + let vertex_id_map=ingest_vertices2(mesh.vertices,acquire_pos_id,acquire_tex_id,acquire_normal_id,acquire_color_id,acquire_vertex_id)?; + }, + } + Ok(model::Mesh{ + unique_pos, + unique_normal, + unique_tex, + unique_color, + unique_vertices, + polygon_groups, + graphics_groups:Vec::new(), + physics_groups:Vec::new(), + }) } \ No newline at end of file