THE ALGORITHM
This commit is contained in:
parent
0b63e06ad2
commit
067b5eee3c
@ -34,6 +34,7 @@ pub enum BrushToMeshError{
|
||||
InvalidFaceCount{
|
||||
count:usize,
|
||||
},
|
||||
InvalidPlanes,
|
||||
}
|
||||
impl std::fmt::Display for BrushToMeshError{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
@ -43,6 +44,7 @@ impl std::fmt::Display for BrushToMeshError{
|
||||
impl core::error::Error for BrushToMeshError{}
|
||||
|
||||
fn planes_to_faces(face_list:Vec<Face>)->Option<Faces>{
|
||||
let mut faces=Vec::new();
|
||||
// for each face, determine one edge at a time until you complete the face
|
||||
let mut dedup=std::collections::HashSet::new();
|
||||
'face: for face0 in &face_list{
|
||||
@ -136,33 +138,58 @@ fn planes_to_faces(face_list:Vec<Face>)->Option<Faces>{
|
||||
}
|
||||
|
||||
// === follow edges around face ===
|
||||
// Note that we chose face2 so that the faces create a particular winding order.
|
||||
// Note that we chose face2 such that the 3 faces create a particular winding order.
|
||||
// If we choose a consistent face to follow (face1, face2) it will always wind with a consistent chirality
|
||||
|
||||
// keep looping until we meet this face again
|
||||
let face1=face1;
|
||||
let mut face=Vec::new();
|
||||
loop{
|
||||
// push point onto vertices
|
||||
face.push(intersection.divide().fix_1());
|
||||
|
||||
// the measure
|
||||
let edge_dir=face0.normal.cross(face1.normal);
|
||||
|
||||
// the dot product to beat
|
||||
let d_intersection=edge_dir.dot(intersection.num)/intersection.den;
|
||||
|
||||
for new_face in &face_list{
|
||||
if core::ptr::eq(face0,new_face){
|
||||
continue;
|
||||
// find the next face moving clockwise around face0
|
||||
let (new_face,new_intersection,_)=face_list.iter().filter_map(|new_face|{
|
||||
// ignore faces we've seen before
|
||||
if core::ptr::eq(face0,new_face)
|
||||
|core::ptr::eq(face2,new_face){
|
||||
return None;
|
||||
}
|
||||
if core::ptr::eq(face1,new_face){
|
||||
continue;
|
||||
}
|
||||
if core::ptr::eq(face2,new_face){
|
||||
continue;
|
||||
}
|
||||
if let Some(new_intersection)=solve3(new_face,face1,face2){
|
||||
let new_intersection=solve3(face0,face2,new_face)?;
|
||||
|
||||
// the d value must be larger
|
||||
let d_new_intersection=edge_dir.dot(new_intersection.num)/new_intersection.den;
|
||||
if d_new_intersection.le_ratio(d_intersection){
|
||||
return None;
|
||||
}
|
||||
Some((new_face,new_intersection,d_new_intersection))
|
||||
}).min_by_key(|&(_,_,d)|d)?;
|
||||
|
||||
// we looped back around to face1, we're done!
|
||||
if core::ptr::eq(face1,new_face){
|
||||
break;
|
||||
}
|
||||
|
||||
face2=new_face;
|
||||
intersection=new_intersection;
|
||||
}
|
||||
|
||||
faces.push(face);
|
||||
}
|
||||
|
||||
None
|
||||
if faces.is_empty(){
|
||||
None
|
||||
}else{
|
||||
Some(Faces{
|
||||
faces,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn brush_to_mesh(bsp:&vbsp::Bsp,brush:&vbsp::Brush)->Result<model::Mesh,BrushToMeshError>{
|
||||
@ -181,7 +208,7 @@ pub fn brush_to_mesh(bsp:&vbsp::Bsp,brush:&vbsp::Brush)->Result<model::Mesh,Brus
|
||||
return Err(BrushToMeshError::InvalidFaceCount{count:face_list.len()});
|
||||
}
|
||||
|
||||
let faces=planes_to_faces(face_list)?;
|
||||
let faces=planes_to_faces(face_list).ok_or(BrushToMeshError::InvalidPlanes)?;
|
||||
|
||||
// generate the mesh
|
||||
let mut polygon_list=Vec::new();
|
||||
|
Loading…
x
Reference in New Issue
Block a user