/***************************************************************************
*                                                                          *
*  Copyright (C) Golaem S.A.  All Rights Reserved.                         *
*                                                                          *
***************************************************************************/

#pragma once

#include "glmVector3.h"

namespace glm
{
/** 
* \brief A 3D Ray3.
* 
* \ingroup geometry3
* \author Golaem <dev@golaem.com>
*
* \param float Manipulated scalar type (\ref Expression, double, float...)
*/

class GLM_CORE_API Ray3
{
  public:
    GLM_CLASS_STAT_ID( glm::MemoryStatIds::GolaemShared)

    /** 
	* \brief Constructor.
	* \param source The source of the ray (default is null vector)
	* \param direction The direction of the ray (default is null vector)
	*/
    Ray3(const Vector3& source = Vector3::getNullVector(), const Vector3& direction = Vector3(1, 0, 0))
        : _source(source)
        , _direction(direction)
    {
        // this is REALLY costly when projecting a lot (specially since whole 3D update branch) insure this is already normalized
        //_direction.normalizeSelf();
        GLM_DEBUG_ASSERT(_direction.isNormalized(GLM_NORMALIZED_EPSILON_SQR));
    }

    /** 
	* \name Accessors.
	*/
    //@{
    const Vector3& getSource() const { return _source; }

    const Vector3& getDirection() const { return _direction; }
    //@}

    /** 
	* \brief Project a point on the ray.
	*
	* \param[in] point The given point.
	* \param[out] t The parameter for whom source + direction * t (ie value(t)) = the projected point.
	* \param[out] delta The vector between the given point and the projected point.
	*/
    void project(const Vector3& point, float& t, Vector3& delta) const
    {
        t = (point - _source) * _direction;
        delta = point - value(t);
    }
    /** 
	* \brief Returns the ray point pamaretrized by t.
	*
	* \param t The parameter
	* \return The point.
	*/
    Vector3 value(const float& t) const { return _source + _direction * t; }

  protected:
    /** 
	* \brief Source of the ray. 
	*/
    Vector3 _source;

    /** 
	* \brief Normalized vector representing the direction of the ray.
	*/
    Vector3 _direction;
};
}
