rustracer/src/obj.rs

52 lines
1.9 KiB
Rust

use std::path::Path;
use std::sync::Arc;
use tobj::LoadOptions;
use crate::{BVH, Color, Dielectric, HittableList, HittableObject, Lambertian, Material, Point3, Vec3};
use crate::hittable::Hittable;
use crate::triangle::Triangle;
pub fn obj_to_hitable(path: &Path) -> HittableObject {
let mut lo = LoadOptions::default();
lo.triangulate = true;
let (models, materials) = tobj::load_obj(path, &lo)
.unwrap();
let default_mat: Arc<Material> = Arc::new(
Material::Dielectric(
Dielectric::new(1.5)
)
);
let mut triangles: HittableList = Vec::with_capacity(models.len());
for model in models {
let mesh = model.mesh;
for f in 0..mesh.indices.len() / 3 {
let i0 = mesh.indices[3 * f] as usize;
let i1 = mesh.indices[3 * f + 1] as usize;
let i2 = mesh.indices[3 * f + 2] as usize;
let v0 = Point3::new(
mesh.positions[i0 * 3] as f64,
mesh.positions[i0 * 3 + 1] as f64,
mesh.positions[i0 * 3 + 2] as f64);
let v1 = Point3::new(
mesh.positions[i1 * 3] as f64,
mesh.positions[i1 * 3 + 1] as f64,
mesh.positions[i1 * 3 + 2] as f64);
let v2 = Point3::new(
mesh.positions[i2 * 3] as f64,
mesh.positions[i2 * 3 + 1] as f64,
mesh.positions[i2 * 3 + 2] as f64);
let triangle = if mesh.normals.len() <= i0 * 3 + 2 {
Triangle::without_normal(v0, v1, v2, default_mat.clone())
} else {
let normal = Vec3::new(
mesh.normals[i0 * 3] as f64,
mesh.normals[i0 * 3 + 1] as f64,
mesh.normals[i0 * 3 + 2] as f64);
Triangle::new(v0, v1, v2, normal, default_mat.clone())
};
triangles.push(Arc::new(triangle));
}
}
Arc::new(BVH::new(triangles, 0.0, 1.0))
}