Add translation and rotation

This commit is contained in:
max.nuding 2022-07-08 15:43:12 +02:00
parent f2a8db6430
commit f5f46a7a0b
Failed to extract signature
4 changed files with 119 additions and 18 deletions

View File

@ -19,6 +19,30 @@ pub struct HitRecord<'material> {
pub material: &'material Arc<Material> pub material: &'material Arc<Material>
} }
impl<'material> HitRecord<'material> {
pub fn normalized(&mut self, ray: &Ray) {
let dot = ray.direction().dot(&self.normal);
let front_face = dot < 0.0;
let normal = if front_face { self.normal } else { -self.normal };
self.normal = normal;
self.front_face = front_face;
}
/*pub fn normalized(& self) -> Self {
let dot = ray.direction().dot(self.normal);
let front_face = dot < 0.0;
let normal = if front_face { self.normal } else { -self.normal };
HitRecord {
point: self.point,
normal,
t: self.t,
u: self.u,
v: self.v,
front_face,
material: self.material
}
}*/
}
pub trait Hittable { pub trait Hittable {
fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option<HitRecord>; fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option<HitRecord>;
fn bounding_box(&self, time0: f64, time1: f64) -> Option<Aabb>; fn bounding_box(&self, time0: f64, time1: f64) -> Option<Aabb>;
@ -74,19 +98,18 @@ impl Hittable for Sphere {
} }
let point = ray.at(root); let point = ray.at(root);
let normal = (point - self.center) / self.radius; let normal = (point - self.center) / self.radius;
let dot = ray.direction().dot(&normal);
let front_face = dot < 0.0;
let (u, v) = Sphere::uv(&normal); let (u, v) = Sphere::uv(&normal);
let normal = if front_face { normal } else { -normal }; let mut rec = HitRecord {
Some(HitRecord {
point, point,
normal, normal,
t: root, t: root,
u, u,
v, v,
front_face, front_face: false, // Will be set during normalied()
material: &self.material material: &self.material
}) };
rec.normalized(ray);
Some(rec)
} }
fn bounding_box(&self, _time0: f64, _time1: f64) -> Option<Aabb> { fn bounding_box(&self, _time0: f64, _time1: f64) -> Option<Aabb> {
let s = Vec3::new(self.radius, self.radius, self.radius); let s = Vec3::new(self.radius, self.radius, self.radius);

View File

@ -17,6 +17,8 @@ use crate::noise::NoiseTexture;
use crate::perlin::Perlin; use crate::perlin::Perlin;
use crate::texture::CheckerTexture; use crate::texture::CheckerTexture;
use crate::rect::{Plane, Rect2D}; use crate::rect::{Plane, Rect2D};
use crate::rotate_y::RotateY;
use crate::translate::Translate;
mod vec3; mod vec3;
mod ray; mod ray;
@ -32,10 +34,12 @@ mod noise;
mod image_texture; mod image_texture;
mod rect; mod rect;
mod cuboid; mod cuboid;
mod translate;
mod rotate_y;
// Image // Image
const DEFAULT_ASPECT_RATIO: f64 = 3.0 / 2.0; const DEFAULT_ASPECT_RATIO: f64 = 3.0 / 2.0;
const IMAGE_WIDTH: usize = 600; const IMAGE_WIDTH: usize = 400;
const SAMPLES_PER_PIXEL: i32 = 100; const SAMPLES_PER_PIXEL: i32 = 100;
const MAX_DEPTH: i32 = 50; const MAX_DEPTH: i32 = 50;
@ -113,16 +117,32 @@ fn cornell_box() -> Scene {
))); )));
// Boxes // Boxes
world.push(Arc::new(Cuboid::new( let rotated1 = RotateY::new(
Point3::new(130.0, 0.0, 65.0), Cuboid::new(
Point3::new(295.0, 165.0, 230.0), Point3::new(0.0, 0.0, 0.0),
white.clone() Point3::new(165.0, 330.0, 165.0),
))); white.clone()
world.push(Arc::new(Cuboid::new( ),
Point3::new(265.0, 0.0, 295.0), 15.0
Point3::new(430.0, 330.0, 460.0), );
white.clone() let box1 = Translate::new(
))); rotated1,
Vec3::new(265.0, 0.0, 295.0)
);
world.push(Arc::new(box1));
let rotated2 = RotateY::new(
Cuboid::new(
Point3::new(0.0, 0.0, 0.0),
Point3::new(165.0, 165.0, 165.0),
white.clone()
),
-18.0
);
let box2 = Translate::new(
rotated2,
Vec3::new(130.0,0.0,65.0)
);
world.push(Arc::new(box2));
let look_from = Point3::new(278.0, 278.0, -800.0); let look_from = Point3::new(278.0, 278.0, -800.0);

48
src/translate.rs Normal file
View File

@ -0,0 +1,48 @@
use crate::hittable::{HitRecord, Hittable};
use crate::{Aabb, Ray, Vec3};
pub struct Translate<H: Hittable> {
hittable: H,
offset: Vec3
}
impl<H: Hittable> Translate<H> {
pub fn new(hittable: H, offset: Vec3) -> Self {
Self { hittable, offset }
}
}
impl<H: Hittable> Hittable for Translate<H> {
fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option<HitRecord> {
let moved_ray = Ray::new(
ray.origin() - self.offset,
ray.direction(),
ray.time());
match &self.hittable.hit(&moved_ray, t_min, t_max) {
Some(hit_record) => {
let mut hr = HitRecord {
point: hit_record.point,
material: hit_record.material,
front_face: hit_record.front_face, // Maybe need to calc normal and front_face again?
normal: hit_record.normal,
t: hit_record.t,
u: hit_record.u,
v: hit_record.v
};
hr.normalized(ray);
Some(hr)
}
_ => None
}
}
fn bounding_box(&self, time0: f64, time1: f64) -> Option<Aabb> {
match &self.hittable.bounding_box(time0, time1) {
Some(bounding_box) => Some(Aabb {
minimum: bounding_box.minimum + self.offset,
maximum: bounding_box.maximum + self.offset,
}),
_ => None
}
}
}

View File

@ -1,5 +1,5 @@
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::ops::{Add, AddAssign, Div, Mul, Neg, Sub, Index, MulAssign}; use std::ops::{Add, AddAssign, Div, Mul, Neg, Sub, Index, MulAssign, IndexMut};
use rand::distributions::{Distribution, Uniform}; use rand::distributions::{Distribution, Uniform};
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -295,6 +295,16 @@ impl Index<i32> for Vec3 {
} }
} }
} }
impl IndexMut<i32> for Vec3 {
fn index_mut(&mut self, index: i32) -> &mut f64{
match index {
0 => &mut self.x,
1 => &mut self.y,
2 => &mut self.z,
_ => panic!("Unknown index")
}
}
}
impl Index<usize> for Vec3 { impl Index<usize> for Vec3 {
type Output = f64; type Output = f64;
fn index(&self, index: usize) -> &Self::Output { fn index(&self, index: usize) -> &Self::Output {