//! Defines the DifferentialGeometry type which is used to pass information
//! about the hit piece of geometry back from the intersection to the shading

use linalg::{Point, Normal};
use geometry::{Geometry, Instance};

/// Stores information about a hit piece of geometry of some object in the scene
#[deriving(Copy)]
pub struct DifferentialGeometry<'a, 'b> {
    /// The hit point 
    pub p: Point,
    /// The shading normal
    pub n: Normal,
    /// The geometry normal
    pub ng: Normal,
    /// The geometry that was hit
    pub geom: &'a (Geometry + 'a),
    /// The instance of geometry that was hit
    pub instance: Option<&'b Instance<'b>>,
}

impl<'a, 'b> DifferentialGeometry<'a, 'b> {
    /// Initialize the differential geometry with 0 values for all fields
    /// and None for the hit geometry
    pub fn new(p: &Point, n: &Normal, ng: &Normal, geom: &'a (Geometry + 'a),
               instance: Option<&'b Instance<'b>>) -> DifferentialGeometry<'a, 'b> {
        DifferentialGeometry { p: *p, n: *n, ng: *ng, geom: geom, instance: instance }
    }
}


//! Defines the DifferentialGeometry type which is used to pass information
//! about the hit piece of geometry back from the intersection to the shading

use linalg::{Point, Normal};
use geometry::{Geometry, Instance};

/// Stores information about a hit piece of geometry of some object in the scene
#[deriving(Copy)]
pub struct DifferentialGeometry<'a, 'b> {
    /// The hit point 
    pub p: Point,
    /// The shading normal
    pub n: Normal,
    /// The geometry normal
    pub ng: Normal,
    /// The geometry that was hit
    pub geom: &'a (Geometry + 'static),
    /// The instance of geometry that was hit
    pub instance: Option<&'b Instance<'b>>,
}

impl<'a, 'b> DifferentialGeometry<'a, 'b> {
    /// Initialize the differential geometry with 0 values for all fields
    /// and None for the hit geometry
    pub fn new(p: &Point, n: &Normal, ng: &Normal, geom: &'a (Geometry + 'static),
               instance: Option<&'b Instance<'b>>) -> DifferentialGeometry<'a, 'b> {
        DifferentialGeometry { p: *p, n: *n, ng: *ng, geom: geom, instance: instance }
    }
}


Use 'static lifetime bound to require that geom is a real struct
Use 'static lifetime bound to require that geom is a real struct

This bound requires that the underlying object implementing the trait
is a real struct, not a reference or etc. See http://stackoverflow.com/questions/26212397/rust-lang-references-to-traits-in-structs/26213294#26213294 for some more info
