use crate::{
rand_utils, Axis, efloat::{self, EFloat},
Point, Normal, Direction, Float,
Vec3, Vec2, Transform, Mat3
};
use crate::tracer::{
hit::Hit, material::Material,
onb::Onb, ray::Ray
};
use std::sync::Arc;
pub use aabb::AaBoundingBox;
pub use cone::Cone;
pub use cube::Cube;
pub use cylinder::Cylinder;
pub use disk::Disk;
pub use instance::{Instance, Instanceable};
pub use kdtree::{KdTree, Mesh};
pub use medium::Medium;
pub use plane::Plane;
pub use rectangle::Rectangle;
pub use sphere::Sphere;
pub use triangle::Triangle;
pub use triangle_mesh::{TriangleMesh, Face};
mod aabb;
mod cone;
mod cube;
mod cylinder;
mod disk;
mod instance;
mod kdtree;
mod medium;
mod plane;
mod rectangle;
mod sphere;
mod triangle;
mod triangle_mesh;
pub trait Object: Sync {
fn hit(&self, r: &Ray, t_min: Float, t_max: Float) -> Option<Hit>;
}
pub trait Bounded: Object {
fn bounding_box(&self) -> AaBoundingBox;
}
pub trait Sampleable: Object {
fn area(&self) -> Float;
fn sample_leaving(&self, rand_sq0: Vec2, rand_sq1: Vec2) -> (Ray, Hit) {
let ho = self.sample_on(rand_sq0);
let ns = ho.ns;
let xo = ho.p;
let uvw = Onb::new(ns);
let wi_local = rand_utils::square_to_cos_hemisphere(rand_sq1);
let wi = uvw.to_world(wi_local);
(Ray::new(xo, wi), ho)
}
fn sample_leaving_pdf(&self, r: &Ray, ng: Normal) -> (Float, Float) {
let pdf_origin = 1.0 / self.area();
let wi = r.dir;
let cos_theta = ng.dot(wi);
let pdf_dir = cos_theta / crate::PI;
(pdf_origin, pdf_dir)
}
fn sample_on(&self, rand_sq: Vec2) -> Hit;
fn sample_towards(&self, xo: Point, rand_sq: Vec2) -> Direction {
let xi = self.sample_on(rand_sq).p;
xi - xo
}
fn sample_towards_pdf(&self, ri: &Ray) -> (Float, Option<Hit>) {
match self.hit(ri, 0.0, crate::INF) {
None => (0.0, None),
Some(hi) => {
let p = 1.0 / self.area();
(p, Some(hi))
}
}
}
}