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)]
pub enum Error{
Block,
NotSupposedToHappen,
MissingVertexId(u32),
Planar64Vec3(strafesnet_common::integer::Planar64TryFromFloatError),
RobloxPhysicsData(rbx_mesh::physics_data::Error),
@ -54,78 +53,78 @@ impl MeshDataNormalChecker{
impl std::error::Error for Error{}
pub fn convert(roblox_physics_data:&[u8],roblox_mesh_data:&[u8])->Result<model::Mesh,Error>{
match (roblox_physics_data,roblox_mesh_data){
(b"",b"")=>return Err(Error::Block),
(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],
};
const NORMAL_FACES:usize=6;
let mut polygon_groups_normal_id=vec![Vec::new();NORMAL_FACES];
// build graphics and physics meshes
let mut mb=strafesnet_common::model::MeshBuilder::new();
// graphics
const NORMAL_FACES:usize=6;
let mut polygon_groups_normal_id=vec![Vec::new();NORMAL_FACES];
for [vertex_id0,vertex_id1,vertex_id2] in graphics_mesh.faces{
let face=[
graphics_mesh.vertices.get(vertex_id0.0 as usize).ok_or(Error::MissingVertexId(vertex_id0.0))?,
graphics_mesh.vertices.get(vertex_id1.0 as usize).ok_or(Error::MissingVertexId(vertex_id1.0))?,
graphics_mesh.vertices.get(vertex_id2.0 as usize).ok_or(Error::MissingVertexId(vertex_id2.0))?,
];
let mut normal_agreement_checker=MeshDataNormalChecker::new();
let face=face.into_iter().map(|vertex|{
normal_agreement_checker.check(vertex.normal_id);
let pos=mb.acquire_pos_id(vec3::try_from_f32_array(vertex.pos)?);
let normal=mb.acquire_normal_id(vec3::try_from_f32_array(vertex.norm)?);
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!");
let graphics_groups=if !roblox_mesh_data.is_empty(){
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::Block),
rbx_mesh::mesh_data::CSGPHS::CSGPHS2(mesh_data2)=>mesh_data2.mesh,
rbx_mesh::mesh_data::CSGPHS::CSGPHS4(mesh_data4)=>mesh_data4.mesh,
};
for [vertex_id0,vertex_id1,vertex_id2] in graphics_mesh.faces{
let face=[
graphics_mesh.vertices.get(vertex_id0.0 as usize).ok_or(Error::MissingVertexId(vertex_id0.0))?,
graphics_mesh.vertices.get(vertex_id1.0 as usize).ok_or(Error::MissingVertexId(vertex_id1.0))?,
graphics_mesh.vertices.get(vertex_id2.0 as usize).ok_or(Error::MissingVertexId(vertex_id2.0))?,
];
let mut normal_agreement_checker=MeshDataNormalChecker::new();
let face=face.into_iter().map(|vertex|{
normal_agreement_checker.check(vertex.normal_id);
let pos=mb.acquire_pos_id(vec3::try_from_f32_array(vertex.pos)?);
let normal=mb.acquire_normal_id(vec3::try_from_f32_array(vertex.norm)?);
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!");
}
}
}
let graphics_groups=(0..polygon_groups_normal_id.len()).map(|polygon_group_id|{
model::IndexedGraphicsGroup{
render:RenderConfigId::new(0),
groups:vec![PolygonGroupId::new(polygon_group_id as u32)]
}
}).collect();
(0..polygon_groups_normal_id.len()).map(|polygon_group_id|{
model::IndexedGraphicsGroup{
render:RenderConfigId::new(0),
groups:vec![PolygonGroupId::new(polygon_group_id as u32)]
}
}).collect()
}else{
Vec::new()
};
//physics
let color=mb.acquire_color_id(glam::Vec4::ONE);
let tex=mb.acquire_tex_id(glam::Vec2::ZERO);
let physics_convex_meshes=if !roblox_physics_data.is_empty(){
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|
// graphics polygon groups (to be rendered)
Ok(PolygonGroup::PolygonList(PolygonList::new(faces)))
).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)
Ok(PolygonGroup::PolygonList(PolygonList::new(mesh.faces.into_iter().map(|[vertex_id0,vertex_id1,vertex_id2]|{
let face=[