forked from 1b-agent/opencadstudio-upstream
fix(obj): concave OBJ faces are triangulated, not fanned
A fan only covers convex faces; architectural n-gons filled well outside their outline (the sample's faces covered 63% extra area). Fixes #680 Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
b66b5100bd
commit
4c1ddec646
2 files changed
+35
-6
No files matched your search
+25
-5
@@ -51,11 +51,31 @@ pub fn parse_obj(src: &str, color: [f32; 4]) -> Option<MeshModel> {
|
||||
Some((pos_i, norm_i))
|
||||
})
|
||||
.collect();
|
||||
// Fan-triangulate: (0,1,2), (0,2,3), …
|
||||
for k in 1..(descs.len() as isize - 1) {
|
||||
face_verts.push(descs[0]);
|
||||
face_verts.push(descs[k as usize]);
|
||||
face_verts.push(descs[k as usize + 1]);
|
||||
// A fan is only right for convex faces; floor-plan n-gons
|
||||
// are concave, so larger faces go through the kernel's
|
||||
// triangulator and fall back to the fan if it declines. (#680)
|
||||
let corners: Vec<[f64; 3]> = descs
|
||||
.iter()
|
||||
.map(|(pos_i, _)| {
|
||||
let p = positions.get(*pos_i).copied().unwrap_or([0.0; 3]);
|
||||
[p[0] as f64, p[1] as f64, p[2] as f64]
|
||||
})
|
||||
.collect();
|
||||
let triangles = if descs.len() > 3 {
|
||||
crate::entities::mesh::triangulate_planar_indices(&corners)
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
if triangles.is_empty() {
|
||||
for k in 1..(descs.len() as isize - 1) {
|
||||
face_verts.push(descs[0]);
|
||||
face_verts.push(descs[k as usize]);
|
||||
face_verts.push(descs[k as usize + 1]);
|
||||
}
|
||||
} else {
|
||||
for triangle in triangles {
|
||||
face_verts.extend(triangle.map(|index| descs[index]));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
||||
Reference in new issue
Block a user