| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- // ----------------------------------------------------------------
- // From Game Programming in C++ by Sanjay Madhav
- // Copyright (C) 2017 Sanjay Madhav. All rights reserved.
- //
- // Released under the BSD License
- // See LICENSE in root directory for full details.
- // ----------------------------------------------------------------
- #include "Math.h"
- const Vector2 Vector2::Zero(0.0f, 0.0f);
- const Vector2 Vector2::UnitX(1.0f, 0.0f);
- const Vector2 Vector2::UnitY(0.0f, 1.0f);
- const Vector2 Vector2::NegUnitX(-1.0f, 0.0f);
- const Vector2 Vector2::NegUnitY(0.0f, -1.0f);
- const Vector3 Vector3::Zero(0.0f, 0.0f, 0.f);
- const Vector3 Vector3::UnitX(1.0f, 0.0f, 0.0f);
- const Vector3 Vector3::UnitY(0.0f, 1.0f, 0.0f);
- const Vector3 Vector3::UnitZ(0.0f, 0.0f, 1.0f);
- const Vector3 Vector3::NegUnitX(-1.0f, 0.0f, 0.0f);
- const Vector3 Vector3::NegUnitY(0.0f, -1.0f, 0.0f);
- const Vector3 Vector3::NegUnitZ(0.0f, 0.0f, -1.0f);
- const Vector3 Vector3::Infinity(Math::Infinity, Math::Infinity, Math::Infinity);
- const Vector3 Vector3::NegInfinity(Math::NegInfinity, Math::NegInfinity, Math::NegInfinity);
- static float m3Ident[3][3] =
- {
- { 1.0f, 0.0f, 0.0f },
- { 0.0f, 1.0f, 0.0f },
- { 0.0f, 0.0f, 1.0f }
- };
- const Matrix3 Matrix3::Identity(m3Ident);
- static float m4Ident[4][4] =
- {
- { 1.0f, 0.0f, 0.0f, 0.0f },
- { 0.0f, 1.0f, 0.0f, 0.0f },
- { 0.0f, 0.0f, 1.0f, 0.0f },
- { 0.0f, 0.0f, 0.0f, 1.0f }
- };
- const Matrix4 Matrix4::Identity(m4Ident);
- const Quaternion Quaternion::Identity(0.0f, 0.0f, 0.0f, 1.0f);
- Vector2 Vector2::Transform(const Vector2& vec, const Matrix3& mat, float w /*= 1.0f*/)
- {
- Vector2 retVal;
- retVal.x = vec.x * mat.mat[0][0] + vec.y * mat.mat[1][0] + w * mat.mat[2][0];
- retVal.y = vec.x * mat.mat[0][1] + vec.y * mat.mat[1][1] + w * mat.mat[2][1];
- //ignore w since we aren't returning a new value for it...
- return retVal;
- }
- Vector3 Vector3::Transform(const Vector3& vec, const Matrix4& mat, float w /*= 1.0f*/)
- {
- Vector3 retVal;
- retVal.x = vec.x * mat.mat[0][0] + vec.y * mat.mat[1][0] +
- vec.z * mat.mat[2][0] + w * mat.mat[3][0];
- retVal.y = vec.x * mat.mat[0][1] + vec.y * mat.mat[1][1] +
- vec.z * mat.mat[2][1] + w * mat.mat[3][1];
- retVal.z = vec.x * mat.mat[0][2] + vec.y * mat.mat[1][2] +
- vec.z * mat.mat[2][2] + w * mat.mat[3][2];
- //ignore w since we aren't returning a new value for it...
- return retVal;
- }
- // This will transform the vector and renormalize the w component
- Vector3 Vector3::TransformWithPerspDiv(const Vector3& vec, const Matrix4& mat, float w /*= 1.0f*/)
- {
- Vector3 retVal;
- retVal.x = vec.x * mat.mat[0][0] + vec.y * mat.mat[1][0] +
- vec.z * mat.mat[2][0] + w * mat.mat[3][0];
- retVal.y = vec.x * mat.mat[0][1] + vec.y * mat.mat[1][1] +
- vec.z * mat.mat[2][1] + w * mat.mat[3][1];
- retVal.z = vec.x * mat.mat[0][2] + vec.y * mat.mat[1][2] +
- vec.z * mat.mat[2][2] + w * mat.mat[3][2];
- float transformedW = vec.x * mat.mat[0][3] + vec.y * mat.mat[1][3] +
- vec.z * mat.mat[2][3] + w * mat.mat[3][3];
- if (!Math::NearZero(Math::Abs(transformedW)))
- {
- transformedW = 1.0f / transformedW;
- retVal *= transformedW;
- }
- return retVal;
- }
- // Transform a Vector3 by a quaternion
- Vector3 Vector3::Transform(const Vector3& v, const Quaternion& q)
- {
- // v + 2.0*cross(q.xyz, cross(q.xyz,v) + q.w*v);
- Vector3 qv(q.x, q.y, q.z);
- Vector3 retVal = v;
- retVal += 2.0f * Vector3::Cross(qv, Vector3::Cross(qv, v) + q.w * v);
- return retVal;
- }
- void Matrix4::Invert()
- {
- // Thanks slow math
- // This is a really janky way to unroll everything...
- float tmp[12];
- float src[16];
- float dst[16];
- float det;
- // Transpose matrix
- // row 1 to col 1
- src[0] = mat[0][0];
- src[4] = mat[0][1];
- src[8] = mat[0][2];
- src[12] = mat[0][3];
- // row 2 to col 2
- src[1] = mat[1][0];
- src[5] = mat[1][1];
- src[9] = mat[1][2];
- src[13] = mat[1][3];
- // row 3 to col 3
- src[2] = mat[2][0];
- src[6] = mat[2][1];
- src[10] = mat[2][2];
- src[14] = mat[2][3];
- // row 4 to col 4
- src[3] = mat[3][0];
- src[7] = mat[3][1];
- src[11] = mat[3][2];
- src[15] = mat[3][3];
- // Calculate cofactors
- tmp[0] = src[10] * src[15];
- tmp[1] = src[11] * src[14];
- tmp[2] = src[9] * src[15];
- tmp[3] = src[11] * src[13];
- tmp[4] = src[9] * src[14];
- tmp[5] = src[10] * src[13];
- tmp[6] = src[8] * src[15];
- tmp[7] = src[11] * src[12];
- tmp[8] = src[8] * src[14];
- tmp[9] = src[10] * src[12];
- tmp[10] = src[8] * src[13];
- tmp[11] = src[9] * src[12];
-
- dst[0] = tmp[0] * src[5] + tmp[3] * src[6] + tmp[4] * src[7];
- dst[0] -= tmp[1] * src[5] + tmp[2] * src[6] + tmp[5] * src[7];
- dst[1] = tmp[1] * src[4] + tmp[6] * src[6] + tmp[9] * src[7];
- dst[1] -= tmp[0] * src[4] + tmp[7] * src[6] + tmp[8] * src[7];
- dst[2] = tmp[2] * src[4] + tmp[7] * src[5] + tmp[10] * src[7];
- dst[2] -= tmp[3] * src[4] + tmp[6] * src[5] + tmp[11] * src[7];
- dst[3] = tmp[5] * src[4] + tmp[8] * src[5] + tmp[11] * src[6];
- dst[3] -= tmp[4] * src[4] + tmp[9] * src[5] + tmp[10] * src[6];
- dst[4] = tmp[1] * src[1] + tmp[2] * src[2] + tmp[5] * src[3];
- dst[4] -= tmp[0] * src[1] + tmp[3] * src[2] + tmp[4] * src[3];
- dst[5] = tmp[0] * src[0] + tmp[7] * src[2] + tmp[8] * src[3];
- dst[5] -= tmp[1] * src[0] + tmp[6] * src[2] + tmp[9] * src[3];
- dst[6] = tmp[3] * src[0] + tmp[6] * src[1] + tmp[11] * src[3];
- dst[6] -= tmp[2] * src[0] + tmp[7] * src[1] + tmp[10] * src[3];
- dst[7] = tmp[4] * src[0] + tmp[9] * src[1] + tmp[10] * src[2];
- dst[7] -= tmp[5] * src[0] + tmp[8] * src[1] + tmp[11] * src[2];
-
- tmp[0] = src[2] * src[7];
- tmp[1] = src[3] * src[6];
- tmp[2] = src[1] * src[7];
- tmp[3] = src[3] * src[5];
- tmp[4] = src[1] * src[6];
- tmp[5] = src[2] * src[5];
- tmp[6] = src[0] * src[7];
- tmp[7] = src[3] * src[4];
- tmp[8] = src[0] * src[6];
- tmp[9] = src[2] * src[4];
- tmp[10] = src[0] * src[5];
- tmp[11] = src[1] * src[4];
-
- dst[8] = tmp[0] * src[13] + tmp[3] * src[14] + tmp[4] * src[15];
- dst[8] -= tmp[1] * src[13] + tmp[2] * src[14] + tmp[5] * src[15];
- dst[9] = tmp[1] * src[12] + tmp[6] * src[14] + tmp[9] * src[15];
- dst[9] -= tmp[0] * src[12] + tmp[7] * src[14] + tmp[8] * src[15];
- dst[10] = tmp[2] * src[12] + tmp[7] * src[13] + tmp[10] * src[15];
- dst[10] -= tmp[3] * src[12] + tmp[6] * src[13] + tmp[11] * src[15];
- dst[11] = tmp[5] * src[12] + tmp[8] * src[13] + tmp[11] * src[14];
- dst[11] -= tmp[4] * src[12] + tmp[9] * src[13] + tmp[10] * src[14];
- dst[12] = tmp[2] * src[10] + tmp[5] * src[11] + tmp[1] * src[9];
- dst[12] -= tmp[4] * src[11] + tmp[0] * src[9] + tmp[3] * src[10];
- dst[13] = tmp[8] * src[11] + tmp[0] * src[8] + tmp[7] * src[10];
- dst[13] -= tmp[6] * src[10] + tmp[9] * src[11] + tmp[1] * src[8];
- dst[14] = tmp[6] * src[9] + tmp[11] * src[11] + tmp[3] * src[8];
- dst[14] -= tmp[10] * src[11] + tmp[2] * src[8] + tmp[7] * src[9];
- dst[15] = tmp[10] * src[10] + tmp[4] * src[8] + tmp[9] * src[9];
- dst[15] -= tmp[8] * src[9] + tmp[11] * src[10] + tmp[5] * src[8];
-
- // Calculate determinant
- det = src[0] * dst[0] + src[1] * dst[1] + src[2] * dst[2] + src[3] * dst[3];
-
- // Inverse of matrix is divided by determinant
- det = 1 / det;
- for (int j = 0; j < 16; j++)
- {
- dst[j] *= det;
- }
- // Set it back
- for (int i = 0; i < 4; i++)
- {
- for (int j = 0; j < 4; j++)
- {
- mat[i][j] = dst[i * 4 + j];
- }
- }
- }
- Matrix4 Matrix4::CreateFromQuaternion(const class Quaternion& q)
- {
- float mat[4][4];
-
- mat[0][0] = 1.0f - 2.0f * q.y * q.y - 2.0f * q.z * q.z;
- mat[0][1] = 2.0f * q.x * q.y + 2.0f * q.w * q.z;
- mat[0][2] = 2.0f * q.x * q.z - 2.0f * q.w * q.y;
- mat[0][3] = 0.0f;
- mat[1][0] = 2.0f * q.x * q.y - 2.0f * q.w * q.z;
- mat[1][1] = 1.0f - 2.0f * q.x * q.x - 2.0f * q.z * q.z;
- mat[1][2] = 2.0f * q.y * q.z + 2.0f * q.w * q.x;
- mat[1][3] = 0.0f;
- mat[2][0] = 2.0f * q.x * q.z + 2.0f * q.w * q.y;
- mat[2][1] = 2.0f * q.y * q.z - 2.0f * q.w * q.x;
- mat[2][2] = 1.0f - 2.0f * q.x * q.x - 2.0f * q.y * q.y;
- mat[2][3] = 0.0f;
- mat[3][0] = 0.0f;
- mat[3][1] = 0.0f;
- mat[3][2] = 0.0f;
- mat[3][3] = 1.0f;
- return Matrix4(mat);
- }
|