From 11245af1122a2f5cf8c0dd399b3d8a4747d49c09 Mon Sep 17 00:00:00 2001 From: dengqn Date: Sat, 9 Aug 2025 01:19:01 +0800 Subject: [PATCH] chore: hit record --- src/camera.rs | 18 +++++++++--------- src/hittable.rs | 39 +++++++++++++++++++++++++-------------- src/main.rs | 2 +- src/sphere.rs | 18 +++++++++--------- 4 files changed, 44 insertions(+), 33 deletions(-) diff --git a/src/camera.rs b/src/camera.rs index 6040577..ab556af 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -4,7 +4,7 @@ use std::io::{BufWriter}; use crate::hittable::HittableList; use crate::math_utils::clamp; use crate::ppm_writer::PPMWriter; -use crate::types_defined::{Camera, Color, Point, Ray, Vec3}; +use crate::types_defined::{Camera, Color, HitRecord, Point, Ray, Vec3}; use rand::rngs::ThreadRng; use rand::{Rng, thread_rng}; @@ -89,11 +89,6 @@ impl<'a> Camera<'a> { ); self.ppm_file_writer.write(color.to_color()); - - - // content - // img_content.push_str(&color_clamped.to_color_str().as_str()); - // img_content.push('\n'); } } @@ -108,11 +103,16 @@ impl<'a> Camera<'a> { } // 限制出射光线的角度(0.001经验值) - let hr = world.hit(&ray, 0.001, f32::MAX); - if hr.t >= 0.0 { + let hit_record = &mut HitRecord{ + t: 0.0, + normal: Vec3::new(0.0, 0.0, 0.0), + front_face: false, + }; + let hit = world.hit(&ray, 0.001, f32::MAX, hit_record); + if hit_record.t >= 0.0 { // diffuse normal vec let diffuse_vec = Vec3::random_unit(); - let lambertian_vec = diffuse_vec + hr.normal; + let lambertian_vec = diffuse_vec + hit_record.normal; // 每次反射按0.5计算颜色(反射率 ) return 0.5 * self.ray_color(&Ray::new(ray.point, lambertian_vec), depth - 1, world); } diff --git a/src/hittable.rs b/src/hittable.rs index 4089645..070f451 100644 --- a/src/hittable.rs +++ b/src/hittable.rs @@ -1,7 +1,7 @@ use crate::types_defined::{HitRecord, Ray, Vec3}; pub trait Hittable { - fn hit(&self, r: &Ray, t_min: f32, t_max: f32) -> HitRecord; + fn hit(&self, r: &Ray, t_min: f32, t_max: f32, hit_record: &mut HitRecord) -> bool; } @@ -19,22 +19,33 @@ impl HittableList { let _ = &self.objects.push(object); } - pub fn hit(&self, r: &Ray, t_min: f32, t_max: f32) -> HitRecord { + pub fn hit(&self, r: &Ray, t_min: f32, t_max: f32, hit_record: &mut HitRecord) -> bool { + + let mut hits = false; + let mut closest_so_far = t_max; + + let temp_hit_record = &mut HitRecord{ + t: 0.0, + normal: Vec3::new(0.0, 0.0, 0.0), + front_face: false, + }; + for object in &self.objects { - let temp = object.hit(r, t_min, t_max); - if temp.t >= 0.0 { - return temp + let hit = object.hit(r, t_min, closest_so_far, temp_hit_record); + if hit { + hits = true; + closest_so_far = temp_hit_record.t; + + hit_record.t = temp_hit_record.t; + hit_record.front_face = temp_hit_record.front_face; + hit_record.normal = temp_hit_record.normal; + if temp_hit_record.t >= 0.0 { + return true; + } } } - HitRecord { - t: -1.0, - normal: Vec3 { - x: 0.0, - y: 0.0, - z: 0.0, - }, - front_face: false, - } + + hits } } diff --git a/src/main.rs b/src/main.rs index e6456cc..7f644fa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,7 +37,7 @@ fn camera_render() { width, 16.0 / 9.0, 2.0, - Point::new(0.0, 0.0, 0.0), + Point::new(0.0, 0.0, 1.0), Vec3::new(0.0, 0.0, -1.0), 50, 50, diff --git a/src/sphere.rs b/src/sphere.rs index 9261dc9..388efa0 100644 --- a/src/sphere.rs +++ b/src/sphere.rs @@ -11,7 +11,7 @@ impl Sphere { } impl hittable::Hittable for Sphere { - fn hit(&self, r: &Ray, t_min: f32, t_max: f32) -> HitRecord { + fn hit(&self, r: &Ray, t_min: f32, t_max: f32, hit_record: &mut HitRecord) -> bool { let a: f32 = r.direction.length_squared(); let h = r.direction.dot(self.center - r.point); // let b = -2.0 * r.direction.dot(sphere_center - r.point); @@ -28,19 +28,19 @@ impl hittable::Hittable for Sphere { if root <= t_min || root >= t_max { root = far; if root <= t_min || root >= t_max { - root = -1.0; + // hit_record.t = -1.0; + return false } } let p = r.at(root); let normal = (p - self.center) / self.radius; - HitRecord { - t: root, - // p, - normal, - // check if r.p inside(>=0) the sphere. - front_face: r.direction.dot(normal) < 0.0, - } + + hit_record.t = root; + hit_record.normal = normal; + hit_record.front_face = r.direction.dot(normal) < 0.0; + + true } } \ No newline at end of file