Compare commits
3 Commits
master
...
max-area-t
Author | SHA1 | Date | |
---|---|---|---|
2a03987d89 | |||
57a4cadaf3 | |||
881bc60ab3 |
@ -314,6 +314,9 @@ impl TryFrom<&model::Mesh> for PhysicsMesh{
|
|||||||
return Err(PhysicsMeshError::ZeroVertices);
|
return Err(PhysicsMeshError::ZeroVertices);
|
||||||
}
|
}
|
||||||
let verts=mesh.unique_pos.iter().copied().map(Vert).collect();
|
let verts=mesh.unique_pos.iter().copied().map(Vert).collect();
|
||||||
|
// TODO: do not hash faces to get face id
|
||||||
|
// meshes can have multiple identical nd representations while still being distinct faces,
|
||||||
|
// especially when the complete mesh is a non-convex mesh.
|
||||||
//TODO: fix submeshes
|
//TODO: fix submeshes
|
||||||
//flat map mesh.physics_groups[$1].groups.polys()[$2] as face_id
|
//flat map mesh.physics_groups[$1].groups.polys()[$2] as face_id
|
||||||
//lower face_id points to upper face_id
|
//lower face_id points to upper face_id
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use strafesnet_common::integer::Planar64;
|
use strafesnet_common::integer::{self,Planar64,Planar64Vec3};
|
||||||
use strafesnet_common::{model,integer};
|
use strafesnet_common::model::{self,VertexId};
|
||||||
use strafesnet_common::integer::{vec3::Vector3,Fixed,Ratio};
|
use strafesnet_common::integer::{vec3::Vector3,Fixed,Ratio};
|
||||||
|
|
||||||
use crate::{valve_transform_normal,valve_transform_dist};
|
use crate::{valve_transform_normal,valve_transform_dist};
|
||||||
@ -138,7 +138,15 @@ fn planes_to_faces(face_list:std::collections::HashSet<Face>)->Result<Faces,Plan
|
|||||||
loop{
|
loop{
|
||||||
// push point onto vertices
|
// push point onto vertices
|
||||||
// problem: this may push a vertex that does not fit in the fixed point range and is thus meaningless
|
// problem: this may push a vertex that does not fit in the fixed point range and is thus meaningless
|
||||||
face.push(intersection.divide().narrow_1().unwrap());
|
//
|
||||||
|
// physics bug 2 originates from vertices being imprecise?
|
||||||
|
//
|
||||||
|
// Mask off the most precise 16 bits so that
|
||||||
|
// when face normals are calculated from
|
||||||
|
// the remaining 16 fractional bits
|
||||||
|
// they never exceed 32 bits of precision.
|
||||||
|
const MASK:Planar64=Planar64::raw(!((1<<16)-1));
|
||||||
|
face.push(intersection.divide().narrow_1().unwrap().map(|c|c&MASK));
|
||||||
|
|
||||||
// we looped back around to face1, we're done!
|
// we looped back around to face1, we're done!
|
||||||
if core::ptr::eq(face1,face2){
|
if core::ptr::eq(face1,face2){
|
||||||
@ -204,6 +212,33 @@ impl std::fmt::Display for BrushToMeshError{
|
|||||||
}
|
}
|
||||||
impl core::error::Error for BrushToMeshError{}
|
impl core::error::Error for BrushToMeshError{}
|
||||||
|
|
||||||
|
fn subdivide_max_area(tris:&mut Vec<Vec<VertexId>>,cw_verts:&[(VertexId,Planar64Vec3)],i0:usize,i2:usize,id0:VertexId,id2:VertexId,v0:Planar64Vec3,v2:Planar64Vec3){
|
||||||
|
if i0+1==i2{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut best_i1=i0+1;
|
||||||
|
if i0+2<i2{
|
||||||
|
let mut best_area={
|
||||||
|
let (_,v1)=cw_verts[best_i1.rem_euclid(cw_verts.len())];
|
||||||
|
(v2-v0).cross(v1-v0).length_squared()
|
||||||
|
};
|
||||||
|
for i1 in i0+2..=i2-1{
|
||||||
|
let (_,v1)=cw_verts[i1.rem_euclid(cw_verts.len())];
|
||||||
|
let area=(v2-v0).cross(v1-v0).length_squared();
|
||||||
|
if best_area<area{
|
||||||
|
best_i1=i1;
|
||||||
|
best_area=area;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let i1=best_i1;
|
||||||
|
let (id1,v1)=cw_verts[i1.rem_euclid(cw_verts.len())];
|
||||||
|
// draw max area first
|
||||||
|
tris.push(vec![id0,id1,id2]);
|
||||||
|
subdivide_max_area(tris,cw_verts,i0,i1,id0,id1,v0,v1);
|
||||||
|
subdivide_max_area(tris,cw_verts,i1,i2,id1,id2,v1,v2);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn faces_to_mesh(faces:Vec<Vec<integer::Planar64Vec3>>)->model::Mesh{
|
pub fn faces_to_mesh(faces:Vec<Vec<integer::Planar64Vec3>>)->model::Mesh{
|
||||||
// generate the mesh
|
// generate the mesh
|
||||||
let mut mb=model::MeshBuilder::new();
|
let mut mb=model::MeshBuilder::new();
|
||||||
@ -212,16 +247,34 @@ pub fn faces_to_mesh(faces:Vec<Vec<integer::Planar64Vec3>>)->model::Mesh{
|
|||||||
// normals are ignored by physics
|
// normals are ignored by physics
|
||||||
let normal=mb.acquire_normal_id(integer::vec3::ZERO);
|
let normal=mb.acquire_normal_id(integer::vec3::ZERO);
|
||||||
|
|
||||||
let polygon_list=faces.into_iter().map(|face|{
|
let polygon_list=faces.into_iter().flat_map(|face|{
|
||||||
face.into_iter().map(|pos|{
|
let cw_verts=face.into_iter().map(|position|{
|
||||||
let pos=mb.acquire_pos_id(pos);
|
let pos=mb.acquire_pos_id(position);
|
||||||
mb.acquire_vertex_id(model::IndexedVertex{
|
(mb.acquire_vertex_id(model::IndexedVertex{
|
||||||
pos,
|
pos,
|
||||||
tex,
|
tex,
|
||||||
normal,
|
normal,
|
||||||
color,
|
color,
|
||||||
})
|
}),position)
|
||||||
}).collect()
|
}).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// scan and select maximum area triangle O(n^3)
|
||||||
|
let len=cw_verts.len();
|
||||||
|
let cw_verts=cw_verts.as_slice();
|
||||||
|
let ((i0,i1,i2),(v0,v1,v2))=cw_verts[..len-2].iter().enumerate().flat_map(|(i0,&(_,v0))|
|
||||||
|
cw_verts[i0+1..len-1].iter().enumerate().flat_map(move|(i1,&(_,v1))|
|
||||||
|
cw_verts[i0+i1+2..].iter().enumerate().map(move|(i2,&(_,v2))|((i0,i0+i1+1,i0+i1+i2+2),(v0,v1,v2)))
|
||||||
|
)
|
||||||
|
).max_by_key(|&(_,(v0,v1,v2))|(v2-v0).cross(v1-v0).length_squared()).unwrap();
|
||||||
|
// scan and select more maximum area triangles n * O(n)
|
||||||
|
let mut tris=Vec::with_capacity(len-2);
|
||||||
|
// da big one
|
||||||
|
let (id0,id1,id2)=(cw_verts[i0].0,cw_verts[i1].0,cw_verts[i2].0);
|
||||||
|
tris.push(vec![id0,id1,id2]);
|
||||||
|
subdivide_max_area(&mut tris,cw_verts,i0,i1,id0,id1,v0,v1);
|
||||||
|
subdivide_max_area(&mut tris,cw_verts,i1,i2,id1,id2,v1,v2);
|
||||||
|
subdivide_max_area(&mut tris,cw_verts,i2,i0+len,id2,id0,v2,v0);
|
||||||
|
tris
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
let polygon_groups=vec![model::PolygonGroup::PolygonList(model::PolygonList::new(polygon_list))];
|
let polygon_groups=vec![model::PolygonGroup::PolygonList(model::PolygonList::new(polygon_list))];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user