library: use Intersected as a super trait
This commit is contained in:
parent
3039607e4f
commit
998838a6fc
|
@ -1,7 +1,7 @@
|
|||
//! Logic for the scene objects
|
||||
|
||||
use crate::material::MaterialEnum;
|
||||
use crate::shape::{Shape, ShapeEnum};
|
||||
use crate::shape::ShapeEnum;
|
||||
use crate::texture::TextureEnum;
|
||||
use crate::Point;
|
||||
use beevee::{
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use super::triangle::Triangle;
|
||||
use super::Shape;
|
||||
use crate::{Point, Point2D, Vector};
|
||||
use beevee::aabb::AABB;
|
||||
use beevee::aabb::{Bounded, AABB};
|
||||
use beevee::bvh::Intersected;
|
||||
use beevee::ray::Ray;
|
||||
use nalgebra::Unit;
|
||||
use serde::Deserialize;
|
||||
|
@ -52,10 +53,6 @@ impl InterpolatedTriangle {
|
|||
}
|
||||
|
||||
impl Shape for InterpolatedTriangle {
|
||||
fn intersect(&self, ray: &Ray) -> Option<f32> {
|
||||
self.tri.intersect(ray)
|
||||
}
|
||||
|
||||
fn normal(&self, point: &Point) -> Unit<Vector> {
|
||||
let (u, v) = {
|
||||
let c = self.tri.barycentric(point);
|
||||
|
@ -70,7 +67,9 @@ impl Shape for InterpolatedTriangle {
|
|||
fn project_texel(&self, point: &Point) -> Point2D {
|
||||
self.tri.project_texel(point)
|
||||
}
|
||||
}
|
||||
|
||||
impl Bounded for InterpolatedTriangle {
|
||||
fn aabb(&self) -> AABB {
|
||||
self.tri.aabb()
|
||||
}
|
||||
|
@ -80,6 +79,12 @@ impl Shape for InterpolatedTriangle {
|
|||
}
|
||||
}
|
||||
|
||||
impl Intersected for InterpolatedTriangle {
|
||||
fn intersect(&self, ray: &Ray) -> Option<f32> {
|
||||
self.tri.intersect(ray)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
|
|
@ -21,35 +21,42 @@ pub enum ShapeEnum {
|
|||
InterpolatedTriangle,
|
||||
}
|
||||
|
||||
// FIXME: this has to be written by hand due to a limitation of `enum_dispatch` on super traits
|
||||
impl Bounded for ShapeEnum {
|
||||
fn aabb(&self) -> AABB {
|
||||
match self {
|
||||
ShapeEnum::Sphere(s) => s.aabb(),
|
||||
ShapeEnum::Triangle(s) => s.aabb(),
|
||||
ShapeEnum::InterpolatedTriangle(s) => s.aabb(),
|
||||
}
|
||||
}
|
||||
|
||||
fn centroid(&self) -> Point {
|
||||
match self {
|
||||
ShapeEnum::Sphere(s) => s.centroid(),
|
||||
ShapeEnum::Triangle(s) => s.centroid(),
|
||||
ShapeEnum::InterpolatedTriangle(s) => s.centroid(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Intersected for ShapeEnum {
|
||||
fn intersect(&self, ray: &Ray) -> Option<f32> {
|
||||
match self {
|
||||
ShapeEnum::Sphere(s) => s.intersect(ray),
|
||||
ShapeEnum::Triangle(s) => s.intersect(ray),
|
||||
ShapeEnum::InterpolatedTriangle(s) => s.intersect(ray),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represent an abstract shape inside the scene.
|
||||
#[enum_dispatch::enum_dispatch(ShapeEnum)]
|
||||
pub trait Shape: std::fmt::Debug {
|
||||
/// Return the distance at which the object intersects with the ray, or None if it does not.
|
||||
fn intersect(&self, ray: &Ray) -> Option<f32>;
|
||||
pub trait Shape: std::fmt::Debug + Intersected {
|
||||
/// Return the unit vector corresponding to the normal at this point of the shape.
|
||||
fn normal(&self, point: &Point) -> Unit<Vector>;
|
||||
/// Project the point from the shape's surface to its texel coordinates.
|
||||
fn project_texel(&self, point: &Point) -> Point2D;
|
||||
/// Enclose the `Shape` in an axi-aligned bounding-box.
|
||||
fn aabb(&self) -> AABB;
|
||||
/// Return the centroid of the shape.
|
||||
fn centroid(&self) -> Point;
|
||||
}
|
||||
|
||||
impl Bounded for dyn Shape {
|
||||
fn aabb(&self) -> AABB {
|
||||
self.aabb()
|
||||
}
|
||||
|
||||
fn centroid(&self) -> Point {
|
||||
self.centroid()
|
||||
}
|
||||
}
|
||||
|
||||
impl Intersected for dyn Shape {
|
||||
fn intersect(&self, ray: &Ray) -> Option<f32> {
|
||||
self.intersect(ray)
|
||||
}
|
||||
}
|
||||
|
||||
mod interpolated_triangle;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use super::Shape;
|
||||
use crate::{Point, Point2D, Vector};
|
||||
use beevee::aabb::AABB;
|
||||
use beevee::aabb::{Bounded, AABB};
|
||||
use beevee::bvh::Intersected;
|
||||
use beevee::ray::Ray;
|
||||
use nalgebra::Unit;
|
||||
use serde::Deserialize;
|
||||
|
@ -38,6 +39,38 @@ impl Sphere {
|
|||
}
|
||||
|
||||
impl Shape for Sphere {
|
||||
fn normal(&self, point: &Point) -> Unit<Vector> {
|
||||
let delt = if self.inverted {
|
||||
self.center - point
|
||||
} else {
|
||||
point - self.center
|
||||
};
|
||||
Unit::new_normalize(delt)
|
||||
}
|
||||
|
||||
fn project_texel(&self, point: &Point) -> Point2D {
|
||||
// Project the sphere on the XY-plane
|
||||
Point2D::new(
|
||||
0.5 + (point.x - self.center.x) / (2. * self.radius),
|
||||
0.5 + (point.y - self.center.y) / (2. * self.radius),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Bounded for Sphere {
|
||||
fn aabb(&self) -> AABB {
|
||||
let delt = Vector::new(self.radius, self.radius, self.radius);
|
||||
let min = self.center - delt;
|
||||
let max = self.center + delt;
|
||||
AABB::with_bounds(min, max)
|
||||
}
|
||||
|
||||
fn centroid(&self) -> Point {
|
||||
self.center
|
||||
}
|
||||
}
|
||||
|
||||
impl Intersected for Sphere {
|
||||
fn intersect(&self, ray: &Ray) -> Option<f32> {
|
||||
use std::mem;
|
||||
|
||||
|
@ -67,34 +100,6 @@ impl Shape for Sphere {
|
|||
Some(t_0)
|
||||
}
|
||||
}
|
||||
|
||||
fn normal(&self, point: &Point) -> Unit<Vector> {
|
||||
let delt = if self.inverted {
|
||||
self.center - point
|
||||
} else {
|
||||
point - self.center
|
||||
};
|
||||
Unit::new_normalize(delt)
|
||||
}
|
||||
|
||||
fn project_texel(&self, point: &Point) -> Point2D {
|
||||
// Project the sphere on the XY-plane
|
||||
Point2D::new(
|
||||
0.5 + (point.x - self.center.x) / (2. * self.radius),
|
||||
0.5 + (point.y - self.center.y) / (2. * self.radius),
|
||||
)
|
||||
}
|
||||
|
||||
fn aabb(&self) -> AABB {
|
||||
let delt = Vector::new(self.radius, self.radius, self.radius);
|
||||
let min = self.center - delt;
|
||||
let max = self.center + delt;
|
||||
AABB::with_bounds(min, max)
|
||||
}
|
||||
|
||||
fn centroid(&self) -> Point {
|
||||
self.center
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use super::Shape;
|
||||
use crate::{Point, Point2D, Vector};
|
||||
use beevee::aabb::AABB;
|
||||
use beevee::aabb::{Bounded, AABB};
|
||||
use beevee::bvh::Intersected;
|
||||
use beevee::ray::Ray;
|
||||
use nalgebra::Unit;
|
||||
use serde::{Deserialize, Deserializer};
|
||||
|
@ -58,6 +59,29 @@ impl Triangle {
|
|||
}
|
||||
|
||||
impl Shape for Triangle {
|
||||
fn normal(&self, _: &Point) -> Unit<Vector> {
|
||||
Unit::new_normalize(self.c0c1.cross(&self.c0c2))
|
||||
}
|
||||
|
||||
fn project_texel(&self, point: &Point) -> Point2D {
|
||||
self.barycentric(point)
|
||||
}
|
||||
}
|
||||
|
||||
impl Bounded for Triangle {
|
||||
fn aabb(&self) -> AABB {
|
||||
AABB::empty()
|
||||
.grow(&self.c0)
|
||||
.grow(&(self.c0 + self.c0c1))
|
||||
.grow(&(self.c0 + self.c0c2))
|
||||
}
|
||||
|
||||
fn centroid(&self) -> Point {
|
||||
self.c0 + (self.c0c1 + self.c0c2) / 2.
|
||||
}
|
||||
}
|
||||
|
||||
impl Intersected for Triangle {
|
||||
fn intersect(&self, ray: &Ray) -> Option<f32> {
|
||||
let pvec = ray.direction.cross(&self.c0c2);
|
||||
let det = self.c0c1.dot(&pvec);
|
||||
|
@ -88,25 +112,6 @@ impl Shape for Triangle {
|
|||
Some(t)
|
||||
}
|
||||
}
|
||||
|
||||
fn normal(&self, _: &Point) -> Unit<Vector> {
|
||||
Unit::new_normalize(self.c0c1.cross(&self.c0c2))
|
||||
}
|
||||
|
||||
fn project_texel(&self, point: &Point) -> Point2D {
|
||||
self.barycentric(point)
|
||||
}
|
||||
|
||||
fn aabb(&self) -> AABB {
|
||||
AABB::empty()
|
||||
.grow(&self.c0)
|
||||
.grow(&(self.c0 + self.c0c1))
|
||||
.grow(&(self.c0 + self.c0c2))
|
||||
}
|
||||
|
||||
fn centroid(&self) -> Point {
|
||||
self.c0 + (self.c0c1 + self.c0c2) / 2.
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
|
|
Loading…
Reference in a new issue