diff options
Diffstat (limited to 'src/libmatrix/mat.cc')
-rw-r--r-- | src/libmatrix/mat.cc | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/src/libmatrix/mat.cc b/src/libmatrix/mat.cc new file mode 100644 index 0000000..93ef63c --- /dev/null +++ b/src/libmatrix/mat.cc @@ -0,0 +1,173 @@ +// +// Copyright (c) 2010 Linaro Limited +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the MIT License which accompanies +// this distribution, and is available at +// http://www.opensource.org/licenses/mit-license.php +// +// Contributors: +// Jesse Barker - original implementation. +// +#include <math.h> +#include "mat.h" + +namespace LibMatrix +{ +namespace Mat4 +{ + +mat4 +translate(float x, float y, float z) +{ + mat4 t; + t[0][3] = x; + t[1][3] = y; + t[2][3] = z; + return t; +} + +mat4 +scale(float x, float y, float z) +{ + mat4 s; + s[0][0] = x; + s[1][1] = y; + s[2][2] = z; + return s; +} + +// +// As per the OpenGL "red book" definition of rotation, from the appendix +// on Homogeneous Coordinates and Transformation Matrices, the "upper left" +// 3x3 portion of the result matrix is formed by: +// +// M = uuT + (cos a)(I - uuT) + (sin a)S +// +// where u is the normalized input vector, uuT is the outer product of that +// vector and its transpose, I is the identity matrix and S is the matrix: +// +// | 0 -z' y' | +// | z' 0 -x' | +// | -y' x' 0 | +// +// where x', y' and z' are the elements of u +// +mat4 +rotate(float angle, float x, float y, float z) +{ + vec3 u(x, y, z); + u.normalize(); + mat3 uuT = outer(u, u); + mat3 s; + s[0][0] = 0; + s[0][1] = -u.z(); + s[0][2] = u.y(); + s[1][0] = u.z(); + s[1][1] = 0; + s[1][2] = -u.x(); + s[2][0] = -u.y(); + s[2][1] = u.x(); + s[2][2] = 0; + mat3 i; + i -= uuT; + // degrees to radians + float angleRadians(angle * M_PI / 180.0); + i *= cos(angleRadians); + s *= sin(angleRadians); + i += s; + mat3 m = uuT + i; + mat4 r; + r[0][0] = m[0][0]; + r[0][1] = m[0][1]; + r[0][2] = m[0][2]; + r[1][0] = m[1][0]; + r[1][1] = m[1][1]; + r[1][2] = m[1][2]; + r[2][0] = m[2][0]; + r[2][1] = m[2][1]; + r[2][2] = m[2][2]; + return r; +} + +mat4 +frustum(float left, float right, float bottom, float top, float near, float far) +{ + float twiceNear(2 * near); + float width(right - left); + float height(top - bottom); + float depth(far - near); + mat4 f; + f[0][0] = twiceNear / width; + f[0][2] = (right + left) / width; + f[1][1] = twiceNear / height; + f[1][2] = (top + bottom) / height; + f[2][2] = -(far + near) / depth; + f[2][3] = -(twiceNear * far) / depth; + f[3][2] = -1; + f[3][3] = 0; + return f; +} + +mat4 +ortho(float left, float right, float bottom, float top, float near, float far) +{ + float width(right - left); + float height(top - bottom); + float depth(far - near); + mat4 o; + o[0][0] = 2 / width; + o[0][3] = (right + left) / width; + o[1][1] = 2 / height; + o[1][3] = (top + bottom) / height; + o[2][2] = -2 / depth; + o[2][3] = (far + near) / depth; + return o; +} + +mat4 +perspective(float fovy, float aspect, float zNear, float zFar) +{ + // degrees to radians + float fovyRadians(fovy * M_PI / 180.0); + // cotangent(x) = 1/tan(x) + float f = 1/tan(fovyRadians / 2); + float depth(zNear - zFar); + mat4 p; + p[0][0] = f / aspect; + p[1][1] = f; + p[2][2] = (zFar + zNear) / depth; + p[2][3] = (2 * zFar * zNear) / depth; + p[3][2] = -1; + p[3][3] = 0; + return p; +} + +mat4 lookAt(float eyeX, float eyeY, float eyeZ, + float centerX, float centerY, float centerZ, + float upX, float upY, float upZ) +{ + vec3 f(centerX - eyeX, centerY - eyeY, centerZ - eyeZ); + f.normalize(); + vec3 up(upX, upY, upZ); + vec3 s = vec3::cross(f, up); + vec3 u = vec3::cross(s, f); + s.normalize(); + u.normalize(); + mat4 la; + la[0][0] = s.x(); + la[0][1] = s.y(); + la[0][2] = s.z(); + la[1][0] = u.x(); + la[1][1] = u.y(); + la[1][2] = u.z(); + la[2][0] = -f.x(); + la[2][1] = -f.y(); + la[2][2] = -f.z(); + la *= translate(-eyeX, -eyeY, -eyeZ); + return la; +} + +} // namespace Mat4 + +} // namespace LibMatrix |