nuclear@3: /************************************************************************************ nuclear@3: nuclear@3: Filename : OVR_Math.h nuclear@3: Content : Implementation of 3D primitives such as vectors, matrices. nuclear@3: Created : September 4, 2012 nuclear@3: Authors : Andrew Reisse, Michael Antonov nuclear@3: nuclear@3: Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. nuclear@3: nuclear@3: Use of this software is subject to the terms of the Oculus license nuclear@3: agreement provided at the time of installation or download, or which nuclear@3: otherwise accompanies this software in either electronic or hard copy form. nuclear@3: nuclear@3: *************************************************************************************/ nuclear@3: nuclear@3: #include "OVR_Math.h" nuclear@3: nuclear@3: #include nuclear@3: nuclear@3: namespace OVR { nuclear@3: nuclear@3: nuclear@3: //------------------------------------------------------------------------------------- nuclear@3: // ***** Math nuclear@3: nuclear@3: nuclear@3: // Single-precision Math constants class. nuclear@3: const float Math::Pi = 3.1415926f; nuclear@3: const float Math::TwoPi = 3.1415926f * 2; nuclear@3: const float Math::PiOver2 = 3.1415926f / 2.0f; nuclear@3: const float Math::PiOver4 = 3.1415926f / 4.0f; nuclear@3: const float Math::E = 2.7182818f; nuclear@3: nuclear@3: const float Math::MaxValue = FLT_MAX; nuclear@3: const float Math::MinPositiveValue = FLT_MIN; nuclear@3: nuclear@3: const float Math::RadToDegreeFactor = 360.0f / Math::TwoPi; nuclear@3: const float Math::DegreeToRadFactor = Math::TwoPi / 360.0f; nuclear@3: nuclear@3: const float Math::Tolerance = 0.00001f; nuclear@3: const float Math::SingularityRadius = 0.0000001f; // Use for Gimbal lock numerical problems nuclear@3: nuclear@3: nuclear@3: // Double-precision Math constants class. nuclear@3: const double Math::Pi = 3.14159265358979; nuclear@3: const double Math::TwoPi = 3.14159265358979 * 2; nuclear@3: const double Math::PiOver2 = 3.14159265358979 / 2.0; nuclear@3: const double Math::PiOver4 = 3.14159265358979 / 4.0; nuclear@3: const double Math::E = 2.71828182845905; nuclear@3: nuclear@3: const double Math::MaxValue = DBL_MAX; nuclear@3: const double Math::MinPositiveValue = DBL_MIN; nuclear@3: nuclear@3: const double Math::RadToDegreeFactor = 360.0 / Math::TwoPi; nuclear@3: const double Math::DegreeToRadFactor = Math::TwoPi / 360.0; nuclear@3: nuclear@3: const double Math::Tolerance = 0.00001; nuclear@3: const double Math::SingularityRadius = 0.000000000001; // Use for Gimbal lock numerical problems nuclear@3: nuclear@3: nuclear@3: nuclear@3: //------------------------------------------------------------------------------------- nuclear@3: // ***** Matrix4f nuclear@3: nuclear@3: nuclear@3: Matrix4f Matrix4f::LookAtRH(const Vector3f& eye, const Vector3f& at, const Vector3f& up) nuclear@3: { nuclear@3: Vector3f z = (eye - at).Normalized(); // Forward nuclear@3: Vector3f x = up.Cross(z).Normalized(); // Right nuclear@3: Vector3f y = z.Cross(x); nuclear@3: nuclear@3: Matrix4f m(x.x, x.y, x.z, -(x * eye), nuclear@3: y.x, y.y, y.z, -(y * eye), nuclear@3: z.x, z.y, z.z, -(z * eye), nuclear@3: 0, 0, 0, 1 ); nuclear@3: return m; nuclear@3: } nuclear@3: nuclear@3: Matrix4f Matrix4f::LookAtLH(const Vector3f& eye, const Vector3f& at, const Vector3f& up) nuclear@3: { nuclear@3: Vector3f z = (at - eye).Normalized(); // Forward nuclear@3: Vector3f x = up.Cross(z).Normalized(); // Right nuclear@3: Vector3f y = z.Cross(x); nuclear@3: nuclear@3: Matrix4f m(x.x, x.y, x.z, -(x * eye), nuclear@3: y.x, y.y, y.z, -(y * eye), nuclear@3: z.x, z.y, z.z, -(z * eye), nuclear@3: 0, 0, 0, 1 ); nuclear@3: return m; nuclear@3: } nuclear@3: nuclear@3: nuclear@3: Matrix4f Matrix4f::PerspectiveLH(float yfov, float aspect, float znear, float zfar) nuclear@3: { nuclear@3: Matrix4f m; nuclear@3: float tanHalfFov = tan(yfov * 0.5f); nuclear@3: nuclear@3: m.M[0][0] = 1.0f / (aspect * tanHalfFov); nuclear@3: m.M[1][1] = 1.0f / tanHalfFov; nuclear@3: m.M[2][2] = zfar / (zfar - znear); nuclear@3: m.M[3][2] = 1.0f; nuclear@3: m.M[2][3] = (zfar * znear) / (znear - zfar); nuclear@3: m.M[3][3] = 0.0f; nuclear@3: nuclear@3: // Note: Post-projection matrix result assumes Left-Handed coordinate system, nuclear@3: // with Y up, X right and Z forward. This supports positive z-buffer values. nuclear@3: return m; nuclear@3: } nuclear@3: nuclear@3: nuclear@3: Matrix4f Matrix4f::PerspectiveRH(float yfov, float aspect, float znear, float zfar) nuclear@3: { nuclear@3: Matrix4f m; nuclear@3: float tanHalfFov = tan(yfov * 0.5f); nuclear@3: nuclear@3: m.M[0][0] = 1.0f / (aspect * tanHalfFov); nuclear@3: m.M[1][1] = 1.0f / tanHalfFov; nuclear@3: m.M[2][2] = zfar / (znear - zfar); nuclear@3: // m.M[2][2] = zfar / (zfar - znear); nuclear@3: m.M[3][2] = -1.0f; nuclear@3: m.M[2][3] = (zfar * znear) / (znear - zfar); nuclear@3: m.M[3][3] = 0.0f; nuclear@3: nuclear@3: // Note: Post-projection matrix result assumes Left-Handed coordinate system, nuclear@3: // with Y up, X right and Z forward. This supports positive z-buffer values. nuclear@3: // This is the case even for RHS cooridnate input. nuclear@3: return m; nuclear@3: } nuclear@3: nuclear@3: nuclear@3: /* nuclear@3: OffCenterLH nuclear@3: nuclear@3: 2*zn/(r-l) 0 0 0 nuclear@3: 0 2*zn/(t-b) 0 0 nuclear@3: (l+r)/(l-r) (t+b)/(b-t) zf/(zf-zn) 1 nuclear@3: 0 0 zn*zf/(zn-zf) 0 nuclear@3: nuclear@3: */ nuclear@3: nuclear@3: nuclear@3: Matrix4f Matrix4f::Ortho2D(float w, float h) nuclear@3: { nuclear@3: Matrix4f m; nuclear@3: m.M[0][0] = 2.0f/w; nuclear@3: m.M[1][1] = -2.0f/h; nuclear@3: m.M[0][3] = -1.0; nuclear@3: m.M[1][3] = 1.0; nuclear@3: m.M[2][2] = 0; nuclear@3: return m; nuclear@3: } nuclear@3: nuclear@3: }