diff --git a/src/lib.rs b/src/lib.rs index 81f851a..4850fd9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ pub mod image; pub mod integrators; pub mod materials; pub mod mesh; +/// Core raycasting and geometry primitives pub mod raycasting; pub mod realtype; pub mod sampler; diff --git a/src/raycasting/mod.rs b/src/raycasting/mod.rs index 1ba9875..7c6bb91 100644 --- a/src/raycasting/mod.rs +++ b/src/raycasting/mod.rs @@ -20,13 +20,23 @@ pub use axis_aligned_bounding_box::BoundingBox; pub mod bounding_volume_hierarchy; pub use bounding_volume_hierarchy::BoundingVolumeHierarchy; +/// A ray, consisting or a start point and direction +/// +/// This is the basic ray struct used to define things like a line-of-sight +/// going out from the camera of a reflection from a surface. #[derive(Clone, Debug)] pub struct Ray { + /// The start point of the ray pub origin: Point3, + + /// The direction the ray goes in. + /// + /// This vector should always be kept normalized pub direction: Vector3, } impl Ray { + /// Create a new ray pub fn new(origin: Point3, direction: Vector3) -> Ray { Ray { origin, @@ -34,44 +44,91 @@ impl Ray { } } + /// Return the point on the ray that is `t` units from the start pub fn point_at(&self, t: T) -> Point3 { self.origin + self.direction * t } + /// Create a new ray by moving the original ray along it's direction by `amount` + /// + /// `amount` is normally a very small number. This function is useful for ensuring + /// that rounding-errors don;t cause a reflection ray doesn't intersect with the point + /// it's reflected from. pub fn bias(&self, amount: T) -> Ray { Ray::new(self.origin + self.direction * amount, self.direction) } } +/// Information about a ray-primitive intersection. +/// +/// This struct is returned by [intersect()](Intersect::intersect) and contatins all the +/// information needed to evaluate the rendering function for that intersection. #[derive(Debug)] pub struct IntersectionInfo { + /// The distance between the ray origin and the intersection point pub distance: T, + + /// The intersection point pub location: Point3, + + /// The surface normal at the intersection point pub normal: Vector3, + + /// The surface tangent at the intersection point + /// + /// Which surface tangent direction returned is dependent on the [Primitive](Primitive) + /// but should generally be smooth over any given surface pub tangent: Vector3, + + /// Another surface tangent, perpendicular to `tangent` + /// + /// The cross product or `normal` and `tangent` pub cotangent: Vector3, + + /// The direction from the intersection point back towards the ray + /// + /// Equal to `-ray.direction` pub retro: Vector3, + + /// The [Material](crate::materials::Material) which describes the optical + /// properties of the intersected surface pub material: Arc>, } +/// A geometric object that has a [Material](crate::materials::Material) and can be +/// intersected with a [Ray](Ray) pub trait Intersect: Send + Sync { /// Test if the ray intersects the object, and return information about the object and intersection. fn intersect<'a>(&'a self, ray: &Ray) -> Option>; } +/// A geometric object that can be intersected with a ray +/// +/// This is useful for objects that don't have materials (such as [BoundingBox](BoundingBox)) +/// and as a (possibly) faster alternative to [Intersect](Intersect) when only a simple +/// intersection test is needed. pub trait IntersectP: Send + Sync { /// Test if the ray intersects the object, without calculating any extra information. fn intersect(&self, ray: &Ray) -> bool; } +/// Any geometric object for which a [BoundingBox](BoundingBox) can be calculated pub trait HasBoundingBox: Send + Sync { + /// The axis-aligned bounding box of the object + /// + /// The object must fit entirely inside this box. fn bounding_box(&self) -> BoundingBox; } +/// Any geometric object which can have an affine transformation applied to it +/// +/// Used for moving, rotating or scaling primitives pub trait Transform: Send + Sync { + /// Create a new object by applying the transformation to this object. fn transform(&mut self, transformation: &Affine3) -> &Self; } +/// A basic geometric primitive such as a sphere or a triangle pub trait Primitive: Intersect + HasBoundingBox {} #[cfg(test)]