Refactor some method code
This commit is contained in:
parent
6ef2c65009
commit
0d3500ceb5
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -11,4 +11,4 @@ Cargo.lock
|
|||
**/*.rs.bk
|
||||
|
||||
# Debug output of program
|
||||
*.ppm
|
||||
*.ppm
|
||||
|
|
|
@ -36,15 +36,16 @@ 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,2.5), Vector3::new(0.0,0.0,-1.0), 1.0, 16.0 / 9.0, 2.0, 720);
|
||||
let camera = Camera::new(Point3::new(0.0,0.0,3.0), Vector3::new(0.0,0.0,-1.0), 1.0, 16.0 / 9.0, 2.0, 720);
|
||||
|
||||
let scene = Scene {
|
||||
objects: vec![
|
||||
Object::new(Sphere::new(0.0, 0.0, 0.0, 1.0, |a, b| Texture::new(0.0, a, b, 1.0)))
|
||||
Object::new(Sphere::new_solid(1.0, 0.2, 1.7, 0.2, Texture::new(1.0, 1.0, 1.0, 1.0))),
|
||||
Object::new(Sphere::new_solid(0.0, -1.0, 0.0, 1.0, Texture::new(1.0, 1.0, 1.0, 1.0)))
|
||||
],
|
||||
lights: vec![
|
||||
Box::new(PointLight::new(Point3::new(1.0, 0.7, 1.5), Color::white(), 3.0)),
|
||||
Box::new(PointLight::new(Point3::new(-1.0, -0.3, 0.4), Color::new(1.0, 0.0, 0.0), 4.0))
|
||||
Box::new(PointLight::new(Point3::new(1.5, 1.0, 2.5), Color::white(), 3.0)),
|
||||
Box::new(PointLight::new(Point3::new(1.0, -0.4, 1.5), Color::white(), 2.0))
|
||||
],
|
||||
background: Color::gray(0.5)
|
||||
};
|
||||
|
|
|
@ -3,7 +3,7 @@ mod sphere; pub use sphere::*;
|
|||
mod plane; pub use plane::*;
|
||||
mod triangle; pub use triangle::*;
|
||||
mod bound; pub use bound::*;
|
||||
mod pointlight; pub use pointlight::*;
|
||||
mod point_light; pub use point_light::*;
|
||||
|
||||
use crate::types::*;
|
||||
|
||||
|
@ -21,7 +21,7 @@ pub trait Surface {
|
|||
|
||||
// Takes in a point (assumed to be on the object's surface)
|
||||
// and returns the texture information on that point.
|
||||
fn gettexture(&self, point: Point3f) -> Texture;
|
||||
fn get_texture(&self, point: Point3f) -> Texture;
|
||||
|
||||
// Creates a bounding sphere around the object.
|
||||
fn bound(&self) -> Bound;
|
||||
|
@ -38,7 +38,7 @@ impl Object {
|
|||
let bound = surface.bound();
|
||||
Object {
|
||||
surface: Box::new(surface),
|
||||
bound: bound
|
||||
bound
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ impl Object {
|
|||
} else { None }
|
||||
}
|
||||
pub fn normal(&self, point: Point3f) -> Unit3f { self.surface.normal(point) }
|
||||
pub fn gettexture(&self, point: Point3f) -> Texture { self.surface.gettexture(point) }
|
||||
pub fn get_texture(&self, point: Point3f) -> Texture { self.surface.get_texture(point) }
|
||||
}
|
||||
|
||||
pub trait Light {
|
||||
|
@ -57,7 +57,7 @@ pub trait Light {
|
|||
fn check_shadow(&self, point: Point3f, objects: &Vec<Object>) -> bool;
|
||||
|
||||
// Compute color on a point.
|
||||
fn getcolor(&self, point: Point3f) -> Color;
|
||||
fn get_color(&self, point: Point3f) -> Color;
|
||||
|
||||
// Compute intensity on a point.
|
||||
fn intensity(&self, point: Point3f) -> f32;
|
||||
|
|
|
@ -24,7 +24,7 @@ impl Plane {
|
|||
where F: Fn(f32, f32) -> Texture
|
||||
{
|
||||
Plane {
|
||||
center: center,
|
||||
center,
|
||||
normal: Unit::new_normalize(x_axis.cross(&y_axis)),
|
||||
x_axis: x_axis,
|
||||
y_axis: y_axis,
|
||||
|
@ -77,7 +77,7 @@ impl Surface for Plane {
|
|||
|
||||
fn normal(&self, _point: Point3f) -> Unit3f { self.normal }
|
||||
|
||||
fn gettexture(&self, point: Point3f) -> Texture {
|
||||
fn get_texture(&self, point: Point3f) -> Texture {
|
||||
let rel_pos = point - self.center;
|
||||
let proj_point3 = rel_pos - (*self.normal * self.normal.dot(&rel_pos));
|
||||
|
||||
|
|
|
@ -14,11 +14,7 @@ pub struct PointLight {
|
|||
#[allow(dead_code)]
|
||||
impl PointLight {
|
||||
pub fn new(pos: Point3f, color: Color, intensity: f32) -> PointLight {
|
||||
PointLight {
|
||||
pos: pos,
|
||||
color: color,
|
||||
intensity: intensity
|
||||
}
|
||||
PointLight { pos, color, intensity }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,11 +22,11 @@ impl Light for PointLight {
|
|||
fn check_shadow(&self, point: Point3f, objects: &Vec<Object>) -> bool {
|
||||
let max_d = distance(&self.pos, &point);
|
||||
objects.iter()
|
||||
.filter_map(|obj| obj.intersect(Ray::from_points(self.pos, point)))
|
||||
.filter_map(|&obj| obj.intersect(Ray::from_points(self.pos, point)))
|
||||
.all(|d| d - max_d > -1e-3 )
|
||||
}
|
||||
|
||||
fn getcolor(&self, _point: Point3f) -> Color { self.color }
|
||||
fn get_color(&self, _point: Point3f) -> Color { self.color }
|
||||
|
||||
fn intensity(&self, _point: Point3f) -> f32 { self.intensity }
|
||||
|
||||
|
@ -44,7 +40,7 @@ mod tests {
|
|||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn pointlight_checkshadow() {
|
||||
fn point_light_check_shadow() {
|
||||
let light = PointLight::new(Point3::new(0.0, 1.0, 0.0), Color::white(), 1.0);
|
||||
let block = Object::new(Sphere::new_solid(0.0, 0.5, 0.0, 0.1, Texture::new(0.0, 0.0, 0.0, 0.0)));
|
||||
|
|
@ -23,8 +23,7 @@ impl Sphere {
|
|||
where F: Fn(f32, f32) -> Texture
|
||||
{
|
||||
Sphere {
|
||||
center: Point3::new(x, y, z),
|
||||
radius: radius,
|
||||
center: Point3::new(x, y, z), radius,
|
||||
texture: Box::new(texture)
|
||||
}
|
||||
}
|
||||
|
@ -66,10 +65,10 @@ impl Surface for Sphere {
|
|||
Unit::new_normalize(point - self.center)
|
||||
}
|
||||
|
||||
fn gettexture(&self, point: Point3f) -> Texture {
|
||||
fn get_texture(&self, point: Point3f) -> Texture {
|
||||
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 similar to a point on a unit sphere
|
||||
// centred around the origin. We can thus use the normal coordinates to compute
|
||||
// the spherical coordinates of the point.
|
||||
let x = 0.5 + normal.z.atan2(normal.x) / (2.0 * PI);
|
||||
|
@ -78,5 +77,5 @@ impl Surface for Sphere {
|
|||
(*self.texture)(x, y)
|
||||
}
|
||||
|
||||
fn bound(&self) -> Bound { Bound::bypass() }
|
||||
fn bound(&self) -> Bound { Bound { center: self.center, radius: self.radius, bypass: false } }
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ pub struct Triangle {
|
|||
|
||||
pub struct TriangleMesh {
|
||||
pub vertices: Vec<Point3f>,
|
||||
pub tris: Vec<Triangle>
|
||||
pub triangles: Vec<Triangle>
|
||||
}
|
||||
|
||||
fn tri_area(a: &Point3f, b: &Point3f, c: &Point3f) -> f32 {
|
||||
|
@ -78,7 +78,7 @@ impl Triangle {
|
|||
self.intersect_(vertices, ray).map(|(t, u, v)| distance(&ray.origin, &self.from_bary(vertices, t, u, v)))
|
||||
}
|
||||
|
||||
fn gettexture(&self, vertices: &Vec<Point3f>, point: Point3f) -> Texture {
|
||||
fn get_texture(&self, vertices: &Vec<Point3f>, point: Point3f) -> Texture {
|
||||
let (t, u, v) = self.to_bary(vertices, point);
|
||||
(*self.texture)(t, u, v)
|
||||
}
|
||||
|
@ -89,32 +89,27 @@ impl TriangleMesh {
|
|||
pub fn new(vertices: Vec<Point3f>, tris: Vec<(usize, usize, usize, Box<dyn Fn(f32, f32, f32) -> Texture>)>) -> Self {
|
||||
let triangles = tris.into_iter()
|
||||
.map(|(v1, v2, v3, f)| Triangle {
|
||||
v1: v1,
|
||||
v2: v2,
|
||||
v3: v3,
|
||||
v1, v2, v3,
|
||||
normal: Unit::new_normalize((&vertices[v2] - &vertices[v1]).cross(&(&vertices[v3] - &vertices[v1]))),
|
||||
area: tri_area(&vertices[v1], &vertices[v2], &vertices[v3]),
|
||||
texture: f
|
||||
}).collect();
|
||||
TriangleMesh {
|
||||
vertices: vertices,
|
||||
tris: triangles
|
||||
vertices, triangles
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_solid(vertices: Vec<Point3f>, tris: Vec<(usize, usize, usize)>, texture: Texture) -> Self {
|
||||
let triangles = tris.into_iter()
|
||||
.map(|(v1, v2, v3)| Triangle {
|
||||
v1: v1,
|
||||
v2: v2,
|
||||
v3: v3,
|
||||
v1, v2, v3,
|
||||
normal: Unit::new_normalize((&vertices[v2] - &vertices[v1]).cross(&(&vertices[v3] - &vertices[v1]))),
|
||||
area: tri_area(&vertices[v1], &vertices[v2], &vertices[v3]),
|
||||
texture: Box::new(move |_, _, _| texture)
|
||||
}).collect();
|
||||
TriangleMesh {
|
||||
vertices: vertices,
|
||||
tris: triangles
|
||||
vertices,
|
||||
triangles
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,7 +122,7 @@ impl TriangleMesh {
|
|||
|
||||
|
||||
fn closest_tri(&self, point: Point3f) -> &Triangle {
|
||||
self.tris.iter()
|
||||
self.triangles.iter()
|
||||
.map(move |tri| {
|
||||
|
||||
let rel_pos = point - tri.vertex1(&self.vertices);
|
||||
|
@ -150,7 +145,7 @@ impl TriangleMesh {
|
|||
|
||||
impl Surface for TriangleMesh {
|
||||
fn intersect(&self, ray: Ray) -> Option<f32> {
|
||||
self.tris.iter()
|
||||
self.triangles.iter()
|
||||
.filter_map(|tri| tri.intersect(&self.vertices, ray))
|
||||
.min_by(|a, b| a.partial_cmp(&b).unwrap_or(Ordering::Equal))
|
||||
}
|
||||
|
@ -159,8 +154,8 @@ impl Surface for TriangleMesh {
|
|||
self.closest_tri(point).normal
|
||||
}
|
||||
|
||||
fn gettexture(&self, point: Point3f) -> Texture {
|
||||
self.closest_tri(point).gettexture(&self.vertices, point)
|
||||
fn get_texture(&self, point: Point3f) -> Texture {
|
||||
self.closest_tri(point).get_texture(&self.vertices, point)
|
||||
}
|
||||
|
||||
// Uses Welzl's algorithm to solve the bounding sphere problem
|
||||
|
@ -238,6 +233,6 @@ impl Surface for TriangleMesh {
|
|||
|
||||
let (center, radius) = smallest_sphere(points, Vec::new());
|
||||
|
||||
Bound { center: center, radius: radius + 1e-3, bypass: false }
|
||||
Bound { center, radius: radius + 1e-3, bypass: false }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,9 @@ use crate::object::*;
|
|||
|
||||
fn trace(ray: Ray, objects: &Vec<Object>) -> Option<(&Object, f32)> {
|
||||
objects.iter()
|
||||
.filter_map(|obj| obj.intersect(ray)
|
||||
.filter_map(|&obj| obj.intersect(ray)
|
||||
.map(|x| (obj, x)))
|
||||
.min_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(Ordering::Equal))
|
||||
.min_by(|&a, &b| a.1.partial_cmp(&b.1).unwrap_or(Ordering::Equal))
|
||||
}
|
||||
|
||||
fn light_point(objects: &Vec<Object>, obj: &Object, point: Point3f, light: &dyn Light) -> Color {
|
||||
|
@ -34,7 +34,7 @@ pub fn cast_ray(ray: Ray, scene: &Scene) -> Color {
|
|||
let surface_color = obj.gettexture(point).color;
|
||||
|
||||
scene.lights.iter()
|
||||
.map(|light| light_point(&scene.objects, obj, point, &**light))
|
||||
.map(|&light| light_point(&scene.objects, obj, point, &*light))
|
||||
.fold(Color::black(), |acc, c| acc + c) * surface_color
|
||||
}
|
||||
else { scene.background }
|
||||
|
|
|
@ -17,10 +17,7 @@ pub struct Ray {
|
|||
|
||||
impl Ray {
|
||||
pub fn from_parts(origin: Point3f, direction: Unit3f) -> Self {
|
||||
Ray {
|
||||
origin: origin,
|
||||
direction: direction
|
||||
}
|
||||
Ray { origin, direction }
|
||||
}
|
||||
pub fn new(origin: Point3f, direction: Vector3f) -> Self { Ray::from_parts(origin, Unit::new_normalize(direction)) }
|
||||
pub fn from_points(origin: Point3f, points_to: Point3f) -> Self { Ray::new(origin, points_to - origin) }
|
||||
|
@ -109,7 +106,7 @@ impl Texture {
|
|||
pub fn new(red: f32, green: f32, blue: f32, albedo: f32) -> Self {
|
||||
Texture {
|
||||
color: Color::new(red, green, blue),
|
||||
albedo: albedo
|
||||
albedo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue