Add color mapping to planes
This commit is contained in:
parent
ff625f576f
commit
639518c317
|
@ -14,10 +14,10 @@ This list may be changed or extended in the future.
|
||||||
- [x] Sphere intersection test
|
- [x] Sphere intersection test
|
||||||
- [x] Sphere normal generation
|
- [x] Sphere normal generation
|
||||||
- [x] Color mapping on spheres
|
- [x] Color mapping on spheres
|
||||||
- [ ] Plane objects
|
- [x] Plane objects
|
||||||
- [x] Plane struct
|
- [x] Plane struct
|
||||||
- [x] Plane intersection test
|
- [x] Plane intersection test
|
||||||
- [ ] Color mapping on planes
|
- [x] Color mapping on planes
|
||||||
- [ ] Triangle objects
|
- [ ] Triangle objects
|
||||||
- [ ] Triangle struct
|
- [ ] Triangle struct
|
||||||
- [ ] Triangle intersection test
|
- [ ] Triangle intersection test
|
||||||
|
|
|
@ -17,11 +17,11 @@ pub struct Camera {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Camera {
|
impl Camera {
|
||||||
// Constructs a new camera from a position and viewing direction
|
|
||||||
// (assuming the camera is oriented upright).
|
// Constructs a new camera from a position and viewing direction.
|
||||||
pub fn new(pos: Point3<f32>, dir: Vector3<f32>, focal_length: f32,
|
pub fn new_(pos: Point3<f32>, dir: Vector3<f32>, up: Vector3<f32>, focal_length: f32,
|
||||||
canvas_x: f32, canvas_y: f32, image_x: u32, image_y: u32) -> Self {
|
canvas_x: f32, canvas_y: f32, image_x: u32, image_y: u32) -> Self {
|
||||||
let iso = Isometry3::face_towards(&pos, &(pos + dir), &Vector3::y());
|
let iso = Isometry3::face_towards(&pos, &(pos + dir), &up);
|
||||||
Camera {
|
Camera {
|
||||||
matrix: iso,
|
matrix: iso,
|
||||||
focal_length: focal_length,
|
focal_length: focal_length,
|
||||||
|
@ -30,6 +30,12 @@ impl Camera {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Constructs a new camera from a position and viewing direction
|
||||||
|
// (assuming the camera is oriented upright).
|
||||||
|
pub fn new(pos: Point3<f32>, dir: Vector3<f32>, focal_length: f32,
|
||||||
|
canvas_x: f32, canvas_y: f32, image_x: u32, image_y: u32) -> Self
|
||||||
|
{ Camera::new_(pos, dir, Vector3::y(), focal_length, canvas_x, canvas_y, image_x, image_y) }
|
||||||
|
|
||||||
pub fn pos(&self) -> Point3<f32> { Point3::from(self.matrix.translation.vector) }
|
pub fn pos(&self) -> Point3<f32> { Point3::from(self.matrix.translation.vector) }
|
||||||
|
|
||||||
// Takes a 2D point in the image space and
|
// Takes a 2D point in the image space and
|
||||||
|
|
|
@ -52,10 +52,12 @@ fn render(camera: &Camera, scene: &Scene, filename: &str) -> std::io::Result<()>
|
||||||
|
|
||||||
fn main() -> std::io::Result<()> {
|
fn main() -> std::io::Result<()> {
|
||||||
|
|
||||||
let camera = Camera::new(Point3::new(0.0,0.0,0.0), Vector3::new(0.0,0.0,-1.0), 1.0, 2.0, 2.0, 500, 500);
|
let camera = Camera::new(Point3::new(0.0,1.0,0.0), Vector3::new(0.0,0.0,1.0), 1.0, 2.0, 2.0, 500, 500);
|
||||||
|
|
||||||
let scene = vec![
|
let scene = vec![
|
||||||
Object::new(Sphere::new(0.0,0.0,-3.0,2.0, |x, y| Color::new(x, 0.0, y * 2.0)))
|
Object::new(Plane::xz(|x, y| Color::new(y.sin(), x.cos(), 0.0))),
|
||||||
|
Object::new(Plane::new(Point3::new(0.0, 2.0, 0.0), Vector3::z(), Vector3::x(), |x, y| Color::new(x.sin(), y.cos(), 0.0)))
|
||||||
|
// Object::new(Sphere::new_solid(0.0, 0.0, 0.0, 3.0, Color::white()))
|
||||||
];
|
];
|
||||||
|
|
||||||
render(&camera, &scene, "out.ppm")
|
render(&camera, &scene, "out.ppm")
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
|
|
||||||
mod base; pub use base::*;
|
|
||||||
mod sphere; pub use sphere::*;
|
mod sphere; pub use sphere::*;
|
||||||
mod plane; pub use plane::*;
|
mod plane; pub use plane::*;
|
||||||
mod triangle; pub use triangle::*;
|
mod triangle; pub use triangle::*;
|
||||||
|
@ -8,6 +7,14 @@ use na::*;
|
||||||
|
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
|
||||||
|
pub trait Surface {
|
||||||
|
fn intersect(&self, ray: Ray) -> Option<f32>;
|
||||||
|
|
||||||
|
fn normal(&self, point: Point3<f32>) -> Unit<Vector3<f32>>;
|
||||||
|
|
||||||
|
fn getcolor(&self, point: Point3<f32>) -> Color;
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Object {
|
pub struct Object {
|
||||||
pub surface: Box<dyn Surface>
|
pub surface: Box<dyn Surface>
|
||||||
}
|
}
|
||||||
|
@ -23,3 +30,17 @@ impl Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Scene = Vec<Object>;
|
pub type Scene = Vec<Object>;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn obj_getcolor() {
|
||||||
|
let sphere = Object::new(Sphere::new_solid(0.0, 0.0, 0.0, 1.0, Color::white()));
|
||||||
|
|
||||||
|
let point = Point3::new(1.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
assert_eq!(sphere.getcolor(point), Color::white());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
extern crate nalgebra as na;
|
|
||||||
|
|
||||||
use na::*;
|
|
||||||
use na::geometry::Point3;
|
|
||||||
|
|
||||||
use crate::types::*;
|
|
||||||
|
|
||||||
pub trait Surface {
|
|
||||||
fn intersect(&self, ray: Ray) -> Option<f32>;
|
|
||||||
|
|
||||||
fn normal(&self, point: Point3<f32>) -> Unit<Vector3<f32>>;
|
|
||||||
|
|
||||||
fn getcolor(&self, point: Point3<f32>) -> Color;
|
|
||||||
}
|
|
|
@ -4,28 +4,38 @@ use na::*;
|
||||||
use na::geometry::Point3;
|
use na::geometry::Point3;
|
||||||
|
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
use super::base::*;
|
use super::Surface;
|
||||||
|
|
||||||
pub struct Plane {
|
pub struct Plane {
|
||||||
pub center: Point3<f32>,
|
pub center: Point3<f32>,
|
||||||
pub normal: Unit<Vector3<f32>>,
|
pub normal: Unit<Vector3<f32>>,
|
||||||
|
|
||||||
pub texture: Box<dyn Fn(f32, f32) -> Color>
|
x_axis: Vector3<f32>,
|
||||||
|
y_axis: Vector3<f32>,
|
||||||
|
texture: Box<dyn Fn(f32, f32) -> Color>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Plane {
|
impl Plane {
|
||||||
pub fn new<F: 'static>(center: Point3<f32>, normal: Vector3<f32>, texture: F) -> Self
|
pub fn new<F: 'static>(center: Point3<f32>, x_axis: Vector3<f32>, y_axis: Vector3<f32>, texture: F) -> Self
|
||||||
where F: Fn(f32, f32) -> Color
|
where F: Fn(f32, f32) -> Color
|
||||||
{
|
{
|
||||||
Plane {
|
Plane {
|
||||||
center: center,
|
center: center,
|
||||||
normal: Unit::new_normalize(normal),
|
normal: Unit::new_normalize(x_axis.cross(&y_axis)),
|
||||||
|
x_axis: x_axis,
|
||||||
|
y_axis: y_axis,
|
||||||
texture: Box::new(texture)
|
texture: Box::new(texture)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_solid(center: Point3<f32>, normal: Vector3<f32>, color: Color) -> Self
|
pub fn new_solid(center: Point3<f32>, x_axis: Vector3<f32>, y_axis: Vector3<f32>, color: Color) -> Self
|
||||||
{ Plane::new(center, normal, move |_, _| color) }
|
{ Plane::new(center, x_axis, y_axis, move |_, _| color) }
|
||||||
|
|
||||||
|
pub fn xy<F: 'static + Fn(f32, f32) -> Color>(texture: F) -> Self
|
||||||
|
{ Plane::new(Point3::origin(), Vector3::x(), Vector3::y(), texture) }
|
||||||
|
|
||||||
|
pub fn xz<F: 'static + Fn(f32, f32) -> Color>(texture: F) -> Self
|
||||||
|
{ Plane::new(Point3::origin(), Vector3::x(), Vector3::z(), texture) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Surface for Plane {
|
impl Surface for Plane {
|
||||||
|
@ -43,6 +53,45 @@ impl Surface for Plane {
|
||||||
fn normal(&self, _point: Point3<f32>) -> Unit<Vector3<f32>> { self.normal }
|
fn normal(&self, _point: Point3<f32>) -> Unit<Vector3<f32>> { self.normal }
|
||||||
|
|
||||||
fn getcolor(&self, point: Point3<f32>) -> Color {
|
fn getcolor(&self, point: Point3<f32>) -> Color {
|
||||||
unimplemented!()
|
let rel_pos = point - self.center;
|
||||||
|
let proj_point3 = rel_pos - (*self.normal * self.normal.dot(&rel_pos));
|
||||||
|
|
||||||
|
let x = proj_point3.dot(&self.x_axis);
|
||||||
|
let y = proj_point3.dot(&self.y_axis);
|
||||||
|
|
||||||
|
(*self.texture)(x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn plane_new() {
|
||||||
|
let plane = Plane::xy(|_, _| Color::black());
|
||||||
|
|
||||||
|
assert_eq!(plane.center, Point3::new(0.0, 0.0, 0.0));
|
||||||
|
assert_eq!(plane.normal, Unit::new_unchecked(Vector3::z()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn plane_intersect() {
|
||||||
|
const N: f32 = 5.0;
|
||||||
|
let plane = Plane::xz(|_, _| Color::black());
|
||||||
|
|
||||||
|
let ray = Ray::new(Point3::new(0.0, N, 0.0), Vector3::new(0.0, -1.0, 0.0));
|
||||||
|
|
||||||
|
assert_eq!(plane.intersect(ray), Some(N));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn plane_getcolor() {
|
||||||
|
const N: f32 = 5.0;
|
||||||
|
let plane = Plane::xz(|x, y| Color::new(x, y, 0.0));
|
||||||
|
|
||||||
|
let point = Point3::new(5.0, 7.0, 6.0);
|
||||||
|
|
||||||
|
assert_eq!(plane.getcolor(point), Color::new(5.0, 6.0, 0.0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,13 @@ use na::*;
|
||||||
use na::geometry::Point3;
|
use na::geometry::Point3;
|
||||||
|
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
use super::base::*;
|
use super::Surface;
|
||||||
|
|
||||||
pub struct Sphere {
|
pub struct Sphere {
|
||||||
pub center: Point3<f32>,
|
pub center: Point3<f32>,
|
||||||
pub radius: f32,
|
pub radius: f32,
|
||||||
|
|
||||||
pub texture: Box<dyn Fn(f32, f32) -> Color>
|
texture: Box<dyn Fn(f32, f32) -> Color>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sphere {
|
impl Sphere {
|
||||||
|
@ -54,8 +54,8 @@ impl Surface for Sphere {
|
||||||
|
|
||||||
if t0 > t1 { std::mem::swap(&mut t0, &mut t1); }
|
if t0 > t1 { std::mem::swap(&mut t0, &mut t1); }
|
||||||
|
|
||||||
if t0 > 0.0 { Some(t0) }
|
if t0 >= 0.0 { Some(t0) }
|
||||||
else if t1 > 0.0 { Some(t1) }
|
else if t1 >= 0.0 { Some(t1) }
|
||||||
else { None }
|
else { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ impl Ray {
|
||||||
pub fn project(&self, t: f32) -> Point3<f32> { self.origin + t * self.direction.into_inner() }
|
pub fn project(&self, t: f32) -> Point3<f32> { self.origin + t * self.direction.into_inner() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub struct Color {
|
pub struct Color {
|
||||||
pub red: f32,
|
pub red: f32,
|
||||||
pub green: f32,
|
pub green: f32,
|
||||||
|
|
Loading…
Reference in a new issue