use std::fs::File;
use std::io::Write;
use redges::container_trait::FaceAttributeGetter;
use redges::quadric_simplification::{
QuadricSimplificationConfig, SimplificationStrategy, StopCondition,
};
use redges::VertId;
use redges::{quadric_simplification, Redge};
use std::time::Instant;
use redges::wavefront_loader::*;
pub type Vec2 = nalgebra::Vector2<f64>;
pub type Vec3 = nalgebra::Vector3<f64>;
#[derive(Debug, Default, Clone)]
pub struct FaceData {
pub uvs: [Vec2; 3],
pub verts: [VertId; 3],
}
impl FaceAttributeGetter<f64> for FaceData {
fn attribute(&self, vert_index: usize, attribute_id: usize) -> f64 {
self.uvs[vert_index][attribute_id]
}
fn attribute_count(&self) -> usize {
2
}
fn attribute_mut(&mut self, vert_index: usize, attribute_id: usize) -> &mut f64 {
&mut self.uvs[vert_index][attribute_id]
}
fn inner_index(&self, vid: VertId) -> usize {
self.verts
.iter()
.position(|id| *id == vid)
.unwrap_or_else(|| {
panic!(
"Asked for position of vertex {:?} in face {:?}",
vid, self.verts
)
})
}
fn attribute_vertices(&self) -> &[VertId] {
&self.verts
}
fn attribute_vertices_mut(&mut self) -> &mut [VertId] {
&mut self.verts
}
}
fn export_to_obj(vertices: &[Vec3], faces: &Vec<FaceData>, path: &str) -> std::io::Result<()> {
let mut file = File::create(path)?;
for v in vertices {
writeln!(file, "v {} {} {}", v.x, v.y, v.z,)?;
}
for face in faces {
writeln!(file, "vt {} {}", face.uvs[0].x, face.uvs[0].y)?;
writeln!(file, "vt {} {}", face.uvs[1].x, face.uvs[1].y)?;
writeln!(file, "vt {} {}", face.uvs[2].x, face.uvs[2].y)?;
}
for (i, face) in faces.iter().enumerate() {
writeln!(
file,
"f {}/{} {}/{} {}/{}",
face.verts[0].to_index() + 1,
i * 3 + 1, face.verts[1].to_index() + 1,
i * 3 + 2, face.verts[2].to_index() + 1,
i * 3 + 3, )?;
}
Ok(())
}
fn main() {
let mut obj_data = ObjData::from_disk_file("assets/armadillo.obj");
if obj_data.uv_face_indices.is_empty() {
obj_data.uvs = vec![nalgebra::Vector2::new(0., 0.)];
obj_data.uv_face_indices = vec![vec![0; 3]; obj_data.vertex_face_indices.len()];
}
assert!(obj_data.uv_face_indices.len() == obj_data.vertex_face_indices.len());
let mut faces: Vec<_> = (0..obj_data.vertex_face_indices.len())
.map(|i| FaceData {
uvs: [
obj_data.uvs[obj_data.uv_face_indices[i][0] as usize]
.clone()
.map(|s| s as f64),
obj_data.uvs[obj_data.uv_face_indices[i][1] as usize]
.clone()
.map(|s| s as f64),
obj_data.uvs[obj_data.uv_face_indices[i][2] as usize]
.clone()
.map(|s| s as f64),
],
verts: [
VertId(obj_data.vertex_face_indices[i][0] as usize),
VertId(obj_data.vertex_face_indices[i][1] as usize),
VertId(obj_data.vertex_face_indices[i][2] as usize),
],
})
.collect();
if faces.is_empty() {
for i in 0..obj_data.uv_face_indices.len() {
faces.push(FaceData {
uvs: [nalgebra::Vector2::default(); 3],
verts: [
VertId(obj_data.uv_face_indices[i][0] as usize),
VertId(obj_data.uv_face_indices[i][1] as usize),
VertId(obj_data.uv_face_indices[i][2] as usize),
],
});
}
}
let vertices: Vec<_> = obj_data
.vertices
.iter()
.map(|v| v.map(|s| s as f64))
.collect();
let redge = Redge::<(_, _, _)>::new(
vertices.clone(),
(),
faces,
obj_data
.vertex_face_indices
.iter()
.map(|l| l.clone().into_iter().map(|i| i as usize)),
);
let (vs, _ids, fs) = redge.to_face_list();
let _ = export_to_obj(&vs, &fs, "tmp/dbg_uvs_before.obj");
let face_count_before = redge.face_count();
let start = Instant::now();
let redge = redge.clean_overlapping_faces();
let (redge, _) = quadric_simplification::quadric_simplify(
redge,
QuadricSimplificationConfig {
strategy: SimplificationStrategy::Conservative,
attribute_simplification:
quadric_simplification::AttributeSimplification::SimplifyAttributes,
stop_condition: StopCondition::FaceCount(face_count_before / 10),
},
|_, _| false,
);
let duration = start.elapsed();
println!("Time elapsed in simplify() is: {:?}", duration);
let (vs, _ids, fs) = redge.to_face_list();
let _ = export_to_obj(&vs, &fs, "tmp/dbg_uvs_after.obj");
}