Begin implementing triangle hittable

This commit is contained in:
Jonathan Flueren 2022-07-05 18:02:28 +02:00
parent 89bcc587d2
commit 8cb017283d
2 changed files with 68 additions and 8 deletions

View file

@ -14,6 +14,13 @@ pub struct Sphere {
pub mat_ptr: Arc<dyn Material>, pub mat_ptr: Arc<dyn Material>,
} }
pub struct Triangle {
a: Point3,
b: Point3,
c: Point3,
pub mat_ptr: Arc<dyn Material>,
}
pub trait Hittable: Sync + Send { pub trait Hittable: Sync + Send {
fn hit(&self, r: &Ray, t_min: f64, t_max: f64, rec: &mut HitRecord) -> bool; fn hit(&self, r: &Ray, t_min: f64, t_max: f64, rec: &mut HitRecord) -> bool;
} }
@ -92,3 +99,55 @@ impl Hittable for Sphere {
return true; return true;
} }
} }
impl Triangle {
pub fn new(a: Point3, b: Point3, c: Point3, m: Arc<dyn Material>) -> Self {
Triangle {
a,
b,
c,
mat_ptr: m,
}
}
}
impl Hittable for Triangle {
fn hit(&self, r: &Ray, t_min: f64, t_max: f64, rec: &mut HitRecord) -> bool {
let a_to_b = self.b - self.a;
let a_to_c = self.c - self.a;
let u_vec = Vec3::cross(r.direction(), a_to_c);
let det = Vec3::dot(a_to_b, u_vec);
if det < 0.0 { // only positive bound
return false;
}
let inv_det = 1.0 / det;
let a_to_origin = r.origin() - self.a;
let u = Vec3::dot(a_to_origin, u_vec) * inv_det;
if u < 0.0 || u > 1.0 { //check if outside of triangle
return false;
}
let v_vec = Vec3::cross(a_to_origin, a_to_b);
let v = Vec3::dot(r.direction(), v_vec) * inv_det;
if v < 0.0 || u+v > 1.0 { // intersection outside of triangle
return false;
}
let dist = Vec3::dot(a_to_c, v_vec) * inv_det;
if dist > 0.0 {
}
return true;
}
}

View file

@ -51,22 +51,23 @@ fn random_world() -> HittableList {
let mut world = HittableList::new(); let mut world = HittableList::new();
let material_ground = Arc::new(Lambertian::new(&Color::new(0.05, 0.05,0.05))); let material_ground = Arc::new(Lambertian::new(&Color::new(0.05, 0.05,0.05)));
world.add(Box::<Sphere>::new(Sphere::new( world.add(Box::<Sphere>::new(Sphere::new(
Point3::new(0.0, -50000.0, 0.0), Point3::new(0.0, -50000.0, 0.0),
50000.0, 50000.0,
material_ground.clone(), material_ground.clone(),
))); )));
(-6..5).into_iter().for_each(|a| { (-6..5).into_iter().for_each(|a| {
(-6..5).into_iter().for_each(|b| { (-6..5).into_iter().for_each(|b| {
let choose_mat = utility::random_f64(); let choose_mat = utility::random_f64();
let rad = utility::random_rng(0.1, 0.5);
let center = Point3::new( let center = Point3::new(
1.5 * a as f64 + 1.3 * utility::random_f64(), 1.5 * a as f64 + 1.3 * utility::random_f64(),
0.2, rad,
1.5 * b as f64 + 1.3 * utility::random_f64(), 1.5 * b as f64 + 1.3 * utility::random_f64(),
); );
if (center - Point3::new(4.0, 0.2, 0.0)).length() > 0.9 { if (center - Point3::new(4.0, rad, 0.0)).length() > 0.9 {
if choose_mat < 0.8 { if choose_mat < 0.8 {
// diffuse // diffuse
let sphere_material = Arc::new(Lambertian::new( let sphere_material = Arc::new(Lambertian::new(
@ -74,7 +75,7 @@ fn random_world() -> HittableList {
)); ));
world.add(Box::<Sphere>::new(Sphere::new( world.add(Box::<Sphere>::new(Sphere::new(
center, center,
0.2, rad,
sphere_material.clone(), sphere_material.clone(),
))); )));
} else if choose_mat < 0.95 { } else if choose_mat < 0.95 {
@ -146,12 +147,12 @@ fn main() {
// Image // Image
let aspect_ratio = 16.0 / 9.0; let aspect_ratio = 16.0 / 9.0;
let image_width = 1920; let image_width = 600;
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 = 200_u32; let samples_per_pixel = 50_u32;
let max_depth = 50; let max_depth = 50;
let vfov = 25.0; let vfov = 40.0;
let lookfrom = Point3::new(10.0, 4.0, 13.0); let lookfrom = Point3::new(10.0, 4.0, 13.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);