/** * Precomputed Atmospheric Scattering * Copyright (c) 2008 INRIA * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef MAT4_H_ #define MAT4_H_ #include "vec3.h" #ifndef M_PI #define M_PI 3.141592657 #endif /** * A 4x4 matrix. */ template class mat4 { protected: union { type m[4][4]; type _m[16]; }; public: /** * Creates a new, uninitialized matrix. */ mat4(); /** * Creates a new matrix with the given components. The first index is the * row index, the second one is the column index. */ mat4(type m00, type m01, type m02, type m03, type m10, type m11, type m12, type m13, type m20, type m21, type m22, type m23, type m30, type m31, type m32, type m33); /** * Returns the coefficients of this matrix. */ const type* coefficients() const; /** * Returns the row of this matrix whose index is given. */ const type* operator[](int iRow) const; /** * Returns true is this matrix is equal to the given matrix. */ bool operator==(const mat4& m2) const; /** * Returns true is this matrix is different from the given matrix. */ bool operator!=(const mat4& m2) const; /** * Returns the sum of this matrix and of the given matrix. */ mat4 operator+(const mat4& m2) const; /** * Returns the difference of this matrix and of the given matrix. */ mat4 operator-(const mat4& m2) const; /** * Returns the product of this matrix and of the given matrix. */ mat4 operator*(const mat4& m2) const; /** * Returns the product of this matrix and of the given vector. The given * vector w coordinate is set to 1, and the 4 vector result is converted * to a 3 vector by dividing its xyz components by its w component. */ vec3 operator*(const vec3& v) const; /** * Returns the product of this matrix and of the given scalar. */ mat4 operator*(type f) const; /** * Returns the transpose of this matrix. */ mat4 transpose(void) const; /** * Returns the adjoint of this matrix. */ mat4 adjoint() const; /** * Returns the inverse of this matrix. */ mat4 inverse() const; /** * Returns the determinant of this matrix. */ float determinant() const; /** * Returns the translation matrix corresponding to the given translation * vector. */ static mat4 translate(const vec3& v); /** * Returns the perspective projection matrix corresponding to the given * projection parameters. * * @param fovy vertical field of view in degrees. * @param aspect aspect ratio of the projection window. * @param zNear near clipping plane. * @param zFar far clipping plane. */ static mat4 perspectiveProjection(type fovy, type aspect, type zNear, type zFar); }; /** * A 4x4 matrix with float components. */ typedef mat4 mat4f; /** * A 4x4 matrix with double components. */ typedef mat4 mat4d; template inline mat4::mat4() { } template inline mat4::mat4(type m00, type m01, type m02, type m03, type m10, type m11, type m12, type m13, type m20, type m21, type m22, type m23, type m30, type m31, type m32, type m33) { m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03; m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13; m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23; m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33; } template inline const type* mat4::coefficients() const { return _m; } template inline const type* mat4::operator[](int iRow) const { //assert(iRow < 4); return m[iRow]; } template inline bool mat4::operator==(const mat4& m2) const { if ( m[0][0] != m2.m[0][0] || m[0][1] != m2.m[0][1] || m[0][2] != m2.m[0][2] || m[0][3] != m2.m[0][3] || m[1][0] != m2.m[1][0] || m[1][1] != m2.m[1][1] || m[1][2] != m2.m[1][2] || m[1][3] != m2.m[1][3] || m[2][0] != m2.m[2][0] || m[2][1] != m2.m[2][1] || m[2][2] != m2.m[2][2] || m[2][3] != m2.m[2][3] || m[3][0] != m2.m[3][0] || m[3][1] != m2.m[3][1] || m[3][2] != m2.m[3][2] || m[3][3] != m2.m[3][3]) return false; return true; } template inline bool mat4::operator!=(const mat4& m2) const { if ( m[0][0] != m2.m[0][0] || m[0][1] != m2.m[0][1] || m[0][2] != m2.m[0][2] || m[0][3] != m2.m[0][3] || m[1][0] != m2.m[1][0] || m[1][1] != m2.m[1][1] || m[1][2] != m2.m[1][2] || m[1][3] != m2.m[1][3] || m[2][0] != m2.m[2][0] || m[2][1] != m2.m[2][1] || m[2][2] != m2.m[2][2] || m[2][3] != m2.m[2][3] || m[3][0] != m2.m[3][0] || m[3][1] != m2.m[3][1] || m[3][2] != m2.m[3][2] || m[3][3] != m2.m[3][3]) return true; return false; } template inline mat4 mat4::operator+(const mat4& m2) const { mat4 r; r.m[0][0] = m[0][0] + m2.m[0][0]; r.m[0][1] = m[0][1] + m2.m[0][1]; r.m[0][2] = m[0][2] + m2.m[0][2]; r.m[0][3] = m[0][3] + m2.m[0][3]; r.m[1][0] = m[1][0] + m2.m[1][0]; r.m[1][1] = m[1][1] + m2.m[1][1]; r.m[1][2] = m[1][2] + m2.m[1][2]; r.m[1][3] = m[1][3] + m2.m[1][3]; r.m[2][0] = m[2][0] + m2.m[2][0]; r.m[2][1] = m[2][1] + m2.m[2][1]; r.m[2][2] = m[2][2] + m2.m[2][2]; r.m[2][3] = m[2][3] + m2.m[2][3]; r.m[3][0] = m[3][0] + m2.m[3][0]; r.m[3][1] = m[3][1] + m2.m[3][1]; r.m[3][2] = m[3][2] + m2.m[3][2]; r.m[3][3] = m[3][3] + m2.m[3][3]; return r; } template inline mat4 mat4::operator-(const mat4& m2) const { mat4 r; r.m[0][0] = m[0][0] - m2.m[0][0]; r.m[0][1] = m[0][1] - m2.m[0][1]; r.m[0][2] = m[0][2] - m2.m[0][2]; r.m[0][3] = m[0][3] - m2.m[0][3]; r.m[1][0] = m[1][0] - m2.m[1][0]; r.m[1][1] = m[1][1] - m2.m[1][1]; r.m[1][2] = m[1][2] - m2.m[1][2]; r.m[1][3] = m[1][3] - m2.m[1][3]; r.m[2][0] = m[2][0] - m2.m[2][0]; r.m[2][1] = m[2][1] - m2.m[2][1]; r.m[2][2] = m[2][2] - m2.m[2][2]; r.m[2][3] = m[2][3] - m2.m[2][3]; r.m[3][0] = m[3][0] - m2.m[3][0]; r.m[3][1] = m[3][1] - m2.m[3][1]; r.m[3][2] = m[3][2] - m2.m[3][2]; r.m[3][3] = m[3][3] - m2.m[3][3]; return r; } template inline mat4 mat4::operator*(const mat4& m2) const { mat4 r; r.m[0][0] = m[0][0] * m2.m[0][0] + m[0][1] * m2.m[1][0] + m[0][2] * m2.m[2][0] + m[0][3] * m2.m[3][0]; r.m[0][1] = m[0][0] * m2.m[0][1] + m[0][1] * m2.m[1][1] + m[0][2] * m2.m[2][1] + m[0][3] * m2.m[3][1]; r.m[0][2] = m[0][0] * m2.m[0][2] + m[0][1] * m2.m[1][2] + m[0][2] * m2.m[2][2] + m[0][3] * m2.m[3][2]; r.m[0][3] = m[0][0] * m2.m[0][3] + m[0][1] * m2.m[1][3] + m[0][2] * m2.m[2][3] + m[0][3] * m2.m[3][3]; r.m[1][0] = m[1][0] * m2.m[0][0] + m[1][1] * m2.m[1][0] + m[1][2] * m2.m[2][0] + m[1][3] * m2.m[3][0]; r.m[1][1] = m[1][0] * m2.m[0][1] + m[1][1] * m2.m[1][1] + m[1][2] * m2.m[2][1] + m[1][3] * m2.m[3][1]; r.m[1][2] = m[1][0] * m2.m[0][2] + m[1][1] * m2.m[1][2] + m[1][2] * m2.m[2][2] + m[1][3] * m2.m[3][2]; r.m[1][3] = m[1][0] * m2.m[0][3] + m[1][1] * m2.m[1][3] + m[1][2] * m2.m[2][3] + m[1][3] * m2.m[3][3]; r.m[2][0] = m[2][0] * m2.m[0][0] + m[2][1] * m2.m[1][0] + m[2][2] * m2.m[2][0] + m[2][3] * m2.m[3][0]; r.m[2][1] = m[2][0] * m2.m[0][1] + m[2][1] * m2.m[1][1] + m[2][2] * m2.m[2][1] + m[2][3] * m2.m[3][1]; r.m[2][2] = m[2][0] * m2.m[0][2] + m[2][1] * m2.m[1][2] + m[2][2] * m2.m[2][2] + m[2][3] * m2.m[3][2]; r.m[2][3] = m[2][0] * m2.m[0][3] + m[2][1] * m2.m[1][3] + m[2][2] * m2.m[2][3] + m[2][3] * m2.m[3][3]; r.m[3][0] = m[3][0] * m2.m[0][0] + m[3][1] * m2.m[1][0] + m[3][2] * m2.m[2][0] + m[3][3] * m2.m[3][0]; r.m[3][1] = m[3][0] * m2.m[0][1] + m[3][1] * m2.m[1][1] + m[3][2] * m2.m[2][1] + m[3][3] * m2.m[3][1]; r.m[3][2] = m[3][0] * m2.m[0][2] + m[3][1] * m2.m[1][2] + m[3][2] * m2.m[2][2] + m[3][3] * m2.m[3][2]; r.m[3][3] = m[3][0] * m2.m[0][3] + m[3][1] * m2.m[1][3] + m[3][2] * m2.m[2][3] + m[3][3] * m2.m[3][3]; return r; } template inline vec3 mat4::operator*(const vec3& v) const { vec3 r; float fInvW = 1.0 / (m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3]); r.x = (m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3]) * fInvW; r.y = (m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3]) * fInvW; r.z = (m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3]) * fInvW; return r; } template inline mat4 mat4::operator*(type f) const { mat4 r; r.m[0][0] = m[0][0] * f; r.m[0][1] = m[0][1] * f; r.m[0][2] = m[0][2] * f; r.m[0][3] = m[0][3] * f; r.m[1][0] = m[1][0] * f; r.m[1][1] = m[1][1] * f; r.m[1][2] = m[1][2] * f; r.m[1][3] = m[1][3] * f; r.m[2][0] = m[2][0] * f; r.m[2][1] = m[2][1] * f; r.m[2][2] = m[2][2] * f; r.m[2][3] = m[2][3] * f; r.m[3][0] = m[3][0] * f; r.m[3][1] = m[3][1] * f; r.m[3][2] = m[3][2] * f; r.m[3][3] = m[3][3] * f; return r; } template inline mat4 mat4::transpose(void) const { return mat4(m[0][0], m[1][0], m[2][0], m[3][0], m[0][1], m[1][1], m[2][1], m[3][1], m[0][2], m[1][2], m[2][2], m[3][2], m[0][3], m[1][3], m[2][3], m[3][3]); } template inline static float MINOR(const mat4& m, int r0, int r1, int r2, int c0, int c1, int c2) { return m[r0][c0] *(m[r1][c1] * m[r2][c2] - m[r2][c1] * m[r1][c2]) - m[r0][c1] *(m[r1][c0] * m[r2][c2] - m[r2][c0] * m[r1][c2]) + m[r0][c2] *(m[r1][c0] * m[r2][c1] - m[r2][c0] * m[r1][c1]); } template mat4 mat4::adjoint() const { return mat4(MINOR(*this, 1, 2, 3, 1, 2, 3), -MINOR(*this, 0, 2, 3, 1, 2, 3), MINOR(*this, 0, 1, 3, 1, 2, 3), -MINOR(*this, 0, 1, 2, 1, 2, 3), -MINOR(*this, 1, 2, 3, 0, 2, 3), MINOR(*this, 0, 2, 3, 0, 2, 3), -MINOR(*this, 0, 1, 3, 0, 2, 3), MINOR(*this, 0, 1, 2, 0, 2, 3), MINOR(*this, 1, 2, 3, 0, 1, 3), -MINOR(*this, 0, 2, 3, 0, 1, 3), MINOR(*this, 0, 1, 3, 0, 1, 3), -MINOR(*this, 0, 1, 2, 0, 1, 3), -MINOR(*this, 1, 2, 3, 0, 1, 2), MINOR(*this, 0, 2, 3, 0, 1, 2), -MINOR(*this, 0, 1, 3, 0, 1, 2), MINOR(*this, 0, 1, 2, 0, 1, 2)); } template mat4 mat4::inverse() const { return adjoint() * (1.0f / determinant()); } template float mat4::determinant() const { return m[0][0] * MINOR(*this, 1, 2, 3, 1, 2, 3) - m[0][1] * MINOR(*this, 1, 2, 3, 0, 2, 3) + m[0][2] * MINOR(*this, 1, 2, 3, 0, 1, 3) - m[0][3] * MINOR(*this, 1, 2, 3, 0, 1, 2); } template inline mat4 mat4::translate(const vec3 &v) { return mat4(1, 0, 0, v.x, 0, 1, 0, v.y, 0, 0, 1, v.z, 0, 0, 0, 1); } template inline mat4 mat4::perspectiveProjection(type fovy, type aspect, type zNear, type zFar) { type f = (type) 1 / tan(fovy * M_PI / 180.0 / 2); return mat4(f / aspect, 0, 0, 0, 0, f, 0, 0, 0, 0, (zFar + zNear) / (zNear - zFar), (2*zFar*zNear) / (zNear - zFar), 0, 0, -1, 0); } #endif /*MAT4_H_*/