This commit is contained in:
Quaternions 2025-01-30 10:55:01 -08:00
parent 1f95c608f0
commit b42b29b994

@ -6,7 +6,6 @@ use strafesnet_common::integer::vec3;
#[derive(Debug)] #[derive(Debug)]
pub enum Error{ pub enum Error{
Block, Block,
NotSupposedToHappen,
MissingVertexId(u32), MissingVertexId(u32),
Planar64Vec3(strafesnet_common::integer::Planar64TryFromFloatError), Planar64Vec3(strafesnet_common::integer::Planar64TryFromFloatError),
RobloxPhysicsData(rbx_mesh::physics_data::Error), RobloxPhysicsData(rbx_mesh::physics_data::Error),
@ -54,78 +53,78 @@ impl MeshDataNormalChecker{
impl std::error::Error for Error{} impl std::error::Error for Error{}
pub fn convert(roblox_physics_data:&[u8],roblox_mesh_data:&[u8])->Result<model::Mesh,Error>{ pub fn convert(roblox_physics_data:&[u8],roblox_mesh_data:&[u8])->Result<model::Mesh,Error>{
match (roblox_physics_data,roblox_mesh_data){ const NORMAL_FACES:usize=6;
(b"",b"")=>return Err(Error::Block), let mut polygon_groups_normal_id=vec![Vec::new();NORMAL_FACES];
(b"",_)
|(_,b"")=>return Err(Error::NotSupposedToHappen),
_=>(),
}
// graphical
let mesh_data=rbx_mesh::read_mesh_data_versioned(
std::io::Cursor::new(roblox_mesh_data)
).map_err(Error::RobloxMeshData)?;
let graphics_mesh=match mesh_data{
rbx_mesh::mesh_data::CSGPHS::CSGK(_)=>return Err(Error::NotSupposedToHappen),
rbx_mesh::mesh_data::CSGPHS::CSGPHS2(mesh_data2)=>mesh_data2.mesh,
rbx_mesh::mesh_data::CSGPHS::CSGPHS4(mesh_data4)=>mesh_data4.mesh,
};
// physical
let physics_data=rbx_mesh::read_physics_data(
std::io::Cursor::new(roblox_physics_data)
).map_err(Error::RobloxPhysicsData)?;
let physics_convex_meshes=match physics_data{
rbx_mesh::physics_data::PhysicsData::CSGK(_)
// have not seen this format in practice
|rbx_mesh::physics_data::PhysicsData::CSGPHS(rbx_mesh::physics_data::CSGPHS::Block)
=>return Err(Error::NotSupposedToHappen),
rbx_mesh::physics_data::PhysicsData::CSGPHS(rbx_mesh::physics_data::CSGPHS::Meshes(meshes))
=>meshes.meshes,
rbx_mesh::physics_data::PhysicsData::CSGPHS(rbx_mesh::physics_data::CSGPHS::PhysicsInfoMesh(pim))
=>vec![pim.mesh],
};
// build graphics and physics meshes // build graphics and physics meshes
let mut mb=strafesnet_common::model::MeshBuilder::new(); let mut mb=strafesnet_common::model::MeshBuilder::new();
// graphics // graphics
const NORMAL_FACES:usize=6; let graphics_groups=if !roblox_mesh_data.is_empty(){
let mut polygon_groups_normal_id=vec![Vec::new();NORMAL_FACES]; let mesh_data=rbx_mesh::read_mesh_data_versioned(
for [vertex_id0,vertex_id1,vertex_id2] in graphics_mesh.faces{ std::io::Cursor::new(roblox_mesh_data)
let face=[ ).map_err(Error::RobloxMeshData)?;
graphics_mesh.vertices.get(vertex_id0.0 as usize).ok_or(Error::MissingVertexId(vertex_id0.0))?, let graphics_mesh=match mesh_data{
graphics_mesh.vertices.get(vertex_id1.0 as usize).ok_or(Error::MissingVertexId(vertex_id1.0))?, rbx_mesh::mesh_data::CSGPHS::CSGK(_)=>return Err(Error::Block),
graphics_mesh.vertices.get(vertex_id2.0 as usize).ok_or(Error::MissingVertexId(vertex_id2.0))?, rbx_mesh::mesh_data::CSGPHS::CSGPHS2(mesh_data2)=>mesh_data2.mesh,
]; rbx_mesh::mesh_data::CSGPHS::CSGPHS4(mesh_data4)=>mesh_data4.mesh,
let mut normal_agreement_checker=MeshDataNormalChecker::new(); };
let face=face.into_iter().map(|vertex|{ for [vertex_id0,vertex_id1,vertex_id2] in graphics_mesh.faces{
normal_agreement_checker.check(vertex.normal_id); let face=[
let pos=mb.acquire_pos_id(vec3::try_from_f32_array(vertex.pos)?); graphics_mesh.vertices.get(vertex_id0.0 as usize).ok_or(Error::MissingVertexId(vertex_id0.0))?,
let normal=mb.acquire_normal_id(vec3::try_from_f32_array(vertex.norm)?); graphics_mesh.vertices.get(vertex_id1.0 as usize).ok_or(Error::MissingVertexId(vertex_id1.0))?,
let tex=mb.acquire_tex_id(glam::Vec2::from_array(vertex.tex)); graphics_mesh.vertices.get(vertex_id2.0 as usize).ok_or(Error::MissingVertexId(vertex_id2.0))?,
let color=mb.acquire_color_id(glam::Vec4::from_array(vertex.color.map(|f|f as f32/255.0f32))); ];
Ok(mb.acquire_vertex_id(IndexedVertex{pos,tex,normal,color})) let mut normal_agreement_checker=MeshDataNormalChecker::new();
}).collect::<Result<Vec<_>,_>>().map_err(Error::Planar64Vec3)?; let face=face.into_iter().map(|vertex|{
if let Some(normal_id)=normal_agreement_checker.into_agreed_normal(){ normal_agreement_checker.check(vertex.normal_id);
polygon_groups_normal_id[normal_id as usize-1].push(face); let pos=mb.acquire_pos_id(vec3::try_from_f32_array(vertex.pos)?);
}else{ let normal=mb.acquire_normal_id(vec3::try_from_f32_array(vertex.norm)?);
panic!("Empty face!"); let tex=mb.acquire_tex_id(glam::Vec2::from_array(vertex.tex));
let color=mb.acquire_color_id(glam::Vec4::from_array(vertex.color.map(|f|f as f32/255.0f32)));
Ok(mb.acquire_vertex_id(IndexedVertex{pos,tex,normal,color}))
}).collect::<Result<Vec<_>,_>>().map_err(Error::Planar64Vec3)?;
if let Some(normal_id)=normal_agreement_checker.into_agreed_normal(){
polygon_groups_normal_id[normal_id as usize-1].push(face);
}else{
panic!("Empty face!");
}
} }
} (0..polygon_groups_normal_id.len()).map(|polygon_group_id|{
let graphics_groups=(0..polygon_groups_normal_id.len()).map(|polygon_group_id|{ model::IndexedGraphicsGroup{
model::IndexedGraphicsGroup{ render:RenderConfigId::new(0),
render:RenderConfigId::new(0), groups:vec![PolygonGroupId::new(polygon_group_id as u32)]
groups:vec![PolygonGroupId::new(polygon_group_id as u32)] }
} }).collect()
}).collect(); }else{
Vec::new()
};
//physics //physics
let color=mb.acquire_color_id(glam::Vec4::ONE); let physics_convex_meshes=if !roblox_physics_data.is_empty(){
let tex=mb.acquire_tex_id(glam::Vec2::ZERO); let physics_data=rbx_mesh::read_physics_data(
std::io::Cursor::new(roblox_physics_data)
).map_err(Error::RobloxPhysicsData)?;
let physics_convex_meshes=match physics_data{
rbx_mesh::physics_data::PhysicsData::CSGK(_)
// have not seen this format in practice
|rbx_mesh::physics_data::PhysicsData::CSGPHS(rbx_mesh::physics_data::CSGPHS::Block)
=>return Err(Error::Block),
rbx_mesh::physics_data::PhysicsData::CSGPHS(rbx_mesh::physics_data::CSGPHS::Meshes(meshes))
=>meshes.meshes,
rbx_mesh::physics_data::PhysicsData::CSGPHS(rbx_mesh::physics_data::CSGPHS::PhysicsInfoMesh(pim))
=>vec![pim.mesh],
};
physics_convex_meshes
}else{
Vec::new()
};
let polygon_groups:Vec<PolygonGroup>=polygon_groups_normal_id.into_iter().map(|faces| let polygon_groups:Vec<PolygonGroup>=polygon_groups_normal_id.into_iter().map(|faces|
// graphics polygon groups (to be rendered) // graphics polygon groups (to be rendered)
Ok(PolygonGroup::PolygonList(PolygonList::new(faces))) Ok(PolygonGroup::PolygonList(PolygonList::new(faces)))
).chain(physics_convex_meshes.into_iter().map(|mesh|{ ).chain(physics_convex_meshes.into_iter().map(|mesh|{
// this can be factored out of the loop but I am lazy
let color=mb.acquire_color_id(glam::Vec4::ONE);
let tex=mb.acquire_tex_id(glam::Vec2::ZERO);
// physics polygon groups (to do physics) // physics polygon groups (to do physics)
Ok(PolygonGroup::PolygonList(PolygonList::new(mesh.faces.into_iter().map(|[vertex_id0,vertex_id1,vertex_id2]|{ Ok(PolygonGroup::PolygonList(PolygonList::new(mesh.faces.into_iter().map(|[vertex_id0,vertex_id1,vertex_id2]|{
let face=[ let face=[