summaryrefslogtreecommitdiff
path: root/src/math/Matrix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/math/Matrix.cpp')
-rw-r--r--src/math/Matrix.cpp531
1 files changed, 531 insertions, 0 deletions
diff --git a/src/math/Matrix.cpp b/src/math/Matrix.cpp
new file mode 100644
index 0000000..c0d909c
--- /dev/null
+++ b/src/math/Matrix.cpp
@@ -0,0 +1,531 @@
+#include "common.h"
+
+CMatrix::CMatrix(void)
+{
+ m_attachment = nil;
+ m_hasRwMatrix = false;
+}
+
+CMatrix::CMatrix(CMatrix const &m)
+{
+ m_attachment = nil;
+ m_hasRwMatrix = false;
+ *this = m;
+}
+
+CMatrix::CMatrix(RwMatrix *matrix, bool owner)
+{
+ m_attachment = nil;
+ Attach(matrix, owner);
+}
+
+CMatrix::~CMatrix(void)
+{
+ if (m_hasRwMatrix && m_attachment)
+ RwMatrixDestroy(m_attachment);
+}
+
+void
+CMatrix::Attach(RwMatrix *matrix, bool owner)
+{
+#ifdef FIX_BUGS
+ if (m_attachment && m_hasRwMatrix)
+#else
+ if (m_hasRwMatrix && m_attachment)
+#endif
+ RwMatrixDestroy(m_attachment);
+ m_attachment = matrix;
+ m_hasRwMatrix = owner;
+ Update();
+}
+
+void
+CMatrix::AttachRW(RwMatrix *matrix, bool owner)
+{
+ if (m_hasRwMatrix && m_attachment)
+ RwMatrixDestroy(m_attachment);
+ m_attachment = matrix;
+ m_hasRwMatrix = owner;
+ UpdateRW();
+}
+
+void
+CMatrix::Detach(void)
+{
+ if (m_hasRwMatrix && m_attachment)
+ RwMatrixDestroy(m_attachment);
+ m_attachment = nil;
+}
+
+void
+CMatrix::Update(void)
+{
+ GetRight() = m_attachment->right;
+ GetForward() = m_attachment->up;
+ GetUp() = m_attachment->at;
+ GetPosition() = m_attachment->pos;
+}
+
+void
+CMatrix::UpdateRW(void)
+{
+ if (m_attachment) {
+ m_attachment->right = GetRight();
+ m_attachment->up = GetForward();
+ m_attachment->at = GetUp();
+ m_attachment->pos = GetPosition();
+ RwMatrixUpdate(m_attachment);
+ }
+}
+
+void
+CMatrix::operator=(CMatrix const &rhs)
+{
+ memcpy(this, &rhs, sizeof(f));
+ if (m_attachment)
+ UpdateRW();
+}
+
+void
+CMatrix::CopyOnlyMatrix(const CMatrix &other)
+{
+ memcpy(this, &other, sizeof(f));
+}
+
+CMatrix &
+CMatrix::operator+=(CMatrix const &rhs)
+{
+ GetRight() += rhs.GetRight();
+ GetForward() += rhs.GetForward();
+ GetUp() += rhs.GetUp();
+ GetPosition() += rhs.GetPosition();
+ return *this;
+}
+
+void
+CMatrix::SetUnity(void)
+{
+ rx = 1.0f;
+ ry = 0.0f;
+ rz = 0.0f;
+ fx = 0.0f;
+ fy = 1.0f;
+ fz = 0.0f;
+ ux = 0.0f;
+ uy = 0.0f;
+ uz = 1.0f;
+ px = 0.0f;
+ py = 0.0f;
+ pz = 0.0f;
+}
+
+void
+CMatrix::ResetOrientation(void)
+{
+ rx = 1.0f;
+ ry = 0.0f;
+ rz = 0.0f;
+ fx = 0.0f;
+ fy = 1.0f;
+ fz = 0.0f;
+ ux = 0.0f;
+ uy = 0.0f;
+ uz = 1.0f;
+}
+
+void
+CMatrix::SetScale(float s)
+{
+ rx = s;
+ ry = 0.0f;
+ rz = 0.0f;
+
+ fx = 0.0f;
+ fy = s;
+ fz = 0.0f;
+
+ ux = 0.0f;
+ uy = 0.0f;
+ uz = s;
+
+ px = 0.0f;
+ py = 0.0f;
+ pz = 0.0f;
+}
+
+void
+CMatrix::SetTranslate(float x, float y, float z)
+{
+ rx = 1.0f;
+ ry = 0.0f;
+ rz = 0.0f;
+
+ fx = 0.0f;
+ fy = 1.0f;
+ fz = 0.0f;
+
+ ux = 0.0f;
+ uy = 0.0f;
+ uz = 1.0f;
+
+ px = x;
+ py = y;
+ pz = z;
+}
+
+void
+CMatrix::SetRotateXOnly(float angle)
+{
+ float c = Cos(angle);
+ float s = Sin(angle);
+
+ rx = 1.0f;
+ ry = 0.0f;
+ rz = 0.0f;
+
+ fx = 0.0f;
+ fy = c;
+ fz = s;
+
+ ux = 0.0f;
+ uy = -s;
+ uz = c;
+}
+
+void
+CMatrix::SetRotateYOnly(float angle)
+{
+ float c = Cos(angle);
+ float s = Sin(angle);
+
+ rx = c;
+ ry = 0.0f;
+ rz = -s;
+
+ fx = 0.0f;
+ fy = 1.0f;
+ fz = 0.0f;
+
+ ux = s;
+ uy = 0.0f;
+ uz = c;
+}
+
+void
+CMatrix::SetRotateZOnly(float angle)
+{
+ float c = Cos(angle);
+ float s = Sin(angle);
+
+ rx = c;
+ ry = s;
+ rz = 0.0f;
+
+ fx = -s;
+ fy = c;
+ fz = 0.0f;
+
+ ux = 0.0f;
+ uy = 0.0f;
+ uz = 1.0f;
+}
+
+void
+CMatrix::SetRotateX(float angle)
+{
+ SetRotateXOnly(angle);
+ px = 0.0f;
+ py = 0.0f;
+ pz = 0.0f;
+}
+
+
+void
+CMatrix::SetRotateY(float angle)
+{
+ SetRotateYOnly(angle);
+ px = 0.0f;
+ py = 0.0f;
+ pz = 0.0f;
+}
+
+void
+CMatrix::SetRotateZ(float angle)
+{
+ SetRotateZOnly(angle);
+ px = 0.0f;
+ py = 0.0f;
+ pz = 0.0f;
+}
+
+void
+CMatrix::SetRotate(float xAngle, float yAngle, float zAngle)
+{
+ float cX = Cos(xAngle);
+ float sX = Sin(xAngle);
+ float cY = Cos(yAngle);
+ float sY = Sin(yAngle);
+ float cZ = Cos(zAngle);
+ float sZ = Sin(zAngle);
+
+ rx = cZ * cY - (sZ * sX) * sY;
+ ry = (cZ * sX) * sY + sZ * cY;
+ rz = -cX * sY;
+
+ fx = -sZ * cX;
+ fy = cZ * cX;
+ fz = sX;
+
+ ux = (sZ * sX) * cY + cZ * sY;
+ uy = sZ * sY - (cZ * sX) * cY;
+ uz = cX * cY;
+
+ px = 0.0f;
+ py = 0.0f;
+ pz = 0.0f;
+}
+
+void
+CMatrix::RotateX(float x)
+{
+ float c = Cos(x);
+ float s = Sin(x);
+
+ float ry = this->ry;
+ float rz = this->rz;
+ float uy = this->fy;
+ float uz = this->fz;
+ float ay = this->uy;
+ float az = this->uz;
+ float py = this->py;
+ float pz = this->pz;
+
+ this->ry = c * ry - s * rz;
+ this->rz = c * rz + s * ry;
+ this->fy = c * uy - s * uz;
+ this->fz = c * uz + s * uy;
+ this->uy = c * ay - s * az;
+ this->uz = c * az + s * ay;
+ this->py = c * py - s * pz;
+ this->pz = c * pz + s * py;
+}
+
+void
+CMatrix::RotateY(float y)
+{
+ float c = Cos(y);
+ float s = Sin(y);
+
+ float rx = this->rx;
+ float rz = this->rz;
+ float ux = this->fx;
+ float uz = this->fz;
+ float ax = this->ux;
+ float az = this->uz;
+ float px = this->px;
+ float pz = this->pz;
+
+ this->rx = c * rx + s * rz;
+ this->rz = c * rz - s * rx;
+ this->fx = c * ux + s * uz;
+ this->fz = c * uz - s * ux;
+ this->ux = c * ax + s * az;
+ this->uz = c * az - s * ax;
+ this->px = c * px + s * pz;
+ this->pz = c * pz - s * px;
+}
+
+void
+CMatrix::RotateZ(float z)
+{
+ float c = Cos(z);
+ float s = Sin(z);
+
+ float ry = this->ry;
+ float rx = this->rx;
+ float uy = this->fy;
+ float ux = this->fx;
+ float ay = this->uy;
+ float ax = this->ux;
+ float py = this->py;
+ float px = this->px;
+
+ this->rx = c * rx - s * ry;
+ this->ry = c * ry + s * rx;
+ this->fx = c * ux - s * uy;
+ this->fy = c * uy + s * ux;
+ this->ux = c * ax - s * ay;
+ this->uy = c * ay + s * ax;
+ this->px = c * px - s * py;
+ this->py = c * py + s * px;
+
+}
+
+void
+CMatrix::Rotate(float x, float y, float z)
+{
+ float cX = Cos(x);
+ float sX = Sin(x);
+ float cY = Cos(y);
+ float sY = Sin(y);
+ float cZ = Cos(z);
+ float sZ = Sin(z);
+
+ float rx = this->rx;
+ float ry = this->ry;
+ float rz = this->rz;
+ float ux = this->fx;
+ float uy = this->fy;
+ float uz = this->fz;
+ float ax = this->ux;
+ float ay = this->uy;
+ float az = this->uz;
+ float px = this->px;
+ float py = this->py;
+ float pz = this->pz;
+
+ float x1 = cZ * cY - (sZ * sX) * sY;
+ float x2 = (cZ * sX) * sY + sZ * cY;
+ float x3 = -cX * sY;
+ float y1 = -sZ * cX;
+ float y2 = cZ * cX;
+ float y3 = sX;
+ float z1 = (sZ * sX) * cY + cZ * sY;
+ float z2 = sZ * sY - (cZ * sX) * cY;
+ float z3 = cX * cY;
+
+ this->rx = x1 * rx + y1 * ry + z1 * rz;
+ this->ry = x2 * rx + y2 * ry + z2 * rz;
+ this->rz = x3 * rx + y3 * ry + z3 * rz;
+ this->fx = x1 * ux + y1 * uy + z1 * uz;
+ this->fy = x2 * ux + y2 * uy + z2 * uz;
+ this->fz = x3 * ux + y3 * uy + z3 * uz;
+ this->ux = x1 * ax + y1 * ay + z1 * az;
+ this->uy = x2 * ax + y2 * ay + z2 * az;
+ this->uz = x3 * ax + y3 * ay + z3 * az;
+ this->px = x1 * px + y1 * py + z1 * pz;
+ this->py = x2 * px + y2 * py + z2 * pz;
+ this->pz = x3 * px + y3 * py + z3 * pz;
+}
+
+CMatrix &
+CMatrix::operator*=(CMatrix const &rhs)
+{
+ // TODO: VU0 code
+ *this = *this * rhs;
+ return *this;
+}
+
+void
+CMatrix::Reorthogonalise(void)
+{
+ CVector &r = GetRight();
+ CVector &f = GetForward();
+ CVector &u = GetUp();
+ u = CrossProduct(r, f);
+ u.Normalise();
+ r = CrossProduct(f, u);
+ r.Normalise();
+ f = CrossProduct(u, r);
+}
+
+CMatrix
+operator*(const CMatrix &m1, const CMatrix &m2)
+{
+ // TODO: VU0 code
+ CMatrix out;
+ out.rx = m1.rx * m2.rx + m1.fx * m2.ry + m1.ux * m2.rz;
+ out.ry = m1.ry * m2.rx + m1.fy * m2.ry + m1.uy * m2.rz;
+ out.rz = m1.rz * m2.rx + m1.fz * m2.ry + m1.uz * m2.rz;
+ out.fx = m1.rx * m2.fx + m1.fx * m2.fy + m1.ux * m2.fz;
+ out.fy = m1.ry * m2.fx + m1.fy * m2.fy + m1.uy * m2.fz;
+ out.fz = m1.rz * m2.fx + m1.fz * m2.fy + m1.uz * m2.fz;
+ out.ux = m1.rx * m2.ux + m1.fx * m2.uy + m1.ux * m2.uz;
+ out.uy = m1.ry * m2.ux + m1.fy * m2.uy + m1.uy * m2.uz;
+ out.uz = m1.rz * m2.ux + m1.fz * m2.uy + m1.uz * m2.uz;
+ out.px = m1.rx * m2.px + m1.fx * m2.py + m1.ux * m2.pz + m1.px;
+ out.py = m1.ry * m2.px + m1.fy * m2.py + m1.uy * m2.pz + m1.py;
+ out.pz = m1.rz * m2.px + m1.fz * m2.py + m1.uz * m2.pz + m1.pz;
+ return out;
+}
+
+CMatrix &
+Invert(const CMatrix &src, CMatrix &dst)
+{
+ // TODO: VU0 code
+ dst.f[3][0] = dst.f[3][1] = dst.f[3][2] = 0.0f;
+
+ dst.f[0][0] = src.f[0][0];
+ dst.f[0][1] = src.f[1][0];
+ dst.f[0][2] = src.f[2][0];
+
+ dst.f[1][0] = src.f[0][1];
+ dst.f[1][1] = src.f[1][1];
+ dst.f[1][2] = src.f[2][1];
+
+ dst.f[2][0] = src.f[0][2];
+ dst.f[2][1] = src.f[1][2];
+ dst.f[2][2] = src.f[2][2];
+
+
+ dst.f[3][0] += dst.f[0][0] * src.f[3][0];
+ dst.f[3][1] += dst.f[0][1] * src.f[3][0];
+ dst.f[3][2] += dst.f[0][2] * src.f[3][0];
+
+ dst.f[3][0] += dst.f[1][0] * src.f[3][1];
+ dst.f[3][1] += dst.f[1][1] * src.f[3][1];
+ dst.f[3][2] += dst.f[1][2] * src.f[3][1];
+
+ dst.f[3][0] += dst.f[2][0] * src.f[3][2];
+ dst.f[3][1] += dst.f[2][1] * src.f[3][2];
+ dst.f[3][2] += dst.f[2][2] * src.f[3][2];
+
+ dst.f[3][0] = -dst.f[3][0];
+ dst.f[3][1] = -dst.f[3][1];
+ dst.f[3][2] = -dst.f[3][2];
+
+ return dst;
+}
+
+void
+CMatrix::CopyToRwMatrix(RwMatrix* matrix)
+{
+ matrix->right = GetRight();
+ matrix->up = GetForward();
+ matrix->at = GetUp();
+ matrix->pos = GetPosition();
+ RwMatrixUpdate(matrix);
+}
+
+CMatrix
+Invert(const CMatrix &matrix)
+{
+ CMatrix inv;
+ return Invert(matrix, inv);
+}
+
+void
+CCompressedMatrixNotAligned::CompressFromFullMatrix(CMatrix &other)
+{
+ m_rightX = 127.0f * other.GetRight().x;
+ m_rightY = 127.0f * other.GetRight().y;
+ m_rightZ = 127.0f * other.GetRight().z;
+ m_upX = 127.0f * other.GetForward().x;
+ m_upY = 127.0f * other.GetForward().y;
+ m_upZ = 127.0f * other.GetForward().z;
+ m_vecPos = other.GetPosition();
+}
+
+void
+CCompressedMatrixNotAligned::DecompressIntoFullMatrix(CMatrix &other)
+{
+ other.GetRight().x = m_rightX / 127.0f;
+ other.GetRight().y = m_rightY / 127.0f;
+ other.GetRight().z = m_rightZ / 127.0f;
+ other.GetForward().x = m_upX / 127.0f;
+ other.GetForward().y = m_upY / 127.0f;
+ other.GetForward().z = m_upZ / 127.0f;
+ other.GetUp() = CrossProduct(other.GetRight(), other.GetForward());
+ other.GetPosition() = m_vecPos;
+ other.Reorthogonalise();
+} \ No newline at end of file