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 {
|
pub struct HitRecord {
|
||||||
p: Point3,
|
p: Point3,
|
||||||
normal: Vec3,
|
pub normal: Vec3,
|
||||||
t: f64,
|
pub t: f64,
|
||||||
|
front_face: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Sphere {
|
pub struct Sphere {
|
||||||
|
@ -14,11 +15,35 @@ pub struct Sphere {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Hittable {
|
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 {
|
impl Sphere {
|
||||||
fn new(cen: Point3, r: f64) -> Self {
|
pub fn new(cen: Point3, r: f64) -> Self {
|
||||||
Sphere {
|
Sphere {
|
||||||
center: cen,
|
center: cen,
|
||||||
radius: r,
|
radius: r,
|
||||||
|
@ -27,22 +52,22 @@ impl Sphere {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hittable for 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 oc = r.origin() - self.center;
|
||||||
let a = r.direction().length_squared(); // gleiches Ergebnis wie Skalarprodukt
|
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 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 {
|
if discriminant < 0.0 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let sqrtd = discriminant.sqrt();
|
let sqrtd = discriminant.sqrt();
|
||||||
|
|
||||||
let root = (-b / 2.0 - sqrtd) / a;
|
let root = (-half_b - sqrtd) / a;
|
||||||
if root < t_min || t_max < root {
|
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 {
|
if root2 < t_min || t_max < root {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +75,8 @@ impl Hittable for Sphere {
|
||||||
|
|
||||||
rec.t = root;
|
rec.t = root;
|
||||||
rec.p = r.at(rec.t);
|
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;
|
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 color;
|
||||||
mod hittable;
|
mod hittable;
|
||||||
|
mod hittable_list;
|
||||||
mod ray;
|
mod ray;
|
||||||
mod vec3;
|
mod vec3;
|
||||||
|
mod utility;
|
||||||
use ray::Ray;
|
use ray::Ray;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
@ -10,6 +12,10 @@ use std::io::Write;
|
||||||
use vec3::Color;
|
use vec3::Color;
|
||||||
use vec3::Point3;
|
use vec3::Point3;
|
||||||
use vec3::Vec3;
|
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 {
|
fn hit_sphere(center: &Point3, radius: f64, r: &Ray) -> f64 {
|
||||||
let oc = r.origin() - *center;
|
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 {
|
fn ray_color(r: &Ray, world: &HittableList) -> Color {
|
||||||
let t = hit_sphere(&Point3::new(0.0, 0.0, -1.0), 0.5, r);
|
let mut rec = HitRecord::empty();
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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 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);
|
||||||
|
@ -43,9 +48,14 @@ fn main() {
|
||||||
|
|
||||||
// Image
|
// Image
|
||||||
let aspect_ratio = 16.0 / 9.0;
|
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;
|
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
|
// Camera
|
||||||
let viewport_height = 2.0;
|
let viewport_height = 2.0;
|
||||||
let viewport_width = aspect_ratio * viewport_height;
|
let viewport_width = aspect_ratio * viewport_height;
|
||||||
|
@ -74,7 +84,7 @@ fn main() {
|
||||||
origin,
|
origin,
|
||||||
lower_left_corner + u * horizontal + v * vertical - 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);
|
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