Multisphärisch
This commit is contained in:
parent
1c1fca3dfc
commit
94848e45ac
4 changed files with 94 additions and 18 deletions
|
@ -4,8 +4,9 @@ use super::Vec3;
|
|||
|
||||
pub struct HitRecord {
|
||||
p: Point3,
|
||||
normal: Vec3,
|
||||
t: f64,
|
||||
pub normal: Vec3,
|
||||
pub t: f64,
|
||||
front_face: bool,
|
||||
}
|
||||
|
||||
pub struct Sphere {
|
||||
|
@ -14,11 +15,35 @@ pub struct Sphere {
|
|||
}
|
||||
|
||||
pub trait Hittable {
|
||||
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;
|
||||
}
|
||||
|
||||
impl HitRecord {
|
||||
fn set_face_normal(&mut self, r: &Ray, outward_normal: Vec3) {
|
||||
self.front_face = Vec3::dot(r.direction(), outward_normal) < 0.0;
|
||||
if self.front_face {
|
||||
self.normal = outward_normal;
|
||||
} else {
|
||||
self.normal = (-1.0)*outward_normal;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(p: Point3, normal: Vec3, t: f64, front_face: bool) -> Self {
|
||||
HitRecord {
|
||||
p: p,
|
||||
normal: normal,
|
||||
t: t,
|
||||
front_face: front_face,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn empty() -> Self {
|
||||
Self::new(Point3::new(0.0,0.0,0.0), Vec3::new(0.0,0.0,0.0), 0.0, false)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sphere {
|
||||
fn new(cen: Point3, r: f64) -> Self {
|
||||
pub fn new(cen: Point3, r: f64) -> Self {
|
||||
Sphere {
|
||||
center: cen,
|
||||
radius: r,
|
||||
|
@ -27,22 +52,22 @@ impl Sphere {
|
|||
}
|
||||
|
||||
impl Hittable for Sphere {
|
||||
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 {
|
||||
let oc = r.origin() - self.center;
|
||||
let a = r.direction().length_squared(); // gleiches Ergebnis wie Skalarprodukt
|
||||
let b = 2.0 * Vec3::dot(oc, r.direction());
|
||||
let half_b = Vec3::dot(oc, r.direction());
|
||||
let c = oc.length_squared() - self.radius * self.radius;
|
||||
|
||||
let discriminant = b * b - 4.0 * a * c;
|
||||
let discriminant = half_b * half_b - a * c;
|
||||
if discriminant < 0.0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
let sqrtd = discriminant.sqrt();
|
||||
|
||||
let root = (-b / 2.0 - sqrtd) / a;
|
||||
let root = (-half_b - sqrtd) / a;
|
||||
if root < t_min || t_max < root {
|
||||
let root2 = (-b / 2.0 + sqrtd) / a;
|
||||
let root2 = (-half_b + sqrtd) / a;
|
||||
if root2 < t_min || t_max < root {
|
||||
return false;
|
||||
}
|
||||
|
@ -50,7 +75,8 @@ impl Hittable for Sphere {
|
|||
|
||||
rec.t = root;
|
||||
rec.p = r.at(rec.t);
|
||||
rec.normal = (rec.p - self.center) / self.radius;
|
||||
let outward_normal = (rec.p - self.center) / self.radius;
|
||||
rec.set_face_normal(r, outward_normal);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
40
src/hittable_list.rs
Normal file
40
src/hittable_list.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
use super::Hittable;
|
||||
use super::Ray;
|
||||
use super::HitRecord;
|
||||
|
||||
pub struct HittableList {
|
||||
objects: Vec<Box<dyn Hittable>>,
|
||||
}
|
||||
|
||||
impl HittableList {
|
||||
pub fn new()-> Self {
|
||||
HittableList {
|
||||
objects: Vec::<Box<dyn Hittable>>::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.objects.clear();
|
||||
}
|
||||
|
||||
pub fn add(&mut self, obj: Box<dyn Hittable>) {
|
||||
self.objects.push(obj);
|
||||
}
|
||||
|
||||
pub fn hit(&self, r: &Ray, t_min: f64, t_max: f64, rec: &mut HitRecord) -> bool {
|
||||
|
||||
let mut hit_anything = false;
|
||||
let mut closest_so_far = t_max;
|
||||
|
||||
for obj in &self.objects {
|
||||
let mut temp_rec = HitRecord::empty();
|
||||
if obj.hit(&r, t_min, closest_so_far, &mut temp_rec) {
|
||||
hit_anything = true;
|
||||
closest_so_far = temp_rec.t;
|
||||
*rec = temp_rec;
|
||||
}
|
||||
}
|
||||
|
||||
return hit_anything;
|
||||
}
|
||||
}
|
26
src/main.rs
26
src/main.rs
|
@ -1,7 +1,9 @@
|
|||
mod color;
|
||||
mod hittable;
|
||||
mod hittable_list;
|
||||
mod ray;
|
||||
mod vec3;
|
||||
mod utility;
|
||||
use ray::Ray;
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
|
@ -10,6 +12,10 @@ use std::io::Write;
|
|||
use vec3::Color;
|
||||
use vec3::Point3;
|
||||
use vec3::Vec3;
|
||||
use hittable::Hittable;
|
||||
use hittable::Sphere;
|
||||
use hittable_list::HittableList;
|
||||
use hittable::HitRecord;
|
||||
|
||||
fn hit_sphere(center: &Point3, radius: f64, r: &Ray) -> f64 {
|
||||
let oc = r.origin() - *center;
|
||||
|
@ -25,13 +31,12 @@ fn hit_sphere(center: &Point3, radius: f64, r: &Ray) -> f64 {
|
|||
}
|
||||
}
|
||||
|
||||
fn ray_color(r: &Ray) -> Color {
|
||||
let t = hit_sphere(&Point3::new(0.0, 0.0, -1.0), 0.5, r);
|
||||
if t > 0.0 {
|
||||
let n = Vec3::unit_vector(r.at(t) - Vec3::new(0.0, 0.0, -1.0));
|
||||
return 0.5 * Color::new(n.x() + 1.0, n.y() + 1.0, n.z() + 1.0);
|
||||
}
|
||||
fn ray_color(r: &Ray, world: &HittableList) -> Color {
|
||||
let mut rec = HitRecord::empty();
|
||||
|
||||
if world.hit(r, 0.0, f64::INFINITY, &mut rec) {
|
||||
return 0.5 * (rec.normal + Color::new(1.0, 1.0, 1.0));
|
||||
}
|
||||
let unit_direction = r.direction();
|
||||
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);
|
||||
|
@ -43,9 +48,14 @@ fn main() {
|
|||
|
||||
// Image
|
||||
let aspect_ratio = 16.0 / 9.0;
|
||||
let image_width = 2000;
|
||||
let image_width = 1000;
|
||||
let image_height = (image_width as f64 / aspect_ratio) as u64;
|
||||
|
||||
// World
|
||||
let mut world = HittableList::new();
|
||||
world.add(Box::<Sphere>::new(Sphere::new(Point3::new(0.0, 0.0, -1.0), 0.5)));
|
||||
world.add(Box::<Sphere>::new(Sphere::new(Point3::new(0.0, -100.5, -1.0), 100.0)));
|
||||
|
||||
// Camera
|
||||
let viewport_height = 2.0;
|
||||
let viewport_width = aspect_ratio * viewport_height;
|
||||
|
@ -74,7 +84,7 @@ fn main() {
|
|||
origin,
|
||||
lower_left_corner + u * horizontal + v * vertical - origin,
|
||||
);
|
||||
let pixel_color = ray_color(&r);
|
||||
let pixel_color = ray_color(&r, &mut world);
|
||||
|
||||
color::write_color(&mut file, pixel_color);
|
||||
}
|
||||
|
|
0
src/utility.rs
Normal file
0
src/utility.rs
Normal file
Loading…
Reference in a new issue