PlanesToFacesError

This commit is contained in:
Quaternions 2025-02-05 10:54:23 -08:00
parent af3f9cf1fe
commit 2c4ec76c96

@ -28,22 +28,21 @@ fn solve3(c0:&Face,c1:&Face,c2:&Face)->Option<Ratio<Vector3<Fixed<3,96>>,Fixed<3
} }
#[derive(Debug)] #[derive(Debug)]
pub enum BrushToMeshError{ pub enum PlanesToFacesError{
SliceBrushSides, InitFace1,
MissingPlane, InitFace2,
InvalidFaceCount{ InitIntersection,
count:usize, FindNewIntersection,
}, EmptyFaces,
InvalidPlanes,
} }
impl std::fmt::Display for BrushToMeshError{ impl std::fmt::Display for PlanesToFacesError{
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
write!(f,"{self:?}") write!(f,"{self:?}")
} }
} }
impl core::error::Error for BrushToMeshError{} impl core::error::Error for PlanesToFacesError{}
fn planes_to_faces(face_list:std::collections::HashSet<Face>)->Option<Faces>{ fn planes_to_faces(face_list:std::collections::HashSet<Face>)->Result<Faces,PlanesToFacesError>{
let mut faces=Vec::new(); let mut faces=Vec::new();
// for each face, determine one edge at a time until you complete the face // for each face, determine one edge at a time until you complete the face
'face: for face0 in &face_list{ 'face: for face0 in &face_list{
@ -58,7 +57,7 @@ fn planes_to_faces(face_list:std::collections::HashSet<Face>)->Option<Faces>{
// find the most perpendicular face to face0 // find the most perpendicular face to face0
let mut face1=face_list.iter().min_by_key(|&p|{ let mut face1=face_list.iter().min_by_key(|&p|{
face0.normal.dot(p.normal).abs() face0.normal.dot(p.normal).abs()
})?; }).ok_or(PlanesToFacesError::InitFace1)?;
// direction of edge formed by face0 x face1 // direction of edge formed by face0 x face1
let edge_dir=face0.normal.cross(face1.normal); let edge_dir=face0.normal.cross(face1.normal);
@ -67,9 +66,9 @@ fn planes_to_faces(face_list:std::collections::HashSet<Face>)->Option<Faces>{
let mut face2=face_list.iter().max_by_key(|&p|{ let mut face2=face_list.iter().max_by_key(|&p|{
// find the best *oriented* face (no .abs()) // find the best *oriented* face (no .abs())
edge_dir.dot(p.normal) edge_dir.dot(p.normal)
})?; }).ok_or(PlanesToFacesError::InitFace2)?;
let mut intersection=solve3(face0,face1,face2)?; let mut intersection=solve3(face0,face1,face2).ok_or(PlanesToFacesError::InitIntersection)?;
// repeatedly update face0, face1 until all faces form part of the convex solid // repeatedly update face0, face1 until all faces form part of the convex solid
'find: loop{ 'find: loop{
@ -164,7 +163,7 @@ fn planes_to_faces(face_list:std::collections::HashSet<Face>)->Option<Faces>{
} }
Some((new_face,new_intersection,d_new_intersection)) Some((new_face,new_intersection,d_new_intersection))
}).min_by_key(|&(_,_,d)|d)?; }).min_by_key(|&(_,_,d)|d).ok_or(PlanesToFacesError::FindNewIntersection)?;
// we looped back around to face1, we're done! // we looped back around to face1, we're done!
if core::ptr::eq(face1,new_face){ if core::ptr::eq(face1,new_face){
@ -179,14 +178,30 @@ fn planes_to_faces(face_list:std::collections::HashSet<Face>)->Option<Faces>{
} }
if faces.is_empty(){ if faces.is_empty(){
None Err(PlanesToFacesError::EmptyFaces)
}else{ }else{
Some(Faces{ Ok(Faces{
faces, faces,
}) })
} }
} }
#[derive(Debug)]
pub enum BrushToMeshError{
SliceBrushSides,
MissingPlane,
InvalidFaceCount{
count:usize,
},
InvalidPlanes(PlanesToFacesError),
}
impl std::fmt::Display for BrushToMeshError{
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
write!(f,"{self:?}")
}
}
impl core::error::Error for BrushToMeshError{}
pub fn brush_to_mesh(bsp:&vbsp::Bsp,brush:&vbsp::Brush)->Result<model::Mesh,BrushToMeshError>{ pub fn brush_to_mesh(bsp:&vbsp::Bsp,brush:&vbsp::Brush)->Result<model::Mesh,BrushToMeshError>{
let brush_start_idx=brush.brush_side as usize; let brush_start_idx=brush.brush_side as usize;
let sides_range=brush_start_idx..brush_start_idx+brush.num_brush_sides as usize; let sides_range=brush_start_idx..brush_start_idx+brush.num_brush_sides as usize;
@ -203,7 +218,7 @@ pub fn brush_to_mesh(bsp:&vbsp::Bsp,brush:&vbsp::Brush)->Result<model::Mesh,Brus
return Err(BrushToMeshError::InvalidFaceCount{count:face_list.len()}); return Err(BrushToMeshError::InvalidFaceCount{count:face_list.len()});
} }
let faces=planes_to_faces(face_list).ok_or(BrushToMeshError::InvalidPlanes)?; let faces=planes_to_faces(face_list).map_err(BrushToMeshError::InvalidPlanes)?;
// generate the mesh // generate the mesh
let mut polygon_list=Vec::new(); let mut polygon_list=Vec::new();