307 lines
13 KiB
C++
307 lines
13 KiB
C++
|
//
|
||
|
// Copyright 2014 The ANGLE Project Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
// found in the LICENSE file.
|
||
|
//
|
||
|
// Matrix:
|
||
|
// Helper class for doing matrix math.
|
||
|
//
|
||
|
|
||
|
#include "Matrix.h"
|
||
|
|
||
|
#define _USE_MATH_DEFINES
|
||
|
#include <math.h>
|
||
|
#include <cstddef>
|
||
|
|
||
|
using namespace angle;
|
||
|
|
||
|
Matrix4::Matrix4()
|
||
|
{
|
||
|
data[0] = 1.0f;
|
||
|
data[4] = 0.0f;
|
||
|
data[8] = 0.0f;
|
||
|
data[12] = 0.0f;
|
||
|
data[1] = 0.0f;
|
||
|
data[5] = 1.0f;
|
||
|
data[9] = 0.0f;
|
||
|
data[13] = 0.0f;
|
||
|
data[2] = 0.0f;
|
||
|
data[6] = 0.0f;
|
||
|
data[10] = 1.0f;
|
||
|
data[14] = 0.0f;
|
||
|
data[3] = 0.0f;
|
||
|
data[7] = 0.0f;
|
||
|
data[11] = 0.0f;
|
||
|
data[15] = 1.0f;
|
||
|
}
|
||
|
|
||
|
Matrix4::Matrix4(float m00,
|
||
|
float m01,
|
||
|
float m02,
|
||
|
float m03,
|
||
|
float m10,
|
||
|
float m11,
|
||
|
float m12,
|
||
|
float m13,
|
||
|
float m20,
|
||
|
float m21,
|
||
|
float m22,
|
||
|
float m23,
|
||
|
float m30,
|
||
|
float m31,
|
||
|
float m32,
|
||
|
float m33)
|
||
|
{
|
||
|
data[0] = m00;
|
||
|
data[4] = m01;
|
||
|
data[8] = m02;
|
||
|
data[12] = m03;
|
||
|
data[1] = m10;
|
||
|
data[5] = m11;
|
||
|
data[9] = m12;
|
||
|
data[13] = m13;
|
||
|
data[2] = m20;
|
||
|
data[6] = m21;
|
||
|
data[10] = m22;
|
||
|
data[14] = m23;
|
||
|
data[3] = m30;
|
||
|
data[7] = m31;
|
||
|
data[11] = m32;
|
||
|
data[15] = m33;
|
||
|
}
|
||
|
|
||
|
Matrix4 Matrix4::identity()
|
||
|
{
|
||
|
return Matrix4(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);
|
||
|
}
|
||
|
|
||
|
Matrix4 Matrix4::rotate(float angle, const Vector3 &p)
|
||
|
{
|
||
|
Vector3 u = p.normalized();
|
||
|
float theta = static_cast<float>(angle * (M_PI / 180.0f));
|
||
|
float cos_t = cosf(theta);
|
||
|
float sin_t = sinf(theta);
|
||
|
|
||
|
return Matrix4(cos_t + (u.x() * u.x() * (1.0f - cos_t)),
|
||
|
(u.x() * u.y() * (1.0f - cos_t)) - (u.z() * sin_t),
|
||
|
(u.x() * u.z() * (1.0f - cos_t)) + (u.y() * sin_t), 0.0f,
|
||
|
(u.y() * u.x() * (1.0f - cos_t)) + (u.z() * sin_t),
|
||
|
cos_t + (u.y() * u.y() * (1.0f - cos_t)),
|
||
|
(u.y() * u.z() * (1.0f - cos_t)) - (u.x() * sin_t), 0.0f,
|
||
|
(u.z() * u.x() * (1.0f - cos_t)) - (u.y() * sin_t),
|
||
|
(u.z() * u.y() * (1.0f - cos_t)) + (u.x() * sin_t),
|
||
|
cos_t + (u.z() * u.z() * (1.0f - cos_t)), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f);
|
||
|
}
|
||
|
|
||
|
Matrix4 Matrix4::translate(const Vector3 &t)
|
||
|
{
|
||
|
return Matrix4(1.0f, 0.0f, 0.0f, t.x(), 0.0f, 1.0f, 0.0f, t.y(), 0.0f, 0.0f, 1.0f, t.z(), 0.0f,
|
||
|
0.0f, 0.0f, 1.0f);
|
||
|
}
|
||
|
|
||
|
Matrix4 Matrix4::scale(const Vector3 &s)
|
||
|
{
|
||
|
return Matrix4(s.x(), 0.0f, 0.0f, 0.0f, 0.0f, s.y(), 0.0f, 0.0f, 0.0f, 0.0f, s.z(), 0.0f, 0.0f,
|
||
|
0.0f, 0.0f, 1.0f);
|
||
|
}
|
||
|
|
||
|
Matrix4 Matrix4::frustum(float l, float r, float b, float t, float n, float f)
|
||
|
{
|
||
|
return Matrix4((2.0f * n) / (r - l), 0.0f, (r + l) / (r - l), 0.0f, 0.0f, (2.0f * n) / (t - b),
|
||
|
(t + b) / (t - b), 0.0f, 0.0f, 0.0f, -(f + n) / (f - n),
|
||
|
-(2.0f * f * n) / (f - n), 0.0f, 0.0f, -1.0f, 0.0f);
|
||
|
}
|
||
|
|
||
|
Matrix4 Matrix4::perspective(float fovY, float aspectRatio, float nearZ, float farZ)
|
||
|
{
|
||
|
const float frustumHeight = tanf(static_cast<float>(fovY / 360.0f * M_PI)) * nearZ;
|
||
|
const float frustumWidth = frustumHeight * aspectRatio;
|
||
|
return frustum(-frustumWidth, frustumWidth, -frustumHeight, frustumHeight, nearZ, farZ);
|
||
|
}
|
||
|
|
||
|
Matrix4 Matrix4::ortho(float l, float r, float b, float t, float n, float f)
|
||
|
{
|
||
|
return Matrix4(2.0f / (r - l), 0.0f, 0.0f, -(r + l) / (r - l), 0.0f, 2.0f / (t - b), 0.0f,
|
||
|
-(t + b) / (t - b), 0.0f, 0.0f, -2.0f / (f - n), -(f + n) / (f - n), 0.0f, 0.0f,
|
||
|
0.0f, 1.0f);
|
||
|
}
|
||
|
|
||
|
Matrix4 Matrix4::rollPitchYaw(float roll, float pitch, float yaw)
|
||
|
{
|
||
|
return rotate(yaw, Vector3(0, 0, 1)) * rotate(pitch, Vector3(0, 1, 0)) *
|
||
|
rotate(roll, Vector3(1, 0, 0));
|
||
|
}
|
||
|
|
||
|
Matrix4 Matrix4::invert(const Matrix4 &mat)
|
||
|
{
|
||
|
Matrix4 inverted(
|
||
|
mat.data[5] * mat.data[10] * mat.data[15] - mat.data[5] * mat.data[11] * mat.data[14] -
|
||
|
mat.data[9] * mat.data[6] * mat.data[15] + mat.data[9] * mat.data[7] * mat.data[14] +
|
||
|
mat.data[13] * mat.data[6] * mat.data[11] - mat.data[13] * mat.data[7] * mat.data[10],
|
||
|
-mat.data[4] * mat.data[10] * mat.data[15] + mat.data[4] * mat.data[11] * mat.data[14] +
|
||
|
mat.data[8] * mat.data[6] * mat.data[15] - mat.data[8] * mat.data[7] * mat.data[14] -
|
||
|
mat.data[12] * mat.data[6] * mat.data[11] + mat.data[12] * mat.data[7] * mat.data[10],
|
||
|
mat.data[4] * mat.data[9] * mat.data[15] - mat.data[4] * mat.data[11] * mat.data[13] -
|
||
|
mat.data[8] * mat.data[5] * mat.data[15] + mat.data[8] * mat.data[7] * mat.data[13] +
|
||
|
mat.data[12] * mat.data[5] * mat.data[11] - mat.data[12] * mat.data[7] * mat.data[9],
|
||
|
-mat.data[4] * mat.data[9] * mat.data[14] + mat.data[4] * mat.data[10] * mat.data[13] +
|
||
|
mat.data[8] * mat.data[5] * mat.data[14] - mat.data[8] * mat.data[6] * mat.data[13] -
|
||
|
mat.data[12] * mat.data[5] * mat.data[10] + mat.data[12] * mat.data[6] * mat.data[9],
|
||
|
-mat.data[1] * mat.data[10] * mat.data[15] + mat.data[1] * mat.data[11] * mat.data[14] +
|
||
|
mat.data[9] * mat.data[2] * mat.data[15] - mat.data[9] * mat.data[3] * mat.data[14] -
|
||
|
mat.data[13] * mat.data[2] * mat.data[11] + mat.data[13] * mat.data[3] * mat.data[10],
|
||
|
mat.data[0] * mat.data[10] * mat.data[15] - mat.data[0] * mat.data[11] * mat.data[14] -
|
||
|
mat.data[8] * mat.data[2] * mat.data[15] + mat.data[8] * mat.data[3] * mat.data[14] +
|
||
|
mat.data[12] * mat.data[2] * mat.data[11] - mat.data[12] * mat.data[3] * mat.data[10],
|
||
|
-mat.data[0] * mat.data[9] * mat.data[15] + mat.data[0] * mat.data[11] * mat.data[13] +
|
||
|
mat.data[8] * mat.data[1] * mat.data[15] - mat.data[8] * mat.data[3] * mat.data[13] -
|
||
|
mat.data[12] * mat.data[1] * mat.data[11] + mat.data[12] * mat.data[3] * mat.data[9],
|
||
|
mat.data[0] * mat.data[9] * mat.data[14] - mat.data[0] * mat.data[10] * mat.data[13] -
|
||
|
mat.data[8] * mat.data[1] * mat.data[14] + mat.data[8] * mat.data[2] * mat.data[13] +
|
||
|
mat.data[12] * mat.data[1] * mat.data[10] - mat.data[12] * mat.data[2] * mat.data[9],
|
||
|
mat.data[1] * mat.data[6] * mat.data[15] - mat.data[1] * mat.data[7] * mat.data[14] -
|
||
|
mat.data[5] * mat.data[2] * mat.data[15] + mat.data[5] * mat.data[3] * mat.data[14] +
|
||
|
mat.data[13] * mat.data[2] * mat.data[7] - mat.data[13] * mat.data[3] * mat.data[6],
|
||
|
-mat.data[0] * mat.data[6] * mat.data[15] + mat.data[0] * mat.data[7] * mat.data[14] +
|
||
|
mat.data[4] * mat.data[2] * mat.data[15] - mat.data[4] * mat.data[3] * mat.data[14] -
|
||
|
mat.data[12] * mat.data[2] * mat.data[7] + mat.data[12] * mat.data[3] * mat.data[6],
|
||
|
mat.data[0] * mat.data[5] * mat.data[15] - mat.data[0] * mat.data[7] * mat.data[13] -
|
||
|
mat.data[4] * mat.data[1] * mat.data[15] + mat.data[4] * mat.data[3] * mat.data[13] +
|
||
|
mat.data[12] * mat.data[1] * mat.data[7] - mat.data[12] * mat.data[3] * mat.data[5],
|
||
|
-mat.data[0] * mat.data[5] * mat.data[14] + mat.data[0] * mat.data[6] * mat.data[13] +
|
||
|
mat.data[4] * mat.data[1] * mat.data[14] - mat.data[4] * mat.data[2] * mat.data[13] -
|
||
|
mat.data[12] * mat.data[1] * mat.data[6] + mat.data[12] * mat.data[2] * mat.data[5],
|
||
|
-mat.data[1] * mat.data[6] * mat.data[11] + mat.data[1] * mat.data[7] * mat.data[10] +
|
||
|
mat.data[5] * mat.data[2] * mat.data[11] - mat.data[5] * mat.data[3] * mat.data[10] -
|
||
|
mat.data[9] * mat.data[2] * mat.data[7] + mat.data[9] * mat.data[3] * mat.data[6],
|
||
|
mat.data[0] * mat.data[6] * mat.data[11] - mat.data[0] * mat.data[7] * mat.data[10] -
|
||
|
mat.data[4] * mat.data[2] * mat.data[11] + mat.data[4] * mat.data[3] * mat.data[10] +
|
||
|
mat.data[8] * mat.data[2] * mat.data[7] - mat.data[8] * mat.data[3] * mat.data[6],
|
||
|
-mat.data[0] * mat.data[5] * mat.data[11] + mat.data[0] * mat.data[7] * mat.data[9] +
|
||
|
mat.data[4] * mat.data[1] * mat.data[11] - mat.data[4] * mat.data[3] * mat.data[9] -
|
||
|
mat.data[8] * mat.data[1] * mat.data[7] + mat.data[8] * mat.data[3] * mat.data[5],
|
||
|
mat.data[0] * mat.data[5] * mat.data[10] - mat.data[0] * mat.data[6] * mat.data[9] -
|
||
|
mat.data[4] * mat.data[1] * mat.data[10] + mat.data[4] * mat.data[2] * mat.data[9] +
|
||
|
mat.data[8] * mat.data[1] * mat.data[6] - mat.data[8] * mat.data[2] * mat.data[5]);
|
||
|
|
||
|
float determinant = mat.data[0] * inverted.data[0] + mat.data[1] * inverted.data[4] +
|
||
|
mat.data[2] * inverted.data[8] + mat.data[3] * inverted.data[12];
|
||
|
|
||
|
if (determinant != 0.0f)
|
||
|
{
|
||
|
inverted *= 1.0f / determinant;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
inverted = identity();
|
||
|
}
|
||
|
|
||
|
return inverted;
|
||
|
}
|
||
|
|
||
|
Matrix4 Matrix4::transpose(const Matrix4 &mat)
|
||
|
{
|
||
|
return Matrix4(mat.data[0], mat.data[1], mat.data[2], mat.data[3], mat.data[4], mat.data[5],
|
||
|
mat.data[6], mat.data[7], mat.data[8], mat.data[9], mat.data[10], mat.data[11],
|
||
|
mat.data[12], mat.data[13], mat.data[14], mat.data[15]);
|
||
|
}
|
||
|
|
||
|
Vector3 Matrix4::transform(const Matrix4 &mat, const Vector3 &pt)
|
||
|
{
|
||
|
Vector4 transformed = (mat * Vector4(pt, 1.0f)).normalized();
|
||
|
return Vector3(transformed.x(), transformed.y(), transformed.z());
|
||
|
}
|
||
|
|
||
|
Vector3 Matrix4::transform(const Matrix4 &mat, const Vector4 &pt)
|
||
|
{
|
||
|
Vector4 transformed = (mat * pt).normalized();
|
||
|
return Vector3(transformed.x(), transformed.y(), transformed.z());
|
||
|
}
|
||
|
|
||
|
Matrix4 operator*(const Matrix4 &a, const Matrix4 &b)
|
||
|
{
|
||
|
return Matrix4(a.data[0] * b.data[0] + a.data[4] * b.data[1] + a.data[8] * b.data[2] +
|
||
|
a.data[12] * b.data[3],
|
||
|
a.data[0] * b.data[4] + a.data[4] * b.data[5] + a.data[8] * b.data[6] +
|
||
|
a.data[12] * b.data[7],
|
||
|
a.data[0] * b.data[8] + a.data[4] * b.data[9] + a.data[8] * b.data[10] +
|
||
|
a.data[12] * b.data[11],
|
||
|
a.data[0] * b.data[12] + a.data[4] * b.data[13] + a.data[8] * b.data[14] +
|
||
|
a.data[12] * b.data[15],
|
||
|
a.data[1] * b.data[0] + a.data[5] * b.data[1] + a.data[9] * b.data[2] +
|
||
|
a.data[13] * b.data[3],
|
||
|
a.data[1] * b.data[4] + a.data[5] * b.data[5] + a.data[9] * b.data[6] +
|
||
|
a.data[13] * b.data[7],
|
||
|
a.data[1] * b.data[8] + a.data[5] * b.data[9] + a.data[9] * b.data[10] +
|
||
|
a.data[13] * b.data[11],
|
||
|
a.data[1] * b.data[12] + a.data[5] * b.data[13] + a.data[9] * b.data[14] +
|
||
|
a.data[13] * b.data[15],
|
||
|
a.data[2] * b.data[0] + a.data[6] * b.data[1] + a.data[10] * b.data[2] +
|
||
|
a.data[14] * b.data[3],
|
||
|
a.data[2] * b.data[4] + a.data[6] * b.data[5] + a.data[10] * b.data[6] +
|
||
|
a.data[14] * b.data[7],
|
||
|
a.data[2] * b.data[8] + a.data[6] * b.data[9] + a.data[10] * b.data[10] +
|
||
|
a.data[14] * b.data[11],
|
||
|
a.data[2] * b.data[12] + a.data[6] * b.data[13] + a.data[10] * b.data[14] +
|
||
|
a.data[14] * b.data[15],
|
||
|
a.data[3] * b.data[0] + a.data[7] * b.data[1] + a.data[11] * b.data[2] +
|
||
|
a.data[15] * b.data[3],
|
||
|
a.data[3] * b.data[4] + a.data[7] * b.data[5] + a.data[11] * b.data[6] +
|
||
|
a.data[15] * b.data[7],
|
||
|
a.data[3] * b.data[8] + a.data[7] * b.data[9] + a.data[11] * b.data[10] +
|
||
|
a.data[15] * b.data[11],
|
||
|
a.data[3] * b.data[12] + a.data[7] * b.data[13] + a.data[11] * b.data[14] +
|
||
|
a.data[15] * b.data[15]);
|
||
|
}
|
||
|
|
||
|
Matrix4 &operator*=(Matrix4 &a, const Matrix4 &b)
|
||
|
{
|
||
|
a = a * b;
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
Matrix4 operator*(const Matrix4 &a, float b)
|
||
|
{
|
||
|
Matrix4 ret(a);
|
||
|
for (size_t i = 0; i < 16; i++)
|
||
|
{
|
||
|
ret.data[i] *= b;
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
Matrix4 &operator*=(Matrix4 &a, float b)
|
||
|
{
|
||
|
for (size_t i = 0; i < 16; i++)
|
||
|
{
|
||
|
a.data[i] *= b;
|
||
|
}
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
Vector4 operator*(const Matrix4 &a, const Vector4 &b)
|
||
|
{
|
||
|
return Vector4(a.data[0] * b.x() + a.data[4] * b.y() + a.data[8] * b.z() + a.data[12] * b.w(),
|
||
|
a.data[1] * b.x() + a.data[5] * b.y() + a.data[9] * b.z() + a.data[13] * b.w(),
|
||
|
a.data[2] * b.x() + a.data[6] * b.y() + a.data[10] * b.z() + a.data[14] * b.w(),
|
||
|
a.data[3] * b.x() + a.data[7] * b.y() + a.data[11] * b.z() + a.data[15] * b.w());
|
||
|
}
|
||
|
|
||
|
bool operator==(const Matrix4 &a, const Matrix4 &b)
|
||
|
{
|
||
|
for (size_t i = 0; i < 16; i++)
|
||
|
{
|
||
|
if (a.data[i] != b.data[i])
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool operator!=(const Matrix4 &a, const Matrix4 &b)
|
||
|
{
|
||
|
return !(a == b);
|
||
|
}
|