From 490cfbea3a9ede1c5fd16348377bee6687ef85bf Mon Sep 17 00:00:00 2001 From: Aaron Cooper Date: Sat, 21 Feb 2015 14:39:45 -0500 Subject: [PATCH] Added left handed functions for perspective, perspectiveFov, and lookAt. --- glm/gtc/matrix_transform.hpp | 97 +++++++++++++++++++++++++- glm/gtc/matrix_transform.inl | 127 ++++++++++++++++++++++++++++++++++- 2 files changed, 220 insertions(+), 4 deletions(-) diff --git a/glm/gtc/matrix_transform.hpp b/glm/gtc/matrix_transform.hpp index e2fc72a9..e70e6a81 100644 --- a/glm/gtc/matrix_transform.hpp +++ b/glm/gtc/matrix_transform.hpp @@ -171,7 +171,7 @@ namespace glm T near, T far); - /// Creates a matrix for a symetric perspective-view frustum. + /// Creates a matrix for a symetric perspective-view frustum based on the default handedness. /// /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). @@ -186,7 +186,38 @@ namespace glm T near, T far); - /// Builds a perspective projection matrix based on a field of view. + + /// Creates a matrix for a right handed, symetric perspective-view frustum. + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double. + /// @see gtc_matrix_transform + template + GLM_FUNC_DECL tmat4x4 perspectiveRH( + T fovy, + T aspect, + T near, + T far); + + /// Creates a matrix for a left handed, symetric perspective-view frustum. + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double. + /// @see gtc_matrix_transform + template + GLM_FUNC_DECL tmat4x4 perspectiveLH( + T fovy, + T aspect, + T near, + T far); + + /// Builds a perspective projection matrix based on a field of view and the default handedness. /// /// @param fov Expressed in radians. /// @param width @@ -203,6 +234,40 @@ namespace glm T near, T far); + /// Builds a right handed perspective projection matrix based on a field of view. + /// + /// @param fov Expressed in radians. + /// @param width + /// @param height + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double. + /// @see gtc_matrix_transform + template + GLM_FUNC_DECL tmat4x4 perspectiveFovRH( + T fov, + T width, + T height, + T near, + T far); + + /// Builds a left handed perspective projection matrix based on a field of view. + /// + /// @param fov Expressed in radians. + /// @param width + /// @param height + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double. + /// @see gtc_matrix_transform + template + GLM_FUNC_DECL tmat4x4 perspectiveFovLH( + T fov, + T width, + T height, + T near, + T far); + /// Creates a matrix for a symmetric perspective-view frustum with far plane at infinite. /// /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. @@ -285,7 +350,7 @@ namespace glm tvec2 const & delta, tvec4 const & viewport); - /// Build a look at view matrix. + /// Build a look at view matrix based on the default handedness. /// /// @param eye Position of the camera /// @param center Position where the camera is looking at @@ -298,6 +363,32 @@ namespace glm tvec3 const & center, tvec3 const & up); + /// Build a right handed look at view matrix. + /// + /// @param eye Position of the camera + /// @param center Position where the camera is looking at + /// @param up Normalized up vector, how the camera is oriented. Typically (0, 0, 1) + /// @see gtc_matrix_transform + /// @see - frustum(T const & left, T const & right, T const & bottom, T const & top, T const & nearVal, T const & farVal) frustum(T const & left, T const & right, T const & bottom, T const & top, T const & nearVal, T const & farVal) + template + GLM_FUNC_DECL tmat4x4 lookAtRH( + tvec3 const & eye, + tvec3 const & center, + tvec3 const & up); + + /// Build a left handed look at view matrix. + /// + /// @param eye Position of the camera + /// @param center Position where the camera is looking at + /// @param up Normalized up vector, how the camera is oriented. Typically (0, 0, 1) + /// @see gtc_matrix_transform + /// @see - frustum(T const & left, T const & right, T const & bottom, T const & top, T const & nearVal, T const & farVal) frustum(T const & left, T const & right, T const & bottom, T const & top, T const & nearVal, T const & farVal) + template + GLM_FUNC_DECL tmat4x4 lookAtLH( + tvec3 const & eye, + tvec3 const & center, + tvec3 const & up); + /// @} }//namespace glm diff --git a/glm/gtc/matrix_transform.inl b/glm/gtc/matrix_transform.inl index 25df2e3e..047ac6ef 100644 --- a/glm/gtc/matrix_transform.inl +++ b/glm/gtc/matrix_transform.inl @@ -99,7 +99,7 @@ namespace glm tvec3 axis = normalize(v); - Result[0][0] = c + (1 - c) * axis.x * axis.x; + Result[0][0] = c + (1 - c) * axis.x * axis.x; Result[0][1] = (1 - c) * axis.x * axis.y + s * axis.z; Result[0][2] = (1 - c) * axis.x * axis.z - s * axis.y; Result[0][3] = 0; @@ -216,6 +216,22 @@ namespace glm T zNear, T zFar ) + { + #ifdef GLM_LEFT_HANDED + return perspectiveLH(fovy, aspect, zNear, zFar); + #else + return perspectiveRH(fovy, aspect, zNear, zFar); + #endif + } + + template + GLM_FUNC_QUALIFIER tmat4x4 perspectiveRH + ( + T fovy, + T aspect, + T zNear, + T zFar + ) { assert(abs(aspect - std::numeric_limits::epsilon()) > static_cast(0)); @@ -230,6 +246,28 @@ namespace glm return Result; } + template + GLM_FUNC_QUALIFIER tmat4x4 perspectiveLH + ( + T fovy, + T aspect, + T zNear, + T zFar + ) + { + assert(abs(aspect - std::numeric_limits::epsilon()) > static_cast(0)); + + T const tanHalfFovy = tan(fovy / static_cast(2)); + + tmat4x4 Result(static_cast(0)); + Result[0][0] = static_cast(1) / (aspect * tanHalfFovy); + Result[1][1] = static_cast(1) / (tanHalfFovy); + Result[2][2] = (zFar + zNear) / (zFar - zNear); + Result[2][3] = static_cast(1); + Result[3][2] = -(static_cast(2) * zFar * zNear) / (zFar - zNear); + return Result; + } + template GLM_FUNC_QUALIFIER tmat4x4 perspectiveFov ( @@ -239,6 +277,23 @@ namespace glm T zNear, T zFar ) + { + #ifdef GLM_LEFT_HANDED + return perspectiveFovLH(fov, width, height, zNear, zFar); + #else + return perspectiveFovRH(fov, width, height, zNear, zFar); + #endif + } + + template + GLM_FUNC_QUALIFIER tmat4x4 perspectiveFovRH + ( + T fov, + T width, + T height, + T zNear, + T zFar + ) { assert(width > static_cast(0)); assert(height > static_cast(0)); @@ -257,6 +312,33 @@ namespace glm return Result; } + template + GLM_FUNC_QUALIFIER tmat4x4 perspectiveFovLH + ( + T fov, + T width, + T height, + T zNear, + T zFar + ) + { + assert(width > static_cast(0)); + assert(height > static_cast(0)); + assert(fov > static_cast(0)); + + T const rad = fov; + T const h = glm::cos(static_cast(0.5) * rad) / glm::sin(static_cast(0.5) * rad); + T const w = h * height / width; ///todo max(width , Height) / min(width , Height)? + + tmat4x4 Result(static_cast(0)); + Result[0][0] = w; + Result[1][1] = h; + Result[2][2] = (zFar + zNear) / (zFar - zNear); + Result[2][3] = static_cast(1); + Result[3][2] = - (static_cast(2) * zFar * zNear) / (zFar - zNear); + return Result; + } + template GLM_FUNC_QUALIFIER tmat4x4 infinitePerspective ( @@ -390,6 +472,21 @@ namespace glm tvec3 const & center, tvec3 const & up ) + { + #ifdef GLM_LEFT_HANDED + return lookAtLH(eye, center, up); + #else + return lookAtRH(eye, center, up); + #endif + } + + template + GLM_FUNC_QUALIFIER tmat4x4 lookAtRH + ( + tvec3 const & eye, + tvec3 const & center, + tvec3 const & up + ) { tvec3 const f(normalize(center - eye)); tvec3 const s(normalize(cross(f, up))); @@ -410,4 +507,32 @@ namespace glm Result[3][2] = dot(f, eye); return Result; } + + template + GLM_FUNC_QUALIFIER tmat4x4 lookAtLH + ( + tvec3 const & eye, + tvec3 const & center, + tvec3 const & up + ) + { + tvec3 const f(normalize(center - eye)); + tvec3 const s(normalize(cross(up, f))); + tvec3 const u(cross(f, s)); + + tmat4x4 Result(1); + Result[0][0] = s.x; + Result[1][0] = s.y; + Result[2][0] = s.z; + Result[0][1] = u.x; + Result[1][1] = u.y; + Result[2][1] = u.z; + Result[0][2] = f.x; + Result[1][2] = f.y; + Result[2][2] = f.z; + Result[3][0] = -dot(s, eye); + Result[3][1] = -dot(u, eye); + Result[3][2] = -dot(f, eye); + return Result; + } }//namespace glm