feat(plane): add a special checkerboard plane
This commit is contained in:
parent
c3d6d80fd7
commit
61b5437561
@ -1,6 +1,6 @@
|
||||
use lispers::raytracer::{
|
||||
camera::Camera,
|
||||
plane::Plane,
|
||||
plane::Checkerboard,
|
||||
scene::Scene,
|
||||
sphere::Sphere,
|
||||
types::{Color, Light, Material, Point3, Vector3},
|
||||
@ -12,10 +12,10 @@ use std::time::Instant;
|
||||
fn main() {
|
||||
let mut scene = Scene::new();
|
||||
|
||||
scene.set_ambient(Color::new(0.2, 0.2, 0.2));
|
||||
scene.set_ambient(Color::new(0.1, 0.1, 0.1));
|
||||
|
||||
scene.add_light(Light {
|
||||
position: Point3::new(4.0, 7.0, 10.0),
|
||||
position: Point3::new(5.0, 7.0, 10.0),
|
||||
color: Color::new(1.0, 1.0, 1.0),
|
||||
});
|
||||
scene.add_light(Light {
|
||||
@ -23,16 +23,25 @@ fn main() {
|
||||
color: Color::new(1.0, 1.0, 1.0),
|
||||
});
|
||||
|
||||
scene.add_object(Arc::new(Plane::new(
|
||||
scene.add_object(Arc::new(Checkerboard::new(
|
||||
Point3::new(0.0, -1.0, 0.0),
|
||||
Vector3::new(0.0, 1.0, 0.0),
|
||||
Material::new(
|
||||
Color::new(0.5, 0.5, 0.5),
|
||||
Color::new(0.5, 0.5, 0.5),
|
||||
Color::new(1.0, 1.0, 1.0),
|
||||
Color::new(1.0, 1.0, 1.0),
|
||||
Color::new(0.0, 0.0, 0.0),
|
||||
0.0,
|
||||
0.6,
|
||||
0.5,
|
||||
),
|
||||
Material::new(
|
||||
Color::new(0.0, 0.0, 0.0),
|
||||
Color::new(0.0, 0.0, 0.0),
|
||||
Color::new(0.0, 0.0, 0.0),
|
||||
0.0,
|
||||
0.5,
|
||||
),
|
||||
0.3,
|
||||
Vector3::new(0.0, 0.0, 1.0),
|
||||
)));
|
||||
|
||||
scene.add_object(Arc::new(Sphere::new(
|
||||
@ -76,14 +85,14 @@ fn main() {
|
||||
Point3::new(-1.0, -0.5, 0.0),
|
||||
Vector3::new(0.0, 1.0, 0.0),
|
||||
60.0,
|
||||
4 * 256,
|
||||
3 * 256,
|
||||
4 * 512,
|
||||
3 * 512,
|
||||
);
|
||||
|
||||
let fname = "demo-scene.png";
|
||||
print!("Rendering demo scene...");
|
||||
let start = Instant::now();
|
||||
match camera.render(&scene, 5, 3).save(fname) {
|
||||
match camera.render(&scene, 10, 4).save(fname) {
|
||||
Ok(_) => {
|
||||
println!(" finished ({}s) ", start.elapsed().as_secs_f32());
|
||||
println!("Image saved to {}", fname)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use super::types::{Intersect, Material, Point3, Vector3};
|
||||
use super::types::{Intersect, Material, Point3, Scalar, Vector3};
|
||||
|
||||
extern crate nalgebra as na;
|
||||
|
||||
@ -12,6 +12,18 @@ pub struct Plane {
|
||||
material: Material,
|
||||
}
|
||||
|
||||
/// A infinite checkerboard plane in 3D space.
|
||||
pub struct Checkerboard {
|
||||
/// The base plane containing the "white" material
|
||||
base: Plane,
|
||||
/// An alternative "black" material
|
||||
material_alt: Material,
|
||||
/// The scale of the checkerboard (side-length of each square)
|
||||
scale: f64,
|
||||
/// A projection matrix to map 3D points to the 2D plane space.
|
||||
projection_matrix: na::Matrix2x3<Scalar>,
|
||||
}
|
||||
|
||||
impl Plane {
|
||||
/// Create a new plane.
|
||||
/// - `position` is the position of the plane.
|
||||
@ -26,6 +38,32 @@ impl Plane {
|
||||
}
|
||||
}
|
||||
|
||||
impl Checkerboard {
|
||||
/// Create a new Checkerboard Plane.
|
||||
/// - `position` is the position of the plane.
|
||||
/// - `normal` is the normal of the plane.
|
||||
/// - `material1` is the material of the "white" squares.
|
||||
/// - `material2` is the material of the "black" squares.
|
||||
/// - `scale` is the side-length of each square.
|
||||
/// - `up` is "y" direction on the plane in 3D-Space.
|
||||
pub fn new(
|
||||
position: Point3,
|
||||
normal: Vector3,
|
||||
material1: Material,
|
||||
material2: Material,
|
||||
scale: f64,
|
||||
up: Vector3,
|
||||
) -> Checkerboard {
|
||||
let right = up.cross(&normal).normalize();
|
||||
Checkerboard {
|
||||
base: Plane::new(position, normal, material1),
|
||||
material_alt: material2,
|
||||
scale,
|
||||
projection_matrix: na::Matrix3x2::from_columns(&[right, up]).transpose(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Intersect for Plane {
|
||||
fn intersect<'a>(
|
||||
&'a self,
|
||||
@ -49,3 +87,30 @@ impl Intersect for Plane {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Intersect for Checkerboard {
|
||||
fn intersect<'a>(
|
||||
&'a self,
|
||||
ray: &super::types::Ray,
|
||||
) -> Option<(
|
||||
Point3,
|
||||
Vector3,
|
||||
super::types::Scalar,
|
||||
&'a super::types::Material,
|
||||
)> {
|
||||
if let Some((point, normal, t, material)) = self.base.intersect(ray) {
|
||||
let v3 = point - self.base.position;
|
||||
let v2 = self.projection_matrix * v3;
|
||||
|
||||
if ((v2.x / self.scale).round() % 2.0 == 0.0)
|
||||
== ((v2.y / self.scale).round() % 2.0 == 0.0)
|
||||
{
|
||||
Some((point, normal, t, material))
|
||||
} else {
|
||||
Some((point, normal, t, &self.material_alt))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user