aboutsummaryrefslogtreecommitdiff
path: root/dep/g3dlite/source/Matrix4.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dep/g3dlite/source/Matrix4.cpp')
-rw-r--r--dep/g3dlite/source/Matrix4.cpp291
1 files changed, 220 insertions, 71 deletions
diff --git a/dep/g3dlite/source/Matrix4.cpp b/dep/g3dlite/source/Matrix4.cpp
index fbc918f8f3e..f3b25ad5837 100644
--- a/dep/g3dlite/source/Matrix4.cpp
+++ b/dep/g3dlite/source/Matrix4.cpp
@@ -1,16 +1,16 @@
/**
- @file Matrix4.cpp
+ \file G3D/source/Matrix4.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2003-10-02
- @edited 2010-01-29
+ \created 2003-10-02
+ \edited 2012-02-19
*/
#include "G3D/platform.h"
#include "G3D/Matrix4.h"
#include "G3D/Matrix3.h"
+#include "G3D/Matrix2.h"
#include "G3D/Vector4.h"
#include "G3D/Vector3.h"
#include "G3D/BinaryInput.h"
@@ -24,11 +24,11 @@ namespace G3D {
Matrix4::Matrix4(const Any& any) {
- any.verifyName("Matrix4");
+ any.verifyNameBeginsWith("Matrix4", "CFrame", "CoordinateFrame");
any.verifyType(Any::ARRAY);
- const std::string& name = toLower(any.name());
- if (name == "matrix4") {
+ const std::string& name = any.name();
+ if (name == "Matrix4") {
any.verifySize(16);
for (int r = 0; r < 4; ++r) {
@@ -36,26 +36,43 @@ Matrix4::Matrix4(const Any& any) {
elt[r][c] = any[r * 4 + c];
}
}
- } else if (name == "matrix4::scale") {
+ } else if (name == "Matrix4::scale") {
if (any.size() == 1) {
- *this = scale(any[0].number());
+ *this = scale(any[0].floatValue());
} else if (any.size() == 3) {
*this = scale(any[0], any[1], any[2]);
} else {
any.verify(false, "Matrix4::scale() takes either 1 or 3 arguments");
}
- } else if (name == "matrix4::translation") {
+ } else if (name == "Matrix4::rollDegrees") {
+ any.verifySize(1);
+ *this = rollDegrees(any[0].floatValue());
+ } else if (name == "Matrix4::yawDegrees") {
+ any.verifySize(1);
+ *this = yawDegrees(any[0].floatValue());
+ } else if (name == "Matrix4::pitchDegrees") {
+ any.verifySize(1);
+ *this = pitchDegrees(any[0].floatValue());
+ } else if (name == "Matrix4::translation") {
if (any.size() == 3) {
*this = translation(any[0], any[1], any[2]);
} else {
- any.verify(false, "Matrix4::translation() takes either 1 or 3 arguments");
- } } else {
+ any.verify(false, "Matrix4::translation() requires 3 arguments");
+ }
+ } else if (name == "Matrix4::diagonal") {
+ any.verifySize(4);
+ *this = diagonal(any[0], any[1], any[2], any[3]);
+ } else if (name == "Matrix4::identity") {
+ *this = identity();
+ } else if (beginsWith(name, "CFrame") || beginsWith(name, "CoordinateFrame")) {
+ *this = CFrame(any);
+ } else {
any.verify(false, "Expected Matrix4 constructor");
}
}
-Matrix4::operator Any() const {
+Any Matrix4::toAny() const {
Any any(Any::ARRAY, "Matrix4");
any.resize(16);
for (int r = 0; r < 4; ++r) {
@@ -121,6 +138,12 @@ Matrix3 Matrix4::upper3x3() const {
}
+Matrix2 Matrix4::upper2x2() const {
+ return Matrix2(elt[0][0], elt[0][1],
+ elt[1][0], elt[1][1]);
+}
+
+
Matrix4 Matrix4::orthogonalProjection(
const class Rect2D& rect,
float nearval,
@@ -164,59 +187,59 @@ Matrix4 Matrix4::orthogonalProjection(
Matrix4 Matrix4::perspectiveProjection(
- float left,
- float right,
- float bottom,
- float top,
- float nearval,
- float farval,
- float upDirection) {
-
- float x, y, a, b, c, d;
-
- x = (2.0f*nearval) / (right-left);
- y = (2.0f*nearval) / (top-bottom);
+ double left,
+ double right,
+ double bottom,
+ double top,
+ double nearval,
+ double farval,
+ float upDirection) {
+
+ double x, y, a, b, c, d;
+
+ x = (2.0*nearval) / (right-left);
+ y = (2.0*nearval) / (top-bottom);
a = (right+left) / (right-left);
b = (top+bottom) / (top-bottom);
- if (farval >= finf()) {
+ if (farval >= inf()) {
// Infinite view frustum
- c = -1.0f;
- d = -2.0f * nearval;
+ c = -1.0;
+ d = -2.0 * nearval;
} else {
c = -(farval+nearval) / (farval-nearval);
- d = -(2.0f*farval*nearval) / (farval-nearval);
+ d = -(2.0*farval*nearval) / (farval-nearval);
}
- debugAssertM(abs(upDirection) == 1.0f, "upDirection must be -1 or +1");
+ debugAssertM(abs(upDirection) == 1.0, "upDirection must be -1 or +1");
y *= upDirection;
b *= upDirection;
return Matrix4(
- x, 0, a, 0,
- 0, y, b, 0,
- 0, 0, c, d,
+ (float)x, 0, (float)a, 0,
+ 0, (float)y, (float)b, 0,
+ 0, 0, (float)c, (float)d,
0, 0, -1, 0);
}
void Matrix4::getPerspectiveProjectionParameters(
- float& left,
- float& right,
- float& bottom,
- float& top,
- float& nearval,
- float& farval,
+ double& left,
+ double& right,
+ double& bottom,
+ double& top,
+ double& nearval,
+ double& farval,
float upDirection) const {
debugAssertM(abs(upDirection) == 1.0f, "upDirection must be -1 or +1");
- float x = elt[0][0];
- float y = elt[1][1] * upDirection;
- float a = elt[0][2];
- float b = elt[1][2] * upDirection;
- float c = elt[2][2];
- float d = elt[2][3];
+ double x = elt[0][0];
+ double y = elt[1][1] * upDirection;
+ double a = elt[0][2];
+ double b = elt[1][2] * upDirection;
+ double c = elt[2][2];
+ double d = elt[2][3];
// Verify that this really is a projection matrix
debugAssertM(elt[3][2] == -1, "Not a projection matrix");
@@ -232,18 +255,18 @@ void Matrix4::getPerspectiveProjectionParameters(
if (c == -1) {
farval = finf();
- nearval = -d / 2.0f;
+ nearval = -d / 2.0;
} else {
- nearval = d * ((c - 1.0f) / (c + 1.0f) - 1.0f) / (-2.0f * (c - 1.0f) / (c + 1.0f));
- farval = nearval * ((c - 1.0f) / (c + 1.0f));
+ nearval = d * ((c - 1.0) / (c + 1.0) - 1.0) / (-2.0 * (c - 1.0) / (c + 1.0));
+ farval = nearval * ((c - 1.0) / (c + 1.0));
}
- left = (a - 1.0f) * nearval / x;
- right = 2.0f * nearval / x + left;
+ left = (a - 1.0) * nearval / x;
+ right = 2.0 * nearval / x + left;
- bottom = (b - 1.0f) * nearval / y;
- top = 2.0f * nearval / y + bottom;
+ bottom = (b - 1.0) * nearval / y;
+ top = 2.0 * nearval / y + bottom;
}
@@ -401,7 +424,7 @@ bool Matrix4::operator==(const Matrix4& other) const {
float Matrix4::determinant() const {
// Determinant is the dot product of the first row and the first row
// of cofactors (i.e. the first col of the adjoint matrix)
- return cofactor().row(0).dot(row(0));
+ return cofactor().row(0).dot(row(0));
}
@@ -417,14 +440,14 @@ Matrix4 Matrix4::inverse() const {
// Determinant is the dot product of the first row and the first row
// of cofactors (i.e. the first col of the adjoint matrix)
- float det = A.column(0).dot(row(0));
+ float det = A.column(0).dot(row(0));
- return A * (1.0f / det);
+ return A * (1.0f / det);
}
Matrix4 Matrix4::cofactor() const {
- Matrix4 out;
+ Matrix4 out;
// We'll use i to incrementally compute -1 ^ (r+c)
int i = 1;
@@ -482,19 +505,19 @@ float Matrix4::subDeterminant(int excludeRow, int excludeCol) const {
CoordinateFrame Matrix4::approxCoordinateFrame() const {
- CoordinateFrame cframe;
+ CoordinateFrame cframe;
- for (int r = 0; r < 3; ++r) {
- for (int c = 0; c < 3; ++c) {
- cframe.rotation[r][c] = elt[r][c];
- }
- cframe.translation[r] = elt[r][3];
- }
+ for (int r = 0; r < 3; ++r) {
+ for (int c = 0; c < 3; ++c) {
+ cframe.rotation[r][c] = elt[r][c];
+ }
+ cframe.translation[r] = elt[r][3];
+ }
- // Ensure that the rotation matrix is orthonormal
- cframe.rotation.orthonormalize();
+ // Ensure that the rotation matrix is orthonormal
+ cframe.rotation.orthonormalize();
- return cframe;
+ return cframe;
}
@@ -517,12 +540,138 @@ void Matrix4::deserialize(class BinaryInput& b) {
std::string Matrix4::toString() const {
return G3D::format("[%g, %g, %g, %g; %g, %g, %g, %g; %g, %g, %g, %g; %g, %g, %g, %g]",
- elt[0][0], elt[0][1], elt[0][2], elt[0][3],
- elt[1][0], elt[1][1], elt[1][2], elt[1][3],
- elt[2][0], elt[2][1], elt[2][2], elt[2][3],
- elt[3][0], elt[3][1], elt[3][2], elt[3][3]);
+ elt[0][0], elt[0][1], elt[0][2], elt[0][3],
+ elt[1][0], elt[1][1], elt[1][2], elt[1][3],
+ elt[2][0], elt[2][1], elt[2][2], elt[2][3],
+ elt[3][0], elt[3][1], elt[3][2], elt[3][3]);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+Matrix4float64::Matrix4float64(const Matrix4& m) {
+ for (int r = 0; r < 4; ++r) {
+ for (int c = 0; c < 4; ++c) {
+ elt[r][c] = m[r][c];
+ }
+ }
+}
+
+
+Matrix4float64::Matrix4float64() {
+ for (int r = 0; r < 4; ++r) {
+ for (int c = 0; c < 4; ++c) {
+ elt[r][c] = 0.0;
+ }
+ }
+}
+
+
+Matrix4float64::Matrix4float64
+ (double r1c1, double r1c2, double r1c3, double r1c4,
+ double r2c1, double r2c2, double r2c3, double r2c4,
+ double r3c1, double r3c2, double r3c3, double r3c4,
+ double r4c1, double r4c2, double r4c3, double r4c4) {
+ elt[0][0] = r1c1; elt[0][1] = r1c2; elt[0][2] = r1c3; elt[0][3] = r1c4;
+ elt[1][0] = r2c1; elt[1][1] = r2c2; elt[1][2] = r2c3; elt[1][3] = r2c4;
+ elt[2][0] = r3c1; elt[2][1] = r3c2; elt[2][2] = r3c3; elt[2][3] = r3c4;
+ elt[3][0] = r4c1; elt[3][1] = r4c2; elt[3][2] = r4c3; elt[3][3] = r4c4;
+}
+
+
+const Matrix4float64& Matrix4float64::identity() {
+ static Matrix4float64 m(
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1);
+ return m;
+}
+
+
+const Matrix4float64& Matrix4float64::zero() {
+ static Matrix4float64 m;
+ return m;
+}
+
+
+bool Matrix4float64::operator!=(const Matrix4float64& other) const {
+ return ! (*this == other);
+}
+
+
+bool Matrix4float64::operator==(const Matrix4float64& other) const {
+
+ // If the bit patterns are identical, they must be
+ // the same matrix. If not, they *might* still have
+ // equal elements due to floating point weirdness.
+ if (memcmp(this, &other, sizeof(Matrix4float64) == 0)) {
+ return true;
+ }
+
+ for (int r = 0; r < 4; ++r) {
+ for (int c = 0; c < 4; ++c) {
+ if (elt[r][c] != other.elt[r][c]) {
+ return false;
+ }
+ }
+ }
+
+ return true;
}
+
+Vector4 Matrix4float64::operator*(const Vector4& vector) const {
+ Vector4 result;
+ for (int r = 0; r < 4; ++r) {
+ double sum = 0;
+ for (int c = 0; c < 4; ++c) {
+ sum += elt[r][c] * vector[c];
+ }
+ result[r] = (float)sum;
+ }
+
+ return result;
+}
+
+
+Matrix4float64 Matrix4float64::perspectiveProjection(
+ double left,
+ double right,
+ double bottom,
+ double top,
+ double nearval,
+ double farval,
+ float upDirection) {
+ double x, y, a, b, c, d;
+
+ x = (2.0*nearval) / (right-left);
+ y = (2.0*nearval) / (top-bottom);
+ a = (right+left) / (right-left);
+ b = (top+bottom) / (top-bottom);
+
+ if (farval >= inf()) {
+ // Infinite view frustum
+ c = -1.0;
+ d = -2.0 * nearval;
+ } else {
+ c = -(farval+nearval) / (farval-nearval);
+ d = -(2.0*farval*nearval) / (farval-nearval);
+ }
+
+ debugAssertM(abs(upDirection) == 1.0, "upDirection must be -1 or +1");
+ y *= upDirection;
+ b *= upDirection;
+
+ return Matrix4float64(
+ (float)x, 0, (float)a, 0,
+ 0, (float)y, (float)b, 0,
+ 0, 0, (float)c, (float)d,
+ 0, 0, -1, 0);
+}
+
+
} // namespace