From 8200f815bf89ed5c3ae739fb60981a4488383df5 Mon Sep 17 00:00:00 2001 From: Erik Sejersen Date: Tue, 17 Nov 2015 14:52:50 +0100 Subject: [PATCH] Added left and right handedness to more projection functions and added a define for glClipControl GL_ZERO_TO_ONE --- glm/gtc/matrix_transform.hpp | 146 ++++++++++++++++++++++---- glm/gtc/matrix_transform.inl | 196 ++++++++++++++++++++++++++++++++--- 2 files changed, 304 insertions(+), 38 deletions(-) diff --git a/glm/gtc/matrix_transform.hpp b/glm/gtc/matrix_transform.hpp index b9f8098c..ebaf5e1f 100644 --- a/glm/gtc/matrix_transform.hpp +++ b/glm/gtc/matrix_transform.hpp @@ -116,14 +116,14 @@ namespace glm tmat4x4 const & m, tvec3 const & v); - /// Creates a matrix for an orthographic parallel viewing volume. - /// - /// @param left - /// @param right - /// @param bottom - /// @param top - /// @param zNear - /// @param zFar + /// Creates a matrix for an orthographic parallel viewing volume, using the default handedness. + /// + /// @param left + /// @param right + /// @param bottom + /// @param top + /// @param zNear + /// @param zFar /// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double. /// @see gtc_matrix_transform /// @see - glm::ortho(T const & left, T const & right, T const & bottom, T const & top) @@ -136,12 +136,52 @@ namespace glm T zNear, T zFar); + /// Creates a matrix for an orthographic parallel viewing volume, using left-handedness. + /// + /// @param left + /// @param right + /// @param bottom + /// @param top + /// @param zNear + /// @param zFar + /// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double. + /// @see gtc_matrix_transform + /// @see - glm::ortho(T const & left, T const & right, T const & bottom, T const & top) + template + GLM_FUNC_DECL tmat4x4 orthoLH( + T left, + T right, + T bottom, + T top, + T zNear, + T zFar); + + /// Creates a matrix for an orthographic parallel viewing volume, using right-handedness. + /// + /// @param left + /// @param right + /// @param bottom + /// @param top + /// @param zNear + /// @param zFar + /// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double. + /// @see gtc_matrix_transform + /// @see - glm::ortho(T const & left, T const & right, T const & bottom, T const & top) + template + GLM_FUNC_DECL tmat4x4 orthoRH( + T left, + T right, + T bottom, + T top, + T zNear, + T zFar); + /// Creates a matrix for projecting two-dimensional coordinates onto the screen. - /// - /// @param left - /// @param right - /// @param bottom - /// @param top + /// + /// @param left + /// @param right + /// @param bottom + /// @param top /// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double. /// @see gtc_matrix_transform /// @see - glm::ortho(T const & left, T const & right, T const & bottom, T const & top, T const & zNear, T const & zFar) @@ -152,14 +192,14 @@ namespace glm T bottom, T top); - /// Creates a frustum matrix. - /// - /// @param left - /// @param right - /// @param bottom - /// @param top - /// @param near - /// @param far + /// Creates a frustum matrix with default handedness. + /// + /// @param left + /// @param right + /// @param bottom + /// @param top + /// @param near + /// @param far /// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double. /// @see gtc_matrix_transform template @@ -171,6 +211,44 @@ namespace glm T near, T far); + /// Creates a left handed frustum matrix. + /// + /// @param left + /// @param right + /// @param bottom + /// @param top + /// @param near + /// @param far + /// @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 frustumLH( + T left, + T right, + T bottom, + T top, + T near, + T far); + + /// Creates a right handed frustum matrix. + /// + /// @param left + /// @param right + /// @param bottom + /// @param top + /// @param near + /// @param far + /// @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 frustumRH( + T left, + T right, + T bottom, + T top, + T near, + T far); + /// Creates a matrix for a symetric perspective-view frustum based on the default handedness. /// /// @param fovy Specifies the field of view angle in the y direction. Expressed in radians. @@ -267,8 +345,8 @@ namespace glm T near, T far); - /// Creates a matrix for a symmetric perspective-view frustum with far plane at infinite. - /// + /// Creates a matrix for a symmetric perspective-view frustum with far plane at infinite with 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). /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). @@ -278,6 +356,28 @@ namespace glm GLM_FUNC_DECL tmat4x4 infinitePerspective( T fovy, T aspect, T near); + /// Creates a matrix for a left handed, 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. + /// @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). + /// @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 infinitePerspectiveLH( + T fovy, T aspect, T near); + + /// Creates a matrix for a right handed, 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. + /// @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). + /// @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 infinitePerspectiveRH( + T fovy, T aspect, T near); + /// Creates a matrix for a symmetric perspective-view frustum with far plane at infinite for graphics hardware that doesn't support depth clamping. /// /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. diff --git a/glm/gtc/matrix_transform.inl b/glm/gtc/matrix_transform.inl index d60494e3..7e2c05bc 100644 --- a/glm/gtc/matrix_transform.inl +++ b/glm/gtc/matrix_transform.inl @@ -157,14 +157,65 @@ namespace glm T zNear, T zFar ) + { + #ifdef GLM_LEFT_HANDED + return orthoLH(left, right, bottom, top, zNear, zFar); + #else + return orthoRH(left, right, bottom, top, zNear, zFar); + #endif + } + + template + GLM_FUNC_QUALIFIER tmat4x4 orthoLH + ( + T left, + T right, + T bottom, + T top, + T zNear, + T zFar + ) { tmat4x4 Result(1); Result[0][0] = static_cast(2) / (right - left); Result[1][1] = static_cast(2) / (top - bottom); - Result[2][2] = - static_cast(2) / (zFar - zNear); Result[3][0] = - (right + left) / (right - left); Result[3][1] = - (top + bottom) / (top - bottom); + +#ifdef GLM_DEPTH_ZERO_TO_ONE + Result[2][2] = static_cast(1) / (zFar - zNear); + Result[3][2] = - zNear / (zFar - zNear); +#else + Result[2][2] = static_cast(2) / (zFar - zNear); Result[3][2] = - (zFar + zNear) / (zFar - zNear); +#endif + return Result; + } + + template + GLM_FUNC_QUALIFIER tmat4x4 orthoRH + ( + T left, + T right, + T bottom, + T top, + T zNear, + T zFar + ) + { + tmat4x4 Result(1); + Result[0][0] = static_cast(2) / (right - left); + Result[1][1] = static_cast(2) / (top - bottom); + Result[3][0] = - (right + left) / (right - left); + Result[3][1] = - (top + bottom) / (top - bottom); + +#ifdef GLM_DEPTH_ZERO_TO_ONE + Result[2][2] = - static_cast(1) / (zFar - zNear); + Result[3][2] = - zNear / (zFar - zNear); +#else + Result[2][2] = - static_cast(2) / (zFar - zNear); + Result[3][2] = - (zFar + zNear) / (zFar - zNear); +#endif return Result; } @@ -177,13 +228,13 @@ namespace glm T top ) { - tmat4x4 Result(1); - Result[0][0] = static_cast(2) / (right - left); - Result[1][1] = static_cast(2) / (top - bottom); - Result[2][2] = - static_cast(1); - Result[3][0] = - (right + left) / (right - left); - Result[3][1] = - (top + bottom) / (top - bottom); - return Result; + tmat4x4 Result(1); + Result[0][0] = static_cast(2) / (right - left); + Result[1][1] = static_cast(2) / (top - bottom); + Result[2][2] = - static_cast(1); + Result[3][0] = - (right + left) / (right - left); + Result[3][1] = - (top + bottom) / (top - bottom); + return Result; } template @@ -196,15 +247,67 @@ namespace glm T nearVal, T farVal ) + { +#ifdef GLM_LEFT_HANDED + return frustumLH(left, right, bottom, top, nearVal, farVal); +#else + return frustumRH(left, right, bottom, top, nearVal, farVal); +#endif + } + + template + GLM_FUNC_QUALIFIER tmat4x4 frustumLH + ( + T left, + T right, + T bottom, + T top, + T nearVal, + T farVal + ) + { + tmat4x4 Result(0); + Result[0][0] = (static_cast(2) * nearVal) / (right - left); + Result[1][1] = (static_cast(2) * nearVal) / (top - bottom); + Result[2][0] = (right + left) / (right - left); + Result[2][1] = (top + bottom) / (top - bottom); + Result[2][3] = static_cast(1); + +#ifdef GLM_DEPTH_ZERO_TO_ONE + Result[2][2] = farVal / (zFar - nearVal); + Result[3][2] = -(farVal * nearVal) / (zFar - nearVal); +#else + Result[2][2] = (farVal + nearVal) / (farVal - nearVal); + Result[3][2] = - (static_cast(2) * farVal * nearVal) / (farVal - nearVal); +#endif + return Result; + } + + template + GLM_FUNC_QUALIFIER tmat4x4 frustumRH + ( + T left, + T right, + T bottom, + T top, + T nearVal, + T farVal + ) { tmat4x4 Result(0); Result[0][0] = (static_cast(2) * nearVal) / (right - left); Result[1][1] = (static_cast(2) * nearVal) / (top - bottom); Result[2][0] = (right + left) / (right - left); Result[2][1] = (top + bottom) / (top - bottom); - Result[2][2] = -(farVal + nearVal) / (farVal - nearVal); Result[2][3] = static_cast(-1); - Result[3][2] = -(static_cast(2) * farVal * nearVal) / (farVal - nearVal); + +#ifdef GLM_DEPTH_ZERO_TO_ONE + Result[2][2] = farVal / (nearVal - farVal); + Result[3][2] = -(farVal * nearVal) / (farVal - nearVal); +#else + Result[2][2] = - (farVal + nearVal) / (farVal - nearVal); + Result[3][2] = - (static_cast(2) * farVal * nearVal) / (farVal - nearVal); +#endif return Result; } @@ -240,9 +343,15 @@ namespace glm 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); + +#ifdef GLM_DEPTH_ZERO_TO_ONE + Result[2][2] = zFar / (zNear - zFar); + Result[3][2] = -(zFar * zNear) / (zFar - zNear); +#else + Result[2][2] = - (zFar + zNear) / (zFar - zNear); Result[3][2] = - (static_cast(2) * zFar * zNear) / (zFar - zNear); +#endif return Result; } @@ -262,9 +371,15 @@ namespace glm 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); + +#ifdef GLM_DEPTH_ZERO_TO_ONE + Result[2][2] = zFar / (zFar - zNear); + Result[3][2] = -(zFar * zNear) / (zFar - zNear); +#else + Result[2][2] = (zFar + zNear) / (zFar - zNear); + Result[3][2] = - (static_cast(2) * zFar * zNear) / (zFar - zNear); +#endif return Result; } @@ -306,9 +421,15 @@ namespace glm 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); + +#ifdef GLM_DEPTH_ZERO_TO_ONE + Result[2][2] = zFar / (zNear - zFar); + Result[3][2] = -(zFar * zNear) / (zFar - zNear); +#else + Result[2][2] = - (zFar + zNear) / (zFar - zNear); Result[3][2] = - (static_cast(2) * zFar * zNear) / (zFar - zNear); +#endif return Result; } @@ -333,9 +454,16 @@ namespace glm 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); + +#ifdef GLM_DEPTH_ZERO_TO_ONE + Result[2][2] = zFar / (zFar - zNear); + Result[3][2] = -(zFar * zNear) / (zFar - zNear); +#else + Result[2][2] = (zFar + zNear) / (zFar - zNear); Result[3][2] = - (static_cast(2) * zFar * zNear) / (zFar - zNear); +#endif + return Result; } @@ -346,6 +474,21 @@ namespace glm T aspect, T zNear ) + { +#ifdef GLM_LEFT_HANDED + return infinitePerspectiveLH(fovy, aspect, zNear); +#else + return infinitePerspectiveRH(fovy, aspect, zNear); +#endif + } + + template + GLM_FUNC_QUALIFIER tmat4x4 infinitePerspectiveRH + ( + T fovy, + T aspect, + T zNear + ) { T const range = tan(fovy / T(2)) * zNear; T const left = -range * aspect; @@ -362,6 +505,29 @@ namespace glm return Result; } + template + GLM_FUNC_QUALIFIER tmat4x4 infinitePerspectiveLH + ( + T fovy, + T aspect, + T zNear + ) + { + T const range = tan(fovy / T(2)) * zNear; + T const left = -range * aspect; + T const right = range * aspect; + T const bottom = -range; + T const top = range; + + tmat4x4 Result(T(0)); + Result[0][0] = (T(2) * zNear) / (right - left); + Result[1][1] = (T(2) * zNear) / (top - bottom); + Result[2][2] = T(1); + Result[2][3] = T(1); + Result[3][2] = - T(2) * zNear; + return Result; + } + // Infinite projection matrix: http://www.terathon.com/gdc07_lengyel.pdf template GLM_FUNC_QUALIFIER tmat4x4 tweakedInfinitePerspective