Add generic trait Surface
This commit is contained in:
parent
6a7a3c7774
commit
ff625f576f
|
@ -52,11 +52,10 @@ 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, 400, 400);
|
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 scene = vec![
|
let scene = vec![
|
||||||
Object::Sphere(Sphere::new_solid(0.0,0.0,-5.0,2.0, Color::white())),
|
Object::new(Sphere::new(0.0,0.0,-3.0,2.0, |x, y| Color::new(x, 0.0, y * 2.0)))
|
||||||
Object::Sphere(Sphere::new_solid(-3.0,0.0,-8.0,2.5, Color::white()))
|
|
||||||
];
|
];
|
||||||
|
|
||||||
render(&camera, &scene, "out.ppm")
|
render(&camera, &scene, "out.ppm")
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
|
|
||||||
|
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::*;
|
||||||
|
@ -7,28 +8,18 @@ use na::*;
|
||||||
|
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
|
||||||
pub enum Object {
|
pub struct Object {
|
||||||
Sphere(Sphere)
|
pub surface: Box<dyn Surface>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Object {
|
impl Object {
|
||||||
pub fn intersect(&self, ray: Ray) -> Option<f32> {
|
pub fn new<S: 'static + Surface>(surface: S) -> Self {
|
||||||
match *self {
|
Object { surface: Box::new(surface) }
|
||||||
Object::Sphere(ref sphere) => sphere.intersect(ray)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getcolor(&self, point: Point3<f32>) -> Color {
|
pub fn intersect(&self, ray: Ray) -> Option<f32> { self.surface.intersect(ray) }
|
||||||
match *self {
|
pub fn normal(&self, point: Point3<f32>) -> Unit<Vector3<f32>> { self.surface.normal(point) }
|
||||||
Object::Sphere(ref sphere) => sphere.getcolor(point)
|
pub fn getcolor(&self, point: Point3<f32>) -> Color { self.surface.getcolor(point) }
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn normal(&self, point: Point3<f32>) -> Unit<Vector3<f32>> {
|
|
||||||
match *self {
|
|
||||||
Object::Sphere(ref sphere) => sphere.normal(point)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Scene = Vec<Object>;
|
pub type Scene = Vec<Object>;
|
||||||
|
|
14
src/object/base.rs
Normal file
14
src/object/base.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
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,6 +4,7 @@ use na::*;
|
||||||
use na::geometry::Point3;
|
use na::geometry::Point3;
|
||||||
|
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
use super::base::*;
|
||||||
|
|
||||||
pub struct Plane {
|
pub struct Plane {
|
||||||
pub center: Point3<f32>,
|
pub center: Point3<f32>,
|
||||||
|
@ -25,8 +26,10 @@ impl Plane {
|
||||||
|
|
||||||
pub fn new_solid(center: Point3<f32>, normal: Vector3<f32>, color: Color) -> Self
|
pub fn new_solid(center: Point3<f32>, normal: Vector3<f32>, color: Color) -> Self
|
||||||
{ Plane::new(center, normal, move |_, _| color) }
|
{ Plane::new(center, normal, move |_, _| color) }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn intersect(&self, ray: Ray) -> Option<f32> {
|
impl Surface for Plane {
|
||||||
|
fn intersect(&self, ray: Ray) -> Option<f32> {
|
||||||
|
|
||||||
let d = self.normal.dot(&ray.direction);
|
let d = self.normal.dot(&ray.direction);
|
||||||
if d < 1e-6 { return None; }
|
if d < 1e-6 { return None; }
|
||||||
|
@ -37,9 +40,9 @@ impl Plane {
|
||||||
else { None }
|
else { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getcolor(&self, point: Point3<f32>) -> Color {
|
fn normal(&self, _point: Point3<f32>) -> Unit<Vector3<f32>> { self.normal }
|
||||||
|
|
||||||
|
fn getcolor(&self, point: Point3<f32>) -> Color {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn normal(&self, point: Point3<f32>) -> Unit<Vector3<f32>> { self.normal }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ use na::*;
|
||||||
use na::geometry::Point3;
|
use na::geometry::Point3;
|
||||||
|
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
use super::base::*;
|
||||||
|
|
||||||
pub struct Sphere {
|
pub struct Sphere {
|
||||||
pub center: Point3<f32>,
|
pub center: Point3<f32>,
|
||||||
|
@ -27,10 +28,10 @@ impl Sphere {
|
||||||
|
|
||||||
pub fn new_solid(x: f32, y: f32, z: f32, radius: f32, color: Color) -> Self
|
pub fn new_solid(x: f32, y: f32, z: f32, radius: f32, color: Color) -> Self
|
||||||
{ Sphere::new(x, y, z, radius, move |_, _| color) }
|
{ Sphere::new(x, y, z, radius, move |_, _| color) }
|
||||||
|
}
|
||||||
|
|
||||||
// Determines if a ray intersects the circle.
|
impl Surface for Sphere {
|
||||||
// If so, returns the distance to the intersection point.
|
fn intersect(&self, ray: Ray) -> Option<f32> {
|
||||||
pub fn intersect(&self, ray: Ray) -> Option<f32> {
|
|
||||||
fn solve_quadratic(a: f32, b: f32, c: f32) -> Option<(f32, f32)> {
|
fn solve_quadratic(a: f32, b: f32, c: f32) -> Option<(f32, f32)> {
|
||||||
let discr = b * b - 4.0 * a * c;
|
let discr = b * b - 4.0 * a * c;
|
||||||
|
|
||||||
|
@ -58,7 +59,11 @@ impl Sphere {
|
||||||
else { None }
|
else { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getcolor(&self, point: Point3<f32>) -> Color {
|
fn normal(&self, point: Point3<f32>) -> Unit<Vector3<f32>> {
|
||||||
|
Unit::new_normalize(point - self.center)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getcolor(&self, point: Point3<f32>) -> Color {
|
||||||
let normal = self.normal(point);
|
let normal = self.normal(point);
|
||||||
|
|
||||||
// In this particular case, the normal is simular to a point on a unit sphere
|
// In this particular case, the normal is simular to a point on a unit sphere
|
||||||
|
@ -71,8 +76,4 @@ impl Sphere {
|
||||||
|
|
||||||
(*self.texture)(x, y)
|
(*self.texture)(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn normal(&self, point: Point3<f32>) -> Unit<Vector3<f32>> {
|
|
||||||
Unit::new_normalize(point - self.center)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue