THE ALGORITHM
This commit is contained in:
parent
0b63e06ad2
commit
067b5eee3c
@ -34,6 +34,7 @@ pub enum BrushToMeshError{
|
|||||||
InvalidFaceCount{
|
InvalidFaceCount{
|
||||||
count:usize,
|
count:usize,
|
||||||
},
|
},
|
||||||
|
InvalidPlanes,
|
||||||
}
|
}
|
||||||
impl std::fmt::Display for BrushToMeshError{
|
impl std::fmt::Display for BrushToMeshError{
|
||||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
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{}
|
impl core::error::Error for BrushToMeshError{}
|
||||||
|
|
||||||
fn planes_to_faces(face_list:Vec<Face>)->Option<Faces>{
|
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
|
// for each face, determine one edge at a time until you complete the face
|
||||||
let mut dedup=std::collections::HashSet::new();
|
let mut dedup=std::collections::HashSet::new();
|
||||||
'face: for face0 in &face_list{
|
'face: for face0 in &face_list{
|
||||||
@ -136,33 +138,58 @@ fn planes_to_faces(face_list:Vec<Face>)->Option<Faces>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// === follow edges around face ===
|
// === 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
|
// 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{
|
loop{
|
||||||
|
// push point onto vertices
|
||||||
|
face.push(intersection.divide().fix_1());
|
||||||
|
|
||||||
// the measure
|
// the measure
|
||||||
let edge_dir=face0.normal.cross(face1.normal);
|
let edge_dir=face0.normal.cross(face1.normal);
|
||||||
|
|
||||||
// the dot product to beat
|
// the dot product to beat
|
||||||
let d_intersection=edge_dir.dot(intersection.num)/intersection.den;
|
let d_intersection=edge_dir.dot(intersection.num)/intersection.den;
|
||||||
|
|
||||||
for new_face in &face_list{
|
// find the next face moving clockwise around face0
|
||||||
if core::ptr::eq(face0,new_face){
|
let (new_face,new_intersection,_)=face_list.iter().filter_map(|new_face|{
|
||||||
continue;
|
// 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){
|
let new_intersection=solve3(face0,face2,new_face)?;
|
||||||
continue;
|
|
||||||
}
|
// the d value must be larger
|
||||||
if core::ptr::eq(face2,new_face){
|
let d_new_intersection=edge_dir.dot(new_intersection.num)/new_intersection.den;
|
||||||
continue;
|
if d_new_intersection.le_ratio(d_intersection){
|
||||||
}
|
return None;
|
||||||
if let Some(new_intersection)=solve3(new_face,face1,face2){
|
|
||||||
}
|
}
|
||||||
|
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>{
|
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()});
|
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
|
// generate the mesh
|
||||||
let mut polygon_list=Vec::new();
|
let mut polygon_list=Vec::new();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user