|
|
@ -1,6 +1,8 @@
|
|
|
|
use bytemuck::{Pod, Zeroable};
|
|
|
|
use bytemuck::{Pod, Zeroable};
|
|
|
|
use nalgebra::Vector4;
|
|
|
|
use nalgebra::Vector4;
|
|
|
|
use rapier3d::parry::math::Point;
|
|
|
|
use rapier3d::parry::math::Point;
|
|
|
|
|
|
|
|
use tobj::{LoadError, Model, Material};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
#[repr(C)]
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
|
@ -32,14 +34,23 @@ pub struct RawMesh {
|
|
|
|
pub indices: Vec<[u32; 3]>,
|
|
|
|
pub indices: Vec<[u32; 3]>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn load_obj(obj_path: &str) -> RawMesh {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let (models, materials) = tobj::load_obj(obj_path, true).expect("Failed to load file");
|
|
|
|
/// We use meshes in a few different places. To keep things simple, we return
|
|
|
|
|
|
|
|
/// the most basic, direct-to-memory version. If something fancy needs to be done
|
|
|
|
|
|
|
|
/// with it, the fancy stays there
|
|
|
|
|
|
|
|
pub fn load_obj(obj_path: &str) -> Result<RawMesh, String> {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log::info!("Loading object {}", obj_path);
|
|
|
|
|
|
|
|
|
|
|
|
println!("# of models: {}", models.len());
|
|
|
|
// Is there no better way to translate error messages?
|
|
|
|
println!("# of materials: {}", materials.len());
|
|
|
|
let (models, materials) = match tobj::load_obj(obj_path, true) {
|
|
|
|
|
|
|
|
Ok((a, b)) => {Ok((a, b))}
|
|
|
|
|
|
|
|
Err(load_error) => {Err(load_error.to_string())}
|
|
|
|
|
|
|
|
}.unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
println!("{:?}", materials);
|
|
|
|
// println!("# of models: {}", models.len());
|
|
|
|
|
|
|
|
// println!("# of materials: {}", materials.len());
|
|
|
|
|
|
|
|
// println!("{:?}", materials);
|
|
|
|
|
|
|
|
|
|
|
|
let mut index_data: Vec<[u32; 3]> = Vec::new();
|
|
|
|
let mut index_data: Vec<[u32; 3]> = Vec::new();
|
|
|
|
let mut vertex_data = Vec::new();
|
|
|
|
let mut vertex_data = Vec::new();
|
|
|
@ -54,14 +65,22 @@ pub fn load_obj(obj_path: &str) -> RawMesh {
|
|
|
|
let end = next_face + mesh.num_face_indices[f] as usize;
|
|
|
|
let end = next_face + mesh.num_face_indices[f] as usize;
|
|
|
|
let face_indices: Vec<_> = mesh.indices[next_face..end].iter().collect();
|
|
|
|
let face_indices: Vec<_> = mesh.indices[next_face..end].iter().collect();
|
|
|
|
|
|
|
|
|
|
|
|
assert!(face_indices.len() == 3, "we only handle triangulated faces");
|
|
|
|
if face_indices.len() != 3 {
|
|
|
|
|
|
|
|
return Err("we only handle triangulated faces".to_string());
|
|
|
|
|
|
|
|
}
|
|
|
|
index_data.push([*face_indices[0], *face_indices[1], *face_indices[2]]);
|
|
|
|
index_data.push([*face_indices[0], *face_indices[1], *face_indices[2]]);
|
|
|
|
|
|
|
|
|
|
|
|
next_face = end;
|
|
|
|
next_face = end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
assert!(mesh.positions.len() % 3 == 0);
|
|
|
|
if mesh.positions.len() % 3 != 0 {
|
|
|
|
assert!(mesh.texcoords.len() % 2 == 0);
|
|
|
|
return Err(format!("position array not % 3 : {}", mesh.positions.len()))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if mesh.texcoords.len() % 2 != 0 {
|
|
|
|
|
|
|
|
return Err(format!("position array not % 3 : {}", mesh.positions.len()))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if mesh.texcoords.is_empty() {
|
|
|
|
|
|
|
|
log::info!("Mesh texture coordinates empty")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for v in 0..mesh.positions.len() / 3 {
|
|
|
|
for v in 0..mesh.positions.len() / 3 {
|
|
|
|
let texcoords = if mesh.texcoords.len() == 0 {
|
|
|
|
let texcoords = if mesh.texcoords.len() == 0 {
|
|
|
@ -85,8 +104,8 @@ pub fn load_obj(obj_path: &str) -> RawMesh {
|
|
|
|
));
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RawMesh {
|
|
|
|
Ok(RawMesh {
|
|
|
|
vertices: vertex_data.to_vec(),
|
|
|
|
vertices: vertex_data.to_vec(),
|
|
|
|
indices: index_data.to_vec(),
|
|
|
|
indices: index_data.to_vec(),
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|