diff options
Diffstat (limited to 'dev/MinGfx/src/matrix4.h')
-rw-r--r-- | dev/MinGfx/src/matrix4.h | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/dev/MinGfx/src/matrix4.h b/dev/MinGfx/src/matrix4.h new file mode 100644 index 0000000..4abf29f --- /dev/null +++ b/dev/MinGfx/src/matrix4.h @@ -0,0 +1,260 @@ +/* + This file is part of the MinGfx Project. + + Copyright (c) 2017,2018 Regents of the University of Minnesota. + All Rights Reserved. + + Original Author(s) of this File: + Dan Keefe, 2017, University of Minnesota + + Author(s) of Significant Updates/Modifications to the File: + ... + */ + +#ifndef SRC_MATRIX4_H_ +#define SRC_MATRIX4_H_ + +#include <iostream> + +#include "point3.h" +#include "vector3.h" +#include "ray.h" + + +namespace mingfx { + + +/** A 4x4 transformation matrix stored internally as an array of floats in + column-major order so as to be compatible with OpenGL. Examples: + ~~~ + // constructing various matrices: + Matrix4 T = Matrix4::Translation(Vector3(1,0,0)); + Matrix4 S = Matrix4::Scale(Vector3(2,2,2)); + Matrix4 R = Matrix4::RotateX(GfxMath::toRadians(45.0)); + + // compose matrices together by multiplication + Matrix4 M = T * R * S; + Matrix4 Minv = M.Inverse(); + + // transforming points, vectors, etc. + Point3 p1(1,1,1); + Point3 p2 = M * p1; + + Vector3 v1(1,1,1); + Vector3 v2 = M * v1; + + Ray r1(p1, v1); + Ray r2 = M * r1; + ~~~ + */ +class Matrix4 { +public: + + /// The default constructor creates an identity matrix: + Matrix4(); + + /// Constructs a matrix given from an array of 16 floats in OpenGL matrix format + /// (i.e., column major). + Matrix4(const float* a); + + /// Constructs a matrix given from a vector of 16 floats in OpenGL matrix format + /// (i.e., column major). + Matrix4(const std::vector<float> &a); + + /// Copy constructor + Matrix4(const Matrix4& m2); + + /// Destructor + virtual ~Matrix4(); + + /// Check for "equality", taking floating point imprecision into account + bool operator==(const Matrix4& m2) const; + + /// Check for "inequality", taking floating point imprecision into account + bool operator!=(const Matrix4& m2) const; + + /// Matrix assignment operator + Matrix4& operator=(const Matrix4& m2); + + + /// Returns a pointer to the raw data array used to store the matrix. This + /// is a 1D array of 16-elements stored in column-major order. + const float * value_ptr() const; + + /// Accesses the ith element of the raw data array used to store the matrix. + /// This is a 1D array of 16-elements stored in column-major order. + float operator[](const int i) const; + + /// Accesses the ith element of the raw data array used to store the matrix. + /// This is a 1D array of 16-elements stored in column-major order. + float& operator[](const int i); + + /// Access an individual element of the array using the syntax: + /// Matrix4 mat; float row1col2 = mat(1,2); + float operator()(const int row, const int col) const; + + /// Access an individual element of the array using the syntax: + /// Matrix4 mat; mat(1,2) = 1.0; + float& operator()(const int row, const int col); + + + /// Returns the c-th column of the matrix as a Vector type, e.g.,: + /// Vector3 xAxis = mat.getColumnAsVector3(0); + /// Vector3 yAxis = mat.getColumnAsVector3(1); + /// Vector3 zAxis = mat.getColumnAsVector3(2); + Vector3 ColumnToVector3(int c) const; + + /// Returns the c-th column of the matrix as a Vector type, e.g.,: + /// Point3 pos = mat.getColumnAsPoint3(3); + Point3 ColumnToPoint3(int c) const; + + std::vector<float> ToVector() const; + + + // --- Static Constructors for Special Matrices --- + + /** Returns a matrix constructed from individual elements passed in row major + order so that the matrix looks "correct" on the screen as you write this + constructor on 4 lines of code as below. Note the that internally the + matrix constructed will be stored in a 16 element column major array to + be consistent with OpenGL. + */ + static Matrix4 FromRowMajorElements( + const float r1c1, const float r1c2, const float r1c3, const float r1c4, + const float r2c1, const float r2c2, const float r2c3, const float r2c4, + const float r3c1, const float r3c2, const float r3c3, const float r3c4, + const float r4c1, const float r4c2, const float r4c3, const float r4c4 + ); + + // --- Model Transformations --- + + /// Returns the scale matrix described by the vector + static Matrix4 Scale(const Vector3 &v); + + /// Returns the translation matrix described by the vector + static Matrix4 Translation(const Vector3 &v); + + /// Returns the rotation matrix about the x axis by the specified angle + static Matrix4 RotationX(const float radians); + + /// Returns the rotation matrix about the y axis by the specified angle + static Matrix4 RotationY(const float radians); + + /// Returns the rotation matrix about the z axis by the specified angle + static Matrix4 RotationZ(const float radians); + + /// Returns the rotation matrix around the vector v placed at point p, rotate by angle a + static Matrix4 Rotation(const Point3 &p, const Vector3 &v, const float a); + + /// Creates a transformation matrix that maps a coordinate space, *a*, defined + /// one point, *a_p*, and two vectors, *a_v1* and *a_v2*, to a new coordinate + /// space, *b*, also defined by one point, *b_p*, and two vectors, *b_v1* and + /// *b_v2*. The transformation will thus include both some rotation and some + /// translation. Pseudocode example of aligning a billboard defined in the + /// XY plane with a normal in the +Z direction and that rotates around the Y + /// axis with a camera: + /// ~~~ + /// // define a coordiante space for a canonical billboard geometry defined + /// // right at the origin. + /// Point3 a_p = Point3(0,0,0); // billboard's initial base position + /// Vector3 a_v1 = Vector3(0,1,0); // billboard's initial up direction + /// Vector3 a_v2 = Vector3(0,0,1); // billboard's initial normal direction + /// + /// // define a coordinate space for where we want this billboard to go and + /// // the direction it should be facing + /// Point3 b_p = desired_base_pos; // new position for the billboard + /// Vector3 b_v1 = Vector3(0,1,0); // +Y is still up, doesn't change + /// Vector3 b_v2 = (camera.eye() - desired_base_pos); // the normal should point toward the camera + /// b_v2[1] = 0.0; // with 0 change in Y so the billboard does not tilt + /// b_v2.Normalize(); // convert to a unit vector + /// + /// Matrix4 billboard_model_matrix = Matrix4::Align(a_p, a_v1, a_v2, b_p, b_v1, b_v2); + /// ~~~ + static Matrix4 Align(const Point3 &a_p, const Vector3 &a_v1, const Vector3 &a_v2, + const Point3 &b_p, const Vector3 &b_v1, const Vector3 &b_v2); + + + // --- View Matrices --- + + /** Returns a view matrix that centers the camera at the 'eye' position and + orients it to look at the desired 'target' point with the top of the + screen pointed as closely as possible in the direction of the 'up' vector. + */ + static Matrix4 LookAt(Point3 eye, Point3 target, Vector3 up); + + // --- Projection Matrices --- + + /// Returns a perspective projection matrix equivalent to the one gluPerspective + /// creates. + static Matrix4 Perspective(float fov_y_in_degrees, float aspect_ratio, float near_plane_dist, float far_plane_dist); + + /// Returns a projection matrix equivalent the one glFrustum creates + static Matrix4 Frustum(float left, float right, float bottom, float top, float near_plane_dist, float far_plane_dist); + + // --- Inverse, Transposeand Other General Matrix Functions --- + + /// Returns the inverse of the 4x4 matrix if it is nonsingular. If it is + /// singular, then returns the identity matrix. + Matrix4 Inverse() const; + + /** Returns an orthonormal version of the matrix, i.e., guarantees that the + rotational component of the matrix is built from column vectors that are + all unit vectors and orthogonal to each other. + */ + Matrix4 Orthonormal() const; + + /// Returns the transpose of the matrix + Matrix4 Transpose() const; + + /// Returns the determinant of the 3x3 matrix formed by excluding the specified + /// row and column from the 4x4 matrix. + float SubDeterminant(int exclude_row, int exclude_col) const; + + /// Returns the cofactor matrix. + Matrix4 Cofactor() const; + + /// Returns the determinant of the 4x4 matrix + float Determinant() const; + + + +private: + float m[16]; +}; + + + +// ---------- Operator Overloads for Working with Points, Vectors, & Matrices ---------- + + +// --- Matrix multiplication for Points, Vectors, & Matrices --- + +/// Multiply matrix and scalar, returns the new matrix +Matrix4 operator*(const Matrix4& m, const float& s); + +/// Multiply matrix and scalar, returns the new matrix +Matrix4 operator*(const float& s, const Matrix4& m); + +/// Multiply matrix and point, returns the new point +Point3 operator*(const Matrix4& m, const Point3& p); + +/// Multiply matrix and vector, returns the new vector +Vector3 operator*(const Matrix4& m, const Vector3& v); + +/// Multiply two matrices, returns the result +Matrix4 operator*(const Matrix4& m1, const Matrix4& m2); + + + +/// Multiply matrix and the point and vector portions of the ray, returns the new ray +Ray operator*(const Matrix4& m, const Ray& r); + +// --- Stream operators --- + +std::ostream & operator<< ( std::ostream &os, const Matrix4 &m); +std::istream & operator>> ( std::istream &is, Matrix4 &m); + + +} // end namespace + +#endif |