Add translated and rotated cuboids to cornell box scene.
Chose name 'cuboid' because 'box' is a module imported by the prelude in rust and makes things complicated.
This commit is contained in:
parent
f1fcbe7449
commit
7684bb2088
90
rtiow/src/cuboid.rs
Normal file
90
rtiow/src/cuboid.rs
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use aabb::AABB;
|
||||||
|
use flip_normals::FlipNormals;
|
||||||
|
use hitable::Hit;
|
||||||
|
use hitable::HitRecord;
|
||||||
|
use hitable_list::HitableList;
|
||||||
|
use material::Material;
|
||||||
|
use ray::Ray;
|
||||||
|
use rect::XYRect;
|
||||||
|
use rect::XZRect;
|
||||||
|
use rect::YZRect;
|
||||||
|
use vec3::Vec3;
|
||||||
|
|
||||||
|
pub struct Cuboid {
|
||||||
|
p_min: Vec3,
|
||||||
|
p_max: Vec3,
|
||||||
|
walls: HitableList,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Cuboid {
|
||||||
|
pub fn new(p_min: Vec3, p_max: Vec3, material: Box<Material>) -> Cuboid {
|
||||||
|
let material = Arc::new(material);
|
||||||
|
|
||||||
|
Cuboid {
|
||||||
|
p_min,
|
||||||
|
p_max,
|
||||||
|
walls: HitableList::new(vec![
|
||||||
|
Box::new(XYRect::new(
|
||||||
|
p_min.x,
|
||||||
|
p_max.x,
|
||||||
|
p_min.y,
|
||||||
|
p_max.y,
|
||||||
|
p_max.z,
|
||||||
|
Box::new(Arc::clone(&material)),
|
||||||
|
)),
|
||||||
|
Box::new(FlipNormals::new(Box::new(XYRect::new(
|
||||||
|
p_min.x,
|
||||||
|
p_max.x,
|
||||||
|
p_min.y,
|
||||||
|
p_max.y,
|
||||||
|
p_min.z,
|
||||||
|
Box::new(Arc::clone(&material)),
|
||||||
|
)))),
|
||||||
|
Box::new(XZRect::new(
|
||||||
|
p_min.x,
|
||||||
|
p_max.x,
|
||||||
|
p_min.z,
|
||||||
|
p_max.z,
|
||||||
|
p_max.y,
|
||||||
|
Box::new(Arc::clone(&material)),
|
||||||
|
)),
|
||||||
|
Box::new(FlipNormals::new(Box::new(XZRect::new(
|
||||||
|
p_min.x,
|
||||||
|
p_max.x,
|
||||||
|
p_min.z,
|
||||||
|
p_max.z,
|
||||||
|
p_min.y,
|
||||||
|
Box::new(Arc::clone(&material)),
|
||||||
|
)))),
|
||||||
|
Box::new(YZRect::new(
|
||||||
|
p_min.y,
|
||||||
|
p_max.y,
|
||||||
|
p_min.z,
|
||||||
|
p_max.z,
|
||||||
|
p_max.x,
|
||||||
|
Box::new(Arc::clone(&material)),
|
||||||
|
)),
|
||||||
|
Box::new(FlipNormals::new(Box::new(YZRect::new(
|
||||||
|
p_min.y,
|
||||||
|
p_max.y,
|
||||||
|
p_min.z,
|
||||||
|
p_max.z,
|
||||||
|
p_min.x,
|
||||||
|
Box::new(Arc::clone(&material)),
|
||||||
|
)))),
|
||||||
|
]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hit for Cuboid {
|
||||||
|
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
||||||
|
self.walls.hit(r, t_min, t_max)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bounding_box(&self, _t_min: f32, _t_max: f32) -> Option<AABB> {
|
||||||
|
Some(AABB::new(self.p_min, self.p_max))
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
pub mod aabb;
|
pub mod aabb;
|
||||||
pub mod bvh;
|
pub mod bvh;
|
||||||
pub mod camera;
|
pub mod camera;
|
||||||
|
pub mod cuboid;
|
||||||
pub mod flip_normals;
|
pub mod flip_normals;
|
||||||
pub mod hitable;
|
pub mod hitable;
|
||||||
pub mod hitable_list;
|
pub mod hitable_list;
|
||||||
@ -11,9 +12,11 @@ pub mod perlin;
|
|||||||
pub mod ray;
|
pub mod ray;
|
||||||
pub mod rect;
|
pub mod rect;
|
||||||
pub mod renderer;
|
pub mod renderer;
|
||||||
|
pub mod rotate;
|
||||||
pub mod scenes;
|
pub mod scenes;
|
||||||
pub mod sphere;
|
pub mod sphere;
|
||||||
pub mod texture;
|
pub mod texture;
|
||||||
|
pub mod translate;
|
||||||
pub mod vec3;
|
pub mod vec3;
|
||||||
|
|
||||||
extern crate crossbeam_channel;
|
extern crate crossbeam_channel;
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
use self::rand::Rng;
|
use self::rand::Rng;
|
||||||
|
|
||||||
@ -36,6 +38,15 @@ pub trait Material: Send + Sync {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Material for Arc<Box<Material>> {
|
||||||
|
fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> ScatterResponse {
|
||||||
|
(**self).scatter(r_in, rec)
|
||||||
|
}
|
||||||
|
fn emitted(&self, u: f32, v: f32, p: Vec3) -> Vec3 {
|
||||||
|
(**self).emitted(u, v, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Lambertian {
|
pub struct Lambertian {
|
||||||
// TODO(wathiede): implement texture sharing via references
|
// TODO(wathiede): implement texture sharing via references
|
||||||
albedo: Box<Texture>,
|
albedo: Box<Texture>,
|
||||||
|
|||||||
90
rtiow/src/rotate.rs
Normal file
90
rtiow/src/rotate.rs
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
use std::f32::consts::PI;
|
||||||
|
use std::f32::MAX;
|
||||||
|
use std::f32::MIN;
|
||||||
|
|
||||||
|
use aabb::AABB;
|
||||||
|
use hitable::Hit;
|
||||||
|
use hitable::HitRecord;
|
||||||
|
use ray::Ray;
|
||||||
|
use vec3::Vec3;
|
||||||
|
|
||||||
|
pub struct RotateY {
|
||||||
|
hitable: Box<Hit>,
|
||||||
|
sin_theta: f32,
|
||||||
|
cos_theta: f32,
|
||||||
|
bbox: Option<AABB>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RotateY {
|
||||||
|
pub fn new(hitable: Box<Hit>, angle: f32) -> RotateY {
|
||||||
|
let radians = PI / 180. * angle;
|
||||||
|
let sin_theta = radians.sin();
|
||||||
|
let cos_theta = radians.cos();
|
||||||
|
let mut min = vec![MAX, MAX, MAX];
|
||||||
|
let mut max = vec![MIN, MIN, MIN];
|
||||||
|
let bbox = hitable.bounding_box(0., 1.).unwrap();
|
||||||
|
for i in 0..2 {
|
||||||
|
for j in 0..2 {
|
||||||
|
for k in 0..2 {
|
||||||
|
let x = i as f32 * bbox.max().x + (1 - i) as f32 * bbox.min().x;
|
||||||
|
let y = j as f32 * bbox.max().y + (1 - j) as f32 * bbox.min().y;
|
||||||
|
let z = k as f32 * bbox.max().z + (1 - k) as f32 * bbox.min().z;
|
||||||
|
let new_x = cos_theta * x + sin_theta * z;
|
||||||
|
let new_z = -sin_theta * x + cos_theta * z;
|
||||||
|
let tester = Vec3::new(new_x, y, new_z);
|
||||||
|
for c in 0..3 {
|
||||||
|
if tester[c] > max[c] {
|
||||||
|
max[c] = tester[c];
|
||||||
|
}
|
||||||
|
if tester[c] < min[c] {
|
||||||
|
min[c] = tester[c];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RotateY {
|
||||||
|
hitable,
|
||||||
|
sin_theta,
|
||||||
|
cos_theta,
|
||||||
|
bbox: Some(AABB::new(
|
||||||
|
Vec3::new(min[0], min[1], min[2]),
|
||||||
|
Vec3::new(max[0], max[1], max[2]),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hit for RotateY {
|
||||||
|
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
||||||
|
let origin = Vec3::new(
|
||||||
|
self.cos_theta * r.origin[0] - self.sin_theta * r.origin[2],
|
||||||
|
r.origin.y,
|
||||||
|
self.sin_theta * r.origin[0] + self.cos_theta * r.origin[2],
|
||||||
|
);
|
||||||
|
let direction = Vec3::new(
|
||||||
|
self.cos_theta * r.direction[0] - self.sin_theta * r.direction[2],
|
||||||
|
r.direction.y,
|
||||||
|
self.sin_theta * r.direction[0] + self.cos_theta * r.direction[2],
|
||||||
|
);
|
||||||
|
let rotated_r = Ray::new(origin, direction, r.time);
|
||||||
|
if let Some(rec) = self.hitable.hit(rotated_r, t_min, t_max) {
|
||||||
|
let p = Vec3::new(
|
||||||
|
self.cos_theta * rec.p[0] + self.sin_theta * rec.p[2],
|
||||||
|
rec.p[1],
|
||||||
|
-self.sin_theta * rec.p[0] + self.cos_theta * rec.p[2],
|
||||||
|
);
|
||||||
|
let normal = Vec3::new(
|
||||||
|
self.cos_theta * rec.normal[0] + self.sin_theta * rec.normal[2],
|
||||||
|
rec.normal[1],
|
||||||
|
-self.sin_theta * rec.normal[0] + self.cos_theta * rec.normal[2],
|
||||||
|
);
|
||||||
|
return Some(HitRecord { p, normal, ..rec });
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bounding_box(&self, _t_min: f32, _t_max: f32) -> Option<AABB> {
|
||||||
|
self.bbox.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
use camera::Camera;
|
use camera::Camera;
|
||||||
|
use cuboid::Cuboid;
|
||||||
use flip_normals::FlipNormals;
|
use flip_normals::FlipNormals;
|
||||||
use hitable::Hit;
|
use hitable::Hit;
|
||||||
use hitable_list::HitableList;
|
use hitable_list::HitableList;
|
||||||
@ -10,7 +11,9 @@ use rect::XZRect;
|
|||||||
use rect::YZRect;
|
use rect::YZRect;
|
||||||
use renderer::Opt;
|
use renderer::Opt;
|
||||||
use renderer::Scene;
|
use renderer::Scene;
|
||||||
|
use rotate::RotateY;
|
||||||
use texture::ConstantTexture;
|
use texture::ConstantTexture;
|
||||||
|
use translate::Translate;
|
||||||
use vec3::Vec3;
|
use vec3::Vec3;
|
||||||
|
|
||||||
pub fn new(opt: &Opt) -> Scene {
|
pub fn new(opt: &Opt) -> Scene {
|
||||||
@ -33,6 +36,34 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let objects: Vec<Box<Hit>> = vec![
|
let objects: Vec<Box<Hit>> = vec![
|
||||||
|
// Box1
|
||||||
|
Box::new(Translate::new(
|
||||||
|
Box::new(RotateY::new(
|
||||||
|
Box::new(Cuboid::new(
|
||||||
|
Vec3::new(0., 0., 0.),
|
||||||
|
Vec3::new(165., 165., 165.),
|
||||||
|
Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new(
|
||||||
|
0.73, 0.73, 0.73,
|
||||||
|
))))),
|
||||||
|
)),
|
||||||
|
-18.,
|
||||||
|
)),
|
||||||
|
Vec3::new(100., 0., 0.),
|
||||||
|
)),
|
||||||
|
// Box2
|
||||||
|
Box::new(Translate::new(
|
||||||
|
Box::new(RotateY::new(
|
||||||
|
Box::new(Cuboid::new(
|
||||||
|
Vec3::new(0., 0., 0.),
|
||||||
|
Vec3::new(165., 330., 165.),
|
||||||
|
Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new(
|
||||||
|
0.73, 0.73, 0.73,
|
||||||
|
))))),
|
||||||
|
)),
|
||||||
|
15.,
|
||||||
|
)),
|
||||||
|
Vec3::new(265., 0., 295.),
|
||||||
|
)),
|
||||||
// Green wall left
|
// Green wall left
|
||||||
Box::new(FlipNormals::new(Box::new(YZRect::new(
|
Box::new(FlipNormals::new(Box::new(YZRect::new(
|
||||||
0.,
|
0.,
|
||||||
|
|||||||
39
rtiow/src/translate.rs
Normal file
39
rtiow/src/translate.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
use aabb::AABB;
|
||||||
|
use hitable::Hit;
|
||||||
|
use hitable::HitRecord;
|
||||||
|
use ray::Ray;
|
||||||
|
use vec3::Vec3;
|
||||||
|
|
||||||
|
pub struct Translate {
|
||||||
|
hitable: Box<Hit>,
|
||||||
|
offset: Vec3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Translate {
|
||||||
|
pub fn new(hitable: Box<Hit>, offset: Vec3) -> Translate {
|
||||||
|
Translate { hitable, offset }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hit for Translate {
|
||||||
|
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
||||||
|
let moved_r = Ray::new(r.origin - self.offset, r.direction, r.time);
|
||||||
|
if let Some(rec) = self.hitable.hit(moved_r, t_min, t_max) {
|
||||||
|
return Some(HitRecord {
|
||||||
|
p: rec.p + self.offset,
|
||||||
|
..rec
|
||||||
|
});
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bounding_box(&self, t_min: f32, t_max: f32) -> Option<AABB> {
|
||||||
|
if let Some(bbox) = self.hitable.bounding_box(t_min, t_max) {
|
||||||
|
return Some(AABB::new(
|
||||||
|
bbox.min() + self.offset,
|
||||||
|
bbox.max() + self.offset,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user