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<()> {
|
||||
|
||||
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![
|
||||
Object::Sphere(Sphere::new_solid(0.0,0.0,-5.0,2.0, Color::white())),
|
||||
Object::Sphere(Sphere::new_solid(-3.0,0.0,-8.0,2.5, Color::white()))
|
||||
Object::new(Sphere::new(0.0,0.0,-3.0,2.0, |x, y| Color::new(x, 0.0, y * 2.0)))
|
||||
];
|
||||
|
||||
render(&camera, &scene, "out.ppm")
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
mod base; pub use base::*;
|
||||
mod sphere; pub use sphere::*;
|
||||
mod plane; pub use plane::*;
|
||||
mod triangle; pub use triangle::*;
|
||||
|
@ -7,28 +8,18 @@ use na::*;
|
|||
|
||||
use crate::types::*;
|
||||
|
||||
pub enum Object {
|
||||
Sphere(Sphere)
|
||||
pub struct Object {
|
||||
pub surface: Box<dyn Surface>
|
||||
}
|
||||
|
||||
impl Object {
|
||||
pub fn intersect(&self, ray: Ray) -> Option<f32> {
|
||||
match *self {
|
||||
Object::Sphere(ref sphere) => sphere.intersect(ray)
|
||||
}
|
||||
pub fn new<S: 'static + Surface>(surface: S) -> Self {
|
||||
Object { surface: Box::new(surface) }
|
||||
}
|
||||
|
||||
pub fn getcolor(&self, point: Point3<f32>) -> Color {
|
||||
match *self {
|
||||
Object::Sphere(ref sphere) => sphere.getcolor(point)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn normal(&self, point: Point3<f32>) -> Unit<Vector3<f32>> {
|
||||
match *self {
|
||||
Object::Sphere(ref sphere) => sphere.normal(point)
|
||||
}
|
||||
}
|
||||
pub fn intersect(&self, ray: Ray) -> Option<f32> { self.surface.intersect(ray) }
|
||||
pub fn normal(&self, point: Point3<f32>) -> Unit<Vector3<f32>> { self.surface.normal(point) }
|
||||
pub fn getcolor(&self, point: Point3<f32>) -> Color { self.surface.getcolor(point) }
|
||||
}
|
||||
|
||||
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 crate::types::*;
|
||||
use super::base::*;
|
||||
|
||||
pub struct Plane {
|
||||
pub center: Point3<f32>,
|
||||
|
@ -25,8 +26,10 @@ impl Plane {
|
|||
|
||||
pub fn new_solid(center: Point3<f32>, normal: Vector3<f32>, color: Color) -> Self
|
||||
{ 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);
|
||||
if d < 1e-6 { return None; }
|
||||
|
@ -37,9 +40,9 @@ impl Plane {
|
|||
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!()
|
||||
}
|
||||
|
||||
pub fn normal(&self, point: Point3<f32>) -> Unit<Vector3<f32>> { self.normal }
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use na::*;
|
|||
use na::geometry::Point3;
|
||||
|
||||
use crate::types::*;
|
||||
use super::base::*;
|
||||
|
||||
pub struct Sphere {
|
||||
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
|
||||
{ Sphere::new(x, y, z, radius, move |_, _| color) }
|
||||
}
|
||||
|
||||
// Determines if a ray intersects the circle.
|
||||
// If so, returns the distance to the intersection point.
|
||||
pub fn intersect(&self, ray: Ray) -> Option<f32> {
|
||||
impl Surface for Sphere {
|
||||
fn intersect(&self, ray: Ray) -> Option<f32> {
|
||||
fn solve_quadratic(a: f32, b: f32, c: f32) -> Option<(f32, f32)> {
|
||||
let discr = b * b - 4.0 * a * c;
|
||||
|
||||
|
@ -58,7 +59,11 @@ impl Sphere {
|
|||
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);
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
pub fn normal(&self, point: Point3<f32>) -> Unit<Vector3<f32>> {
|
||||
Unit::new_normalize(point - self.center)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue