diff --git a/src/color.rs b/src/color.rs new file mode 100644 index 0000000..5f7a8be --- /dev/null +++ b/src/color.rs @@ -0,0 +1,7 @@ +use crate::types_defined::Color; + +impl Color { + pub fn to_color(self) -> String { + return format!("{} {} {}\n", (self.x * 256.0) as u8, (self.y * 256.0) as u8, (self.z * 256.0) as u8); + } +} \ No newline at end of file diff --git a/src/image.rs b/src/image.rs index 3322262..a77b1d0 100644 --- a/src/image.rs +++ b/src/image.rs @@ -1,14 +1,7 @@ -use crate::{point::Point, ray::Ray, vec3::{self, Vec3}}; +use crate::hittable::Hittable; +use crate::types_defined::{Color, Point, Ray, Sphere, Vec3}; -pub type Color = vec3::Vec3; - - -impl Color { - pub fn to_color(self) -> String { - return format!("{} {} {}\n", (self.x * 256.0) as u8, (self.y * 256.0) as u8, (self.z * 256.0) as u8); - } -} pub fn gen_ray_sphere_normal_ppm_p3(width: i32, height: i32, camera_center: Vec3, viewport_top_left_pixel_center: Vec3, viewport_u_delta: Vec3, viewport_v_delta: Vec3) -> String { let mut img_content = format!("P3\n{} {}\n255\n", width, height); @@ -26,15 +19,15 @@ pub fn gen_ray_sphere_normal_ppm_p3(width: i32, height: i32, camera_center: Vec3 let ray_direction = pixel_center - camera_center; // ray let r = Ray::new(camera_center, ray_direction); - /* 球 */ let _sphere_center = Point::new(0.0, 0.0, -1.0); let sphere_radius = 0.5; + let sphere = Sphere::new(_sphere_center, sphere_radius); // determind color - let color = ray_color_at_sphere_normal(&r, _sphere_center, sphere_radius); + let color = ray_color(&r, sphere); // content img_content.push_str(color.to_color().as_str()); img_content.push('\n'); @@ -44,45 +37,19 @@ pub fn gen_ray_sphere_normal_ppm_p3(width: i32, height: i32, camera_center: Vec3 img_content } -fn hit_sphere_normal(r: &Ray, sphere_center: Point, sphere_radius: f32) -> f32 { - let a: f32 = r.direction.length_squared(); - let h = r.direction.dot(sphere_center - r.point); - // let b = -2.0 * r.direction.dot(sphere_center - r.point); - let c = (sphere_center - r.point).length_squared() - sphere_radius * sphere_radius; - - let discriminant = h*h - a*c; - - // // 两个焦点 - let disc_sqrt = discriminant.sqrt(); - let near = (h - disc_sqrt) / a; - let far = (h + disc_sqrt) / a; - - // 射线起点可能在球内的情况 - if near >= 0.0 && far >= 0.0 { - return near.min(far); - } else if near > 0.0 { - return near; - } else if far > 0.0 { - return far; - } else { - return -1.0 - } -} - /* ray color functions */ -fn ray_color_at_sphere_normal(r: &Ray, sphere_center: Point, sphere_radius: f32) -> Color { - - let t = hit_sphere_normal(r, sphere_center, sphere_radius); - if t >= 0.0 { - let inter_point = r.at(t); +fn ray_color(r: &Ray, h: H) -> Color { + let hr = h.hit(&r, 0.0, f32::MAX); + if hr.t >= 0.0 { + let inter_point = hr.p; // 单位向量 let n = inter_point / inter_point.dot(inter_point); // 法向量也是 -1~1 +1再x0.5让他落到颜色的区间 - return 0.5 * (n - sphere_center + Point::new(1.0, 1.0, 1.0)) + // return 0.5 * (n - sphere_center + Point::new(1.0, 1.0, 1.0)) + return 0.5 * (hr.normal + Point::new(1.0, 1.0, 1.0)) } - // v / |v| let unit_direction = r.direction / r.direction.length(); let a = 0.5*(unit_direction.y + 1.0); diff --git a/src/main.rs b/src/main.rs index 3a80d9c..e0d84b6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,14 +1,15 @@ use write_file_util::{write_image}; -use vec3::{Vec3}; -use point::{Point}; use crate::image::{gen_ray_sphere_normal_ppm_p3}; - +use crate::types_defined::{Point, Vec3}; mod image; mod write_file_util; mod vec3; -mod point; mod ray; +mod hittable; +mod sphere; +mod types_defined; +mod color; fn main() { ray_sphere_normal_scene_render(); diff --git a/src/point.rs b/src/point.rs deleted file mode 100644 index c3e4956..0000000 --- a/src/point.rs +++ /dev/null @@ -1,4 +0,0 @@ -use crate::vec3; - -pub type Point = vec3::Vec3; - diff --git a/src/ray.rs b/src/ray.rs index 17d04a8..e140f51 100644 --- a/src/ray.rs +++ b/src/ray.rs @@ -1,17 +1,6 @@ use std::fmt; use std::fmt::{Display}; - -use crate::{point::Point, vec3::Vec3}; - - -/* -fn: P(t) = t*b -*/ -#[derive(Debug)] -pub struct Ray { - pub point: Point, - pub direction: Vec3 -} +use crate::types_defined::{Point, Ray, Vec3}; impl Ray { pub fn new(p: Point, direction: Vec3) -> Ray { diff --git a/src/types_defined.rs b/src/types_defined.rs new file mode 100644 index 0000000..5557cc7 --- /dev/null +++ b/src/types_defined.rs @@ -0,0 +1,37 @@ +/* +* [3] +*/ +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct Vec3 { + pub x: f32, + pub y: f32, + pub z: f32, +} +pub type Point = Vec3; +pub type Color = Vec3; + +/* +fn: P(t) = t*b +*/ +#[derive(Debug)] +pub struct Ray { + pub point: Point, + pub direction: Vec3 +} + +pub struct HitRecord { + pub t: f32, + pub p: Vec3, + pub normal: Vec3, +} + + +/* +///////////// +// for test +///////////// +*/ +pub struct Sphere { + pub center: Point, + pub radius: f32, +} \ No newline at end of file diff --git a/src/vec3.rs b/src/vec3.rs index 6b2ba95..cc277df 100644 --- a/src/vec3.rs +++ b/src/vec3.rs @@ -1,15 +1,7 @@ use std::{fmt::Display, ops::{Add, AddAssign, Div, Mul, MulAssign, Sub}}; use std::fmt; -/* -* [3] -*/ -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct Vec3 { - pub x: f32, - pub y: f32, - pub z: f32, -} +use crate::types_defined::Vec3; impl Display for Vec3 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {