Get normals for faces directly from .obj
This commit is contained in:
parent
b37f8e3144
commit
acbb572dcd
3 changed files with 80 additions and 45 deletions
20
Cargo.lock
generated
20
Cargo.lock
generated
|
@ -39,9 +39,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytemuck"
|
name = "bytemuck"
|
||||||
version = "1.10.0"
|
version = "1.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c53dfa917ec274df8ed3c572698f381a24eef2efba9492d797301b72b6db408a"
|
checksum = "a5377c8865e74a160d21f29c2d40669f53286db6eab59b88540cbb12ffc8b835"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
|
@ -72,9 +72,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.5.5"
|
version = "0.5.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4c02a4d71819009c192cf4872265391563fd6a84c81ff2c0f2a7026ca4c1d85c"
|
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
|
@ -82,9 +82,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-deque"
|
name = "crossbeam-deque"
|
||||||
version = "0.8.1"
|
version = "0.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
|
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"crossbeam-epoch",
|
"crossbeam-epoch",
|
||||||
|
@ -93,9 +93,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-epoch"
|
name = "crossbeam-epoch"
|
||||||
version = "0.9.9"
|
version = "0.9.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "07db9d94cbd326813772c968ccd25999e5f8ae22f4f8d1b11effa37ef6ce281d"
|
checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
@ -107,9 +107,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.10"
|
version = "0.8.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7d82ee10ce34d7bc12c2122495e7593a9c41347ecdd64185af4ecf72cb1a7f83"
|
checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
|
|
@ -161,16 +161,22 @@ impl Hittable for Triangle {
|
||||||
rec.p = r.at(t);
|
rec.p = r.at(t);
|
||||||
rec.mat_ptr = self.mat_ptr.clone();
|
rec.mat_ptr = self.mat_ptr.clone();
|
||||||
|
|
||||||
// triangle normal alg from https://stackoverflow.com/questions/19350792/calculate-normal-of-a-single-triangle-in-3d-space
|
|
||||||
rec.normal = self.normal;
|
rec.normal = self.normal;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
/* old normal calculation code if normal is not known
|
||||||
|
|
||||||
|
// triangle normal alg from https://stackoverflow.com/questions/19350792/calculate-normal-of-a-single-triangle-in-3d-space
|
||||||
let normal_to_camera = Vec3::new(
|
let normal_to_camera = Vec3::new(
|
||||||
a_to_b.y() * a_to_c.z() - a_to_b.z() * a_to_c.y(),
|
a_to_b.y() * a_to_c.z() - a_to_b.z() * a_to_c.y(),
|
||||||
a_to_b.z() * a_to_c.x() - a_to_b.x() * a_to_c.z(),
|
a_to_b.z() * a_to_c.x() - a_to_b.x() * a_to_c.z(),
|
||||||
a_to_b.x() * a_to_c.y() - a_to_b.y() * a_to_c.x(),
|
a_to_b.x() * a_to_c.y() - a_to_b.y() * a_to_c.x(),
|
||||||
);
|
);
|
||||||
let unit_normal = normal_to_camera / normal_to_camera.length();
|
let unit_normal = normal_to_camera / normal_to_camera.length();
|
||||||
|
|
||||||
|
println!("From obj: {},{},{} - calculated: {},{},{}", self.normal.x(),self.normal.y(),self.normal.z(),unit_normal.x(),unit_normal.y(),unit_normal.z());
|
||||||
|
|
||||||
|
|
||||||
if Vec3::dot(unit_normal, r.direction()) >= 0.0 {
|
if Vec3::dot(unit_normal, r.direction()) >= 0.0 {
|
||||||
// normal towards camera
|
// normal towards camera
|
||||||
rec.set_face_normal(r, unit_normal);
|
rec.set_face_normal(r, unit_normal);
|
||||||
|
@ -180,5 +186,6 @@ impl Hittable for Triangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
90
src/main.rs
90
src/main.rs
|
@ -17,9 +17,6 @@ use material::{Dielectric, Lambertian, Material, Metal};
|
||||||
use ray::Ray;
|
use ray::Ray;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::File;
|
|
||||||
use std::io::{self, BufRead};
|
|
||||||
use std::path::Path;
|
|
||||||
use std::sync::atomic::{AtomicU32, Ordering};
|
use std::sync::atomic::{AtomicU32, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tobj;
|
use tobj;
|
||||||
|
@ -42,13 +39,8 @@ fn ray_color(r: &Ray, world: &HittableList, depth: u32) -> Color {
|
||||||
return attenuation * ray_color(&scattered, world, depth - 1);
|
return attenuation * ray_color(&scattered, world, depth - 1);
|
||||||
}
|
}
|
||||||
return Color::null();
|
return Color::null();
|
||||||
|
|
||||||
//let target = rec.p + rec.normal + Vec3::random_unit_vector(); // rec.p + rec.normal.random_in_hemisphere();
|
|
||||||
//return 0.5 * ray_color(&Ray::new(rec.p, target - rec.p), world, depth - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// return Color::new(1.0, 1.0, 1.0);
|
|
||||||
|
|
||||||
let unit_direction = r.direction();
|
let unit_direction = r.direction();
|
||||||
let t = 0.5 * (unit_direction.y() + 1.0);
|
let t = 0.5 * (unit_direction.y() + 1.0);
|
||||||
return (1.0 - t) * Color::new(1.0, 1.0, 1.0) + t * Color::new(0.5, 0.7, 1.0);
|
return (1.0 - t) * Color::new(1.0, 1.0, 1.0) + t * Color::new(0.5, 0.7, 1.0);
|
||||||
|
@ -144,6 +136,7 @@ fn random_world() -> HittableList {
|
||||||
material5.clone(),
|
material5.clone(),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
/*
|
||||||
world.add(Box::<Triangle>::new(Triangle::new(
|
world.add(Box::<Triangle>::new(Triangle::new(
|
||||||
Point3::new(0.0, 1.0, 5.0),
|
Point3::new(0.0, 1.0, 5.0),
|
||||||
Point3::new(3.0, 2.0, 0.0),
|
Point3::new(3.0, 2.0, 0.0),
|
||||||
|
@ -169,6 +162,7 @@ fn random_world() -> HittableList {
|
||||||
Point3::new(6.0, 4.0, -6.0),
|
Point3::new(6.0, 4.0, -6.0),
|
||||||
material5.clone(),
|
material5.clone(),
|
||||||
)));
|
)));
|
||||||
|
*/
|
||||||
|
|
||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
|
@ -176,9 +170,24 @@ fn random_world() -> HittableList {
|
||||||
fn from_obj(path: &str) -> HittableList {
|
fn from_obj(path: &str) -> HittableList {
|
||||||
let mut world = HittableList::new();
|
let mut world = HittableList::new();
|
||||||
|
|
||||||
let material = Arc::new(Lambertian::new(&Color::new(0.6, 0.2, 0.3)));
|
let material_ground = Arc::new(Lambertian::new(&Color::new(
|
||||||
|
29.0 / 255.0,
|
||||||
|
71.0 / 255.0,
|
||||||
|
14.0 / 255.0,
|
||||||
|
)));
|
||||||
|
world.add(Box::<Sphere>::new(Sphere::new(
|
||||||
|
Point3::new(0.0, -5005.0, 0.0),
|
||||||
|
5000.0,
|
||||||
|
material_ground.clone(),
|
||||||
|
)));
|
||||||
|
|
||||||
|
let material = Arc::new(Lambertian::new(&Color::new(
|
||||||
|
26.0 / 255.0,
|
||||||
|
82.0 / 255.0,
|
||||||
|
118.0 / 255.0,
|
||||||
|
)));
|
||||||
//let material = Arc::new(Dielectric::new(2.0));
|
//let material = Arc::new(Dielectric::new(2.0));
|
||||||
//let material = Arc::new(Metal::new(&Color::new(0.9, 0.9, 0.7), 0.5));
|
//let material = Arc::new(Metal::new(&Color::new(0.9, 0.9, 0.7), 1.0));
|
||||||
|
|
||||||
let cornell_box = tobj::load_obj(path, &tobj::OFFLINE_RENDERING_LOAD_OPTIONS);
|
let cornell_box = tobj::load_obj(path, &tobj::OFFLINE_RENDERING_LOAD_OPTIONS);
|
||||||
let (models, materials) = cornell_box.expect("Failed to load OBJ file");
|
let (models, materials) = cornell_box.expect("Failed to load OBJ file");
|
||||||
|
@ -187,6 +196,7 @@ fn from_obj(path: &str) -> HittableList {
|
||||||
for (i, m) in models.iter().enumerate() {
|
for (i, m) in models.iter().enumerate() {
|
||||||
let mesh = &m.mesh;
|
let mesh = &m.mesh;
|
||||||
|
|
||||||
|
/* Mesh vector lengths
|
||||||
println!("positions: {}", mesh.positions.len());
|
println!("positions: {}", mesh.positions.len());
|
||||||
println!("vertex_color: {}", mesh.vertex_color.len());
|
println!("vertex_color: {}", mesh.vertex_color.len());
|
||||||
println!("normals: {}", mesh.normals.len());
|
println!("normals: {}", mesh.normals.len());
|
||||||
|
@ -195,9 +205,7 @@ fn from_obj(path: &str) -> HittableList {
|
||||||
println!("face_arities: {}", mesh.face_arities.len());
|
println!("face_arities: {}", mesh.face_arities.len());
|
||||||
println!("texcoord_indices: {}", mesh.texcoord_indices.len());
|
println!("texcoord_indices: {}", mesh.texcoord_indices.len());
|
||||||
println!("normal_indices: {}", mesh.normal_indices.len());
|
println!("normal_indices: {}", mesh.normal_indices.len());
|
||||||
|
*/
|
||||||
|
|
||||||
return world;
|
|
||||||
|
|
||||||
let mut next_face = 0;
|
let mut next_face = 0;
|
||||||
for f in 0..mesh.face_arities.len() {
|
for f in 0..mesh.face_arities.len() {
|
||||||
|
@ -211,7 +219,38 @@ fn from_obj(path: &str) -> HittableList {
|
||||||
let index_a = mesh.indices[3 * v] as usize;
|
let index_a = mesh.indices[3 * v] as usize;
|
||||||
let index_b = mesh.indices[3 * v + 1] as usize;
|
let index_b = mesh.indices[3 * v + 1] as usize;
|
||||||
let index_c = mesh.indices[3 * v + 2] as usize;
|
let index_c = mesh.indices[3 * v + 2] as usize;
|
||||||
let index_normal = mesh.normal_indices[]
|
let index_normal_a = mesh.normal_indices[3 * v] as usize;
|
||||||
|
let index_normal_b = mesh.normal_indices[3 * v + 1] as usize;
|
||||||
|
let index_normal_c = mesh.normal_indices[3 * v + 2] as usize;
|
||||||
|
|
||||||
|
let normal_avg = Vec3::unit_vector(
|
||||||
|
Vec3::new(
|
||||||
|
mesh.positions[3 * index_normal_a] as f64,
|
||||||
|
mesh.positions[3 * index_normal_a + 1] as f64,
|
||||||
|
mesh.positions[3 * index_normal_a + 2] as f64,
|
||||||
|
) + Vec3::new(
|
||||||
|
mesh.positions[3 * index_normal_b] as f64,
|
||||||
|
mesh.positions[3 * index_normal_b + 1] as f64,
|
||||||
|
mesh.positions[3 * index_normal_b + 2] as f64,
|
||||||
|
) + Vec3::new(
|
||||||
|
mesh.positions[3 * index_normal_c] as f64,
|
||||||
|
mesh.positions[3 * index_normal_c + 1] as f64,
|
||||||
|
mesh.positions[3 * index_normal_c + 2] as f64,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
println!("a:{},{},{}; b:{},{},{}; c:{},{},{}",
|
||||||
|
mesh.normals[3*index_normal_a],
|
||||||
|
mesh.normals[3*index_normal_a+1],
|
||||||
|
mesh.normals[3*index_normal_a+2],
|
||||||
|
mesh.normals[3*index_normal_b],
|
||||||
|
mesh.normals[3*index_normal_b+1],
|
||||||
|
mesh.normals[3*index_normal_b+2],
|
||||||
|
mesh.normals[3*index_normal_c],
|
||||||
|
mesh.normals[3*index_normal_c+1],
|
||||||
|
mesh.normals[3*index_normal_c+2]);
|
||||||
|
*/
|
||||||
|
|
||||||
world.add(Box::<Triangle>::new(Triangle::new(
|
world.add(Box::<Triangle>::new(Triangle::new(
|
||||||
Point3::new(
|
Point3::new(
|
||||||
|
@ -229,7 +268,7 @@ fn from_obj(path: &str) -> HittableList {
|
||||||
mesh.positions[3 * index_c + 1] as f64,
|
mesh.positions[3 * index_c + 1] as f64,
|
||||||
mesh.positions[3 * index_c + 2] as f64,
|
mesh.positions[3 * index_c + 2] as f64,
|
||||||
),
|
),
|
||||||
mesh.
|
normal_avg,
|
||||||
material.clone(),
|
material.clone(),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
@ -237,16 +276,6 @@ fn from_obj(path: &str) -> HittableList {
|
||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The output is wrapped in a Result to allow matching on errors
|
|
||||||
// Returns an Iterator to the Reader of the lines of the file.
|
|
||||||
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
|
|
||||||
where
|
|
||||||
P: AsRef<Path>,
|
|
||||||
{
|
|
||||||
let file = File::open(filename)?;
|
|
||||||
Ok(io::BufReader::new(file).lines())
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Current world view:
|
Current world view:
|
||||||
|
|
||||||
|
@ -267,27 +296,26 @@ fn main() {
|
||||||
|
|
||||||
// Image
|
// Image
|
||||||
let aspect_ratio = 16.0 / 9.0;
|
let aspect_ratio = 16.0 / 9.0;
|
||||||
let image_width = 600;
|
let image_width = 1200;
|
||||||
let image_height = (image_width as f64 / aspect_ratio) as u32;
|
let image_height = (image_width as f64 / aspect_ratio) as u32;
|
||||||
let samples_per_pixel = 1_u32;
|
let samples_per_pixel = 50_u32;
|
||||||
let max_depth = 50;
|
let max_depth = 50;
|
||||||
|
|
||||||
let vfov = 40.0;
|
let vfov = 40.0;
|
||||||
let lookfrom = Point3::new(2.0, 0.5, 3.0);
|
let lookfrom = Point3::new(2.0, 0.8, 3.0);
|
||||||
let lookat = Point3::new(0.0, 0.0, 0.0);
|
let lookat = Point3::new(0.0, 0.0, 0.0);
|
||||||
let vup = Vec3::new(0.0, 1.0, 0.0);
|
let vup = Vec3::new(0.0, 1.0, 0.0);
|
||||||
let dist_to_focus = 3.0;
|
let dist_to_focus = 3.0;
|
||||||
let aperture = 0.1;
|
let aperture = 0.1;
|
||||||
|
|
||||||
// limit rayon multithreading thread count
|
// limit rayon multithreading thread count
|
||||||
let thread_count = 0; // if 0, for each logical cpu core a thread wil be created
|
let thread_count = 6; // if 0, for each logical cpu core a thread wil be created
|
||||||
if thread_count > 0 {
|
if thread_count > 0 {
|
||||||
env::set_var("RAYON_NUM_THREADS", thread_count.to_string());
|
env::set_var("RAYON_NUM_THREADS", thread_count.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let world = from_obj("obj/suzanne.obj");
|
|
||||||
|
|
||||||
// World
|
// World
|
||||||
|
let world = from_obj("obj/suzanne.obj");
|
||||||
// let world = random_world();
|
// let world = random_world();
|
||||||
|
|
||||||
// Camera
|
// Camera
|
||||||
|
|
Loading…
Reference in a new issue