///////////////////////////////////////////////////////////////////////////////////////////////////
// OpenGL Mathematics Copyright (c) 2005 - 2008 G-Truc Creation (www.g-truc.net)
///////////////////////////////////////////////////////////////////////////////////////////////////
// Created : 2005-12-21
// Updated : 2006-11-13
// Licence : This source is under MIT License
// File    : glm/gtx/transform2.h
///////////////////////////////////////////////////////////////////////////////////////////////////
// Dependency:
// - GLM core
// - GLM_GTX_transform
///////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef glm_gtx_transform2
#define glm_gtx_transform2

// Dependency:
#include "../../glm.h"
#include "../gtx/transform.h"

namespace glm
{
	namespace test{
		void main_ext_gtx_transform2();
	}//namespace test

    template <typename T> detail::tmat3x3<T> shearX2DGTX(const detail::tmat3x3<T> & m, T y);
    template <typename T> detail::tmat3x3<T> shearY2DGTX(const detail::tmat3x3<T> & m, T x);
    template <typename T> detail::tmat4x4<T> shearX3DGTX(const detail::tmat4x4<T> & m, T y, T z);
    template <typename T> detail::tmat4x4<T> shearY3DGTX(const detail::tmat4x4<T> & m, T x, T z);
    template <typename T> detail::tmat4x4<T> shearZ3DGTX(const detail::tmat4x4<T> & m, T x, T y);
    //template <typename T> detail::tmat4x4<T> shearGTX(const detail::tmat4x4<T> & m, shearPlane, planePoint, angle)
    // Identity + tan(angle) * cross(Normal, OnPlaneVector)     0
    // - dot(PointOnPlane, normal) * OnPlaneVector              1

    // Reflect functions seem to don't work
    template <typename T> detail::tmat3x3<T> reflect2DGTX(const detail::tmat3x3<T> & m, const detail::tvec3<T>& normal);
    template <typename T> detail::tmat4x4<T> reflect3DGTX(const detail::tmat4x4<T> & m, const detail::tvec3<T>& normal);
    template <typename T> detail::tmat3x3<T> proj2DGTX(const detail::tmat3x3<T> & m, const detail::tvec3<T>& normal);
    template <typename T> detail::tmat4x4<T> proj3DGTX(const detail::tmat4x4<T> & m, const detail::tvec3<T>& normal);
    template <typename T> detail::tmat4x4<T> lookAtGTX(const detail::tvec3<T>& eye, const detail::tvec3<T>& center, const detail::tvec3<T>& up);

	template <typename T> detail::tmat4x4<T> scaleBiasGTX(T scale, T bias);
	template <typename T> detail::tmat4x4<T> scaleBiasGTX(const detail::tmat4x4<T> & m, T scale, T bias);

    namespace gtx
    {
		//! GLM_GTX_transform2 extension: Add extra transformation matrices
        namespace transform2
        {
            template <typename T> inline detail::tmat3x3<T> shearX2D(const detail::tmat3x3<T> & m, T y){return shearX2DGTX(m, y);}			//!< \brief Transforms a matrix with a shearing on X axis (from GLM_GTX_transform2 extension)
            template <typename T> inline detail::tmat3x3<T> shearY2D(const detail::tmat3x3<T> & m, T x){return shearY2DGTX(m, x);}			//!< \brief Transforms a matrix with a shearing on Y axis (from GLM_GTX_transform2 extension)
            template <typename T> inline detail::tmat4x4<T> shearX3D(const detail::tmat4x4<T> & m, T y, T z){return shearX3DGTX(m, y, z);}	//!< \brief Transforms a matrix with a shearing on X axis (from GLM_GTX_transform2 extension)
            template <typename T> inline detail::tmat4x4<T> shearY3D(const detail::tmat4x4<T> & m, T x, T z){return shearY3DGTX(m, x, z);}	//!< \brief Transforms a matrix with a shearing on Y axis (from GLM_GTX_transform2 extension)
            template <typename T> inline detail::tmat4x4<T> shearZ3D(const detail::tmat4x4<T> & m, T x, T y){return shearZ3DGTX(m, x, y);}	//!< \brief Transforms a matrix with a shearing on Z axis (from GLM_GTX_transform2 extension)
            //template <typename T> inline detail::tmat4x4<T> shear(const detail::tmat4x4<T> & m, shearPlane, planePoint, angle)
            // Identity + tan(angle) * cross(Normal, OnPlaneVector)     0
            // - dot(PointOnPlane, normal) * OnPlaneVector              1

            // Reflect functions seem to don't work
            template <typename T> inline detail::tmat3x3<T> reflect2D(const detail::tmat3x3<T> & m, const detail::tvec3<T>& normal){return reflect2DGTX(m, normal);}									//!< \brief Build a reflection matrix (from GLM_GTX_transform2 extension)
            template <typename T> inline detail::tmat4x4<T> reflect3D(const detail::tmat4x4<T> & m, const detail::tvec3<T>& normal){return reflect3DGTX(m, normal);}									//!< \brief Build a reflection matrix (from GLM_GTX_transform2 extension)
            template <typename T> inline detail::tmat3x3<T> proj2D(const detail::tmat3x3<T> & m, const detail::tvec3<T>& normal){return proj2DGTX(m, normal);}										//!< \brief Build planar projection matrix along normal axis (from GLM_GTX_transform2 extension)
            template <typename T> inline detail::tmat4x4<T> proj3D(const detail::tmat4x4<T> & m, const detail::tvec3<T>& normal){return proj3DGTX(m, normal);}										//!< \brief Build planar projection matrix along normal axis (from GLM_GTX_transform2 extension)
            template <typename T> inline detail::tmat4x4<T> lookAt(const detail::tvec3<T>& eye, const detail::tvec3<T>& center, const detail::tvec3<T>& up){return lookAtGTX(eye, center, up);}	//!< \brief Build a look at view matrix (from GLM_GTX_transform2 extension)

			template <typename T> inline detail::tmat4x4<T> scaleBias(T scale, T bias){return scaleBiasGTX(scale, bias);}																			//!< \brief Build a scale bias matrix (from GLM_GTX_transform2 extension)
			template <typename T> inline detail::tmat4x4<T> scaleBias(const detail::tmat4x4<T>& m, T scale, T bias){return scaleBiasGTX(m, scale, bias);}												//!< \brief Build a scale bias matrix (from GLM_GTX_transform2 extension)

        }
    }
}

#define GLM_GTX_transform2 namespace gtx::transform2

#include "transform2.inl"

#endif//glm_gtx_transform2
