Add translation and rotation
This commit is contained in:
parent
f2a8db6430
commit
f5f46a7a0b
@ -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);
|
||||||
|
38
src/main.rs
38
src/main.rs
@ -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),
|
||||||
|
Point3::new(165.0, 330.0, 165.0),
|
||||||
white.clone()
|
white.clone()
|
||||||
)));
|
),
|
||||||
world.push(Arc::new(Cuboid::new(
|
15.0
|
||||||
Point3::new(265.0, 0.0, 295.0),
|
);
|
||||||
Point3::new(430.0, 330.0, 460.0),
|
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()
|
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
48
src/translate.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
src/vec3.rs
12
src/vec3.rs
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user