=== added directory 'src/libmatrix'
=== added file 'src/libmatrix/COPYING'
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2010 Linaro Limited
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
=== added file 'src/libmatrix/Makefile'
@@ -0,0 +1,17 @@
+TARGETS = libmatrix.a matrix_inverse_test
+SRCS = mat.cc program.cc matrix_inverse_test.cc
+OBJS = $(SRCS:.cc=.o)
+CXXFLAGS = -Wall -Werror -pedantic -O3
+
+default: $(TARGETS)
+
+mat.o : mat.cc mat.h
+program.o: program.cc program.h
+matrix_inverse_test.o: matrix_inverse_test.cc mat.h
+matrix_inverse_test: matrix_inverse_test.o libmatrix.a
+ $(CXX) -o $@ $?
+libmatrix.a : mat.o mat.h stack.h vec.h program.o program.h
+ $(AR) -r $@ $(OBJS)
+
+clean :
+ $(RM) $(OBJS) $(TARGETS)
=== added file 'src/libmatrix/README'
@@ -0,0 +1,11 @@
+libmatrix
+=========
+
+A simple C++ template library that provides containers and arithmetic
+operations for vectors, matrices and matrix stacks of 2, 3 and 4 dimensions.
+Additionally, it provides implementations of the more common matrix
+transformations described by the OpenGL programming guide. libmatrix does
+not make any OpenGL calls, it merely replaces a portion of the fixed-function
+vertex processing API that have been removed from newer releases of core OpenGL
+and omitted from OpenGL ES. The goal is simply to provide developers an easier
+point of entry into developing for OpenGL and OpenGL ES.
=== added file '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
=== added file 'src/libmatrix/mat.h'
@@ -0,0 +1,1074 @@
+//
+// 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.
+//
+#ifndef MAT_H_
+#define MAT_H_
+#include <stdexcept>
+#include <iostream>
+#include <iomanip>
+#include "vec.h"
+
+namespace LibMatrix
+{
+// Proxy class for providing the functionality of a doubly-dimensioned array
+// representation of matrices. Each matrix class defines its operator[]
+// to return an ArrayProxy. The ArrayProxy then returns the appropriate item
+// from its operator[].
+template<typename T, unsigned int dimension>
+class ArrayProxy
+{
+public:
+ ArrayProxy(T* data) { data_ = data; }
+ ~ArrayProxy() { data_ = 0; }
+ T& operator[](int index)
+ {
+ return data_[index * dimension];
+ }
+ const T& operator[](int index) const
+ {
+ return data_[index * dimension];
+ }
+private:
+ T* data_;
+};
+
+
+// Programming interfaces to all matrix objects are represented row-centric
+// (i.e. C/C++ style references to the data appear as matrix[row][column]).
+// However, the internal data representation is column-major, so when using
+// the raw data access member to treat the data as a singly-dimensioned array,
+// it does not have to be transposed.
+template<typename T>
+class tmat2
+{
+public:
+ tmat2()
+ {
+ setIdentity();
+ }
+ tmat2(const tmat2& m)
+ {
+ m_[0] = m.m_[0];
+ m_[1] = m.m_[1];
+ m_[2] = m.m_[2];
+ m_[3] = m.m_[3];
+ }
+ tmat2(const T& c0r0, const T& c0r1, const T& c1r0, const T& c1r1)
+ {
+ m_[0] = c0r0;
+ m_[1] = c0r1;
+ m_[2] = c1r0;
+ m_[3] = c1r1;
+ }
+ ~tmat2() {}
+
+ void setIdentity()
+ {
+ m_[0] = 1;
+ m_[1] = 0;
+ m_[2] = 0;
+ m_[3] = 1;
+ }
+
+ tmat2& transpose()
+ {
+ T tmp_val = m_[1];
+ m_[1] = m_[2];
+ m_[2] = tmp_val;
+ return *this;
+ }
+
+ T determinant()
+ {
+ return (m_[0] * m_[3]) - (m_[2] * m_[1]);
+ }
+
+ tmat2& inverse() throw(std::runtime_error)
+ {
+ T d(determinant());
+ if (d == static_cast<T>(0))
+ {
+ throw std::runtime_error("Matrix is noninvertible!!!!");
+ }
+ T c0r0(m_[3] / d);
+ T c0r1(-m_[1] / d);
+ T c1r0(-m_[2] / d);
+ T c1r1(m_[0] / d);
+ m_[0] = c0r0;
+ m_[1] = c0r1;
+ m_[2] = c1r0;
+ m_[3] = c1r1;
+ return *this;
+ }
+
+ void print() const
+ {
+ static const int precision(6);
+ // row 0
+ std::cout << "| ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[0];
+ std::cout << " ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[2];
+ std::cout << " |" << std::endl;
+ // row 1
+ std::cout << "| ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[1];
+ std::cout << " ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[3];
+ std::cout << " |" << std::endl;
+ }
+
+ operator const T*() const { return &m_[0];}
+
+ bool operator==(const tmat2& rhs) const
+ {
+ return m_[0] == rhs.m_[0] &&
+ m_[1] == rhs.m_[1] &&
+ m_[2] == rhs.m_[2] &&
+ m_[3] == rhs.m_[3];
+ }
+
+ bool operator!=(const tmat2& rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ tmat2& operator=(const tmat2& rhs)
+ {
+ if (this != &rhs)
+ {
+ m_[0] = rhs.m_[0];
+ m_[1] = rhs.m_[1];
+ m_[2] = rhs.m_[2];
+ m_[3] = rhs.m_[3];
+ }
+ return *this;
+ }
+
+ tmat2& operator+=(const tmat2& rhs)
+ {
+ m_[0] += rhs.m_[0];
+ m_[1] += rhs.m_[1];
+ m_[2] += rhs.m_[2];
+ m_[3] += rhs.m_[3];
+ return *this;
+ }
+
+ const tmat2 operator+(const tmat2& rhs)
+ {
+ return tmat2(*this) += rhs;
+ }
+
+ tmat2& operator-=(const tmat2& rhs)
+ {
+ m_[0] -= rhs.m_[0];
+ m_[1] -= rhs.m_[1];
+ m_[2] -= rhs.m_[2];
+ m_[3] -= rhs.m_[3];
+ return *this;
+ }
+
+ const tmat2 operator-(const tmat2& rhs)
+ {
+ return tmat2(*this) += rhs;
+ }
+
+ tmat2& operator*=(const tmat2& rhs)
+ {
+ T c0r0((m_[0] * rhs.m_[0]) + (m_[2] * rhs.m_[1]));
+ T c0r1((m_[1] * rhs.m_[0]) + (m_[3] * rhs.m_[1]));
+ T c1r0((m_[0] * rhs.m_[2]) + (m_[2] * rhs.m_[3]));
+ T c1r1((m_[1] * rhs.m_[2]) + (m_[3] * rhs.m_[3]));
+ m_[0] = c0r0;
+ m_[1] = c0r1;
+ m_[2] = c1r0;
+ m_[3] = c1r1;
+ return *this;
+ }
+
+ const tmat2 operator*(const tmat2& rhs)
+ {
+ return tmat2(*this) *= rhs;
+ }
+
+ tmat2& operator*=(const T& rhs)
+ {
+ m_[0] *= rhs;
+ m_[1] *= rhs;
+ m_[2] *= rhs;
+ m_[3] *= rhs;
+ return *this;
+ }
+
+ const tmat2 operator*(const T& rhs)
+ {
+ return tmat2(*this) *= rhs;
+ }
+
+ tmat2& operator/=(const T& rhs)
+ {
+ m_[0] /= rhs;
+ m_[1] /= rhs;
+ m_[2] /= rhs;
+ m_[3] /= rhs;
+ return *this;
+ }
+
+ const tmat2 operator/(const T& rhs)
+ {
+ return tmat2(*this) /= rhs;
+ }
+
+ ArrayProxy<T, 2> operator[](int index)
+ {
+ return ArrayProxy<T, 2>(&m_[index]);
+ }
+ const ArrayProxy<T, 2> operator[](int index) const
+ {
+ return ArrayProxy<T, 2>(const_cast<T*>(&m_[index]));
+ }
+
+private:
+ T m_[4];
+};
+
+template<typename T>
+const tmat2<T> operator*(const T& lhs, const tmat2<T>& rhs)
+{
+ return tmat2<T>(rhs) * lhs;
+}
+
+template<typename T>
+const tvec2<T> operator*(const tvec2<T>& lhs, const tmat2<T>& rhs)
+{
+ T x((lhs.x() * rhs[0][0]) + (lhs.y() * rhs[1][0]));
+ T y((lhs.x() * rhs[0][1]) + (lhs.y() * rhs[1][1]));
+ return tvec2<T>(x,y);
+}
+
+template<typename T>
+const tvec2<T> operator*(const tmat2<T>& lhs, const tvec2<T>& rhs)
+{
+ T x((lhs[0][0] * rhs.x()) + (lhs[0][1] * rhs.y()));
+ T y((lhs[1][0] * rhs.x()) + (lhs[1][1] * rhs.y()));
+ return tvec2<T>(x, y);
+}
+
+template<typename T>
+const tmat2<T> outer(const tvec2<T>& a, const tvec2<T>& b)
+{
+ tmat2<T> product;
+ product[0][0] = a.x() * b.x();
+ product[0][1] = a.x() * b.y();
+ product[1][0] = a.y() * b.x();
+ product[1][1] = a.y() * b.y();
+ return product;
+}
+
+template<typename T>
+class tmat3
+{
+public:
+ tmat3()
+ {
+ setIdentity();
+ }
+ tmat3(const tmat3& m)
+ {
+ m_[0] = m.m_[0];
+ m_[1] = m.m_[1];
+ m_[2] = m.m_[2];
+ m_[3] = m.m_[3];
+ m_[4] = m.m_[4];
+ m_[5] = m.m_[5];
+ m_[6] = m.m_[6];
+ m_[7] = m.m_[7];
+ m_[8] = m.m_[8];
+ }
+ tmat3(const T& c0r0, const T& c0r1, const T& c0r2,
+ const T& c1r0, const T& c1r1, const T& c1r2,
+ const T& c2r0, const T& c2r1, const T& c2r2)
+ {
+ m_[0] = c0r0;
+ m_[1] = c0r1;
+ m_[2] = c0r2;
+ m_[3] = c1r0;
+ m_[4] = c1r1;
+ m_[5] = c1r2;
+ m_[6] = c2r0;
+ m_[7] = c2r1;
+ m_[8] = c2r2;
+ }
+ ~tmat3() {}
+
+ void setIdentity()
+ {
+ m_[0] = 1;
+ m_[1] = 0;
+ m_[2] = 0;
+ m_[3] = 0;
+ m_[4] = 1;
+ m_[5] = 0;
+ m_[6] = 0;
+ m_[7] = 0;
+ m_[8] = 1;
+ }
+
+ tmat3& transpose()
+ {
+ T tmp_val = m_[1];
+ m_[1] = m_[3];
+ m_[3] = tmp_val;
+ tmp_val = m_[2];
+ m_[2] = m_[6];
+ m_[6] = tmp_val;
+ tmp_val = m_[5];
+ m_[5] = m_[7];
+ m_[7] = tmp_val;
+ return *this;
+ }
+
+ T determinant()
+ {
+ tmat2<T> minor0(m_[4], m_[5], m_[7], m_[8]);
+ tmat2<T> minor3(m_[1], m_[2], m_[7], m_[8]);
+ tmat2<T> minor6(m_[1], m_[2], m_[4], m_[5]);
+ return (m_[0] * minor0.determinant()) -
+ (m_[3] * minor3.determinant()) +
+ (m_[6] * minor6.determinant());
+ }
+
+ tmat3& inverse() throw(std::runtime_error)
+ {
+ T d(determinant());
+ if (d == static_cast<T>(0))
+ {
+ throw std::runtime_error("Matrix is noninvertible!!!!");
+ }
+ tmat2<T> minor0(m_[4], m_[5], m_[7], m_[8]);
+ tmat2<T> minor1(m_[7], m_[8], m_[1], m_[2]);
+ tmat2<T> minor2(m_[1], m_[2], m_[4], m_[5]);
+ tmat2<T> minor3(m_[6], m_[8], m_[3], m_[5]);
+ tmat2<T> minor4(m_[0], m_[2], m_[6], m_[8]);
+ tmat2<T> minor5(m_[3], m_[5], m_[0], m_[2]);
+ tmat2<T> minor6(m_[3], m_[4], m_[6], m_[7]);
+ tmat2<T> minor7(m_[6], m_[7], m_[0], m_[1]);
+ tmat2<T> minor8(m_[0], m_[1], m_[3], m_[4]);
+ m_[0] = minor0.determinant() / d;
+ m_[1] = minor1.determinant() / d;
+ m_[2] = minor2.determinant() / d;
+ m_[3] = minor3.determinant() / d;
+ m_[4] = minor4.determinant() / d;
+ m_[5] = minor5.determinant() / d;
+ m_[6] = minor6.determinant() / d;
+ m_[7] = minor7.determinant() / d;
+ m_[8] = minor8.determinant() / d;
+ return *this;
+ }
+
+ void print() const
+ {
+ static const int precision(6);
+ // row 0
+ std::cout << "| ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[0];
+ std::cout << " ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[3];
+ std::cout << " ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[6];
+ std::cout << " |" << std::endl;
+ // row 1
+ std::cout << "| ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[1];
+ std::cout << " ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[4];
+ std::cout << " ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[7];
+ std::cout << " |" << std::endl;
+ // row 2
+ std::cout << "| ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[2];
+ std::cout << " ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[5];
+ std::cout << " ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[8];
+ std::cout << " |" << std::endl;
+ }
+
+ operator const T*() const { return &m_[0];}
+
+ bool operator==(const tmat3& rhs) const
+ {
+ return m_[0] == rhs.m_[0] &&
+ m_[1] == rhs.m_[1] &&
+ m_[2] == rhs.m_[2] &&
+ m_[3] == rhs.m_[3] &&
+ m_[4] == rhs.m_[4] &&
+ m_[5] == rhs.m_[5] &&
+ m_[6] == rhs.m_[6] &&
+ m_[7] == rhs.m_[7] &&
+ m_[8] == rhs.m_[8];
+ }
+
+ bool operator!=(const tmat3& rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ tmat3& operator=(const tmat3& rhs)
+ {
+ if (this != &rhs)
+ {
+ m_[0] = rhs.m_[0];
+ m_[1] = rhs.m_[1];
+ m_[2] = rhs.m_[2];
+ m_[3] = rhs.m_[3];
+ m_[4] = rhs.m_[4];
+ m_[5] = rhs.m_[5];
+ m_[6] = rhs.m_[6];
+ m_[7] = rhs.m_[7];
+ m_[8] = rhs.m_[8];
+ }
+ return *this;
+ }
+
+ tmat3& operator+=(const tmat3& rhs)
+ {
+ m_[0] += rhs.m_[0];
+ m_[1] += rhs.m_[1];
+ m_[2] += rhs.m_[2];
+ m_[3] += rhs.m_[3];
+ m_[4] += rhs.m_[4];
+ m_[5] += rhs.m_[5];
+ m_[6] += rhs.m_[6];
+ m_[7] += rhs.m_[7];
+ m_[8] += rhs.m_[8];
+ return *this;
+ }
+
+ const tmat3 operator+(const tmat3& rhs)
+ {
+ return tmat3(*this) += rhs;
+ }
+
+ tmat3& operator-=(const tmat3& rhs)
+ {
+ m_[0] -= rhs.m_[0];
+ m_[1] -= rhs.m_[1];
+ m_[2] -= rhs.m_[2];
+ m_[3] -= rhs.m_[3];
+ m_[4] -= rhs.m_[4];
+ m_[5] -= rhs.m_[5];
+ m_[6] -= rhs.m_[6];
+ m_[7] -= rhs.m_[7];
+ m_[8] -= rhs.m_[8];
+ return *this;
+ }
+
+ const tmat3 operator-(const tmat3& rhs)
+ {
+ return tmat3(*this) -= rhs;
+ }
+
+ tmat3& operator*=(const tmat3& rhs)
+ {
+ T c0r0((m_[0] * rhs.m_[0]) + (m_[3] * rhs.m_[1]) + (m_[6] * rhs.m_[2]));
+ T c0r1((m_[1] * rhs.m_[0]) + (m_[4] * rhs.m_[1]) + (m_[7] * rhs.m_[2]));
+ T c0r2((m_[2] * rhs.m_[0]) + (m_[5] * rhs.m_[1]) + (m_[8] * rhs.m_[2]));
+ T c1r0((m_[0] * rhs.m_[3]) + (m_[3] * rhs.m_[4]) + (m_[6] * rhs.m_[5]));
+ T c1r1((m_[1] * rhs.m_[3]) + (m_[4] * rhs.m_[4]) + (m_[7] * rhs.m_[5]));
+ T c1r2((m_[2] * rhs.m_[3]) + (m_[5] * rhs.m_[4]) + (m_[8] * rhs.m_[5]));
+ T c2r0((m_[0] * rhs.m_[6]) + (m_[3] * rhs.m_[7]) + (m_[6] * rhs.m_[8]));
+ T c2r1((m_[1] * rhs.m_[6]) + (m_[4] * rhs.m_[7]) + (m_[7] * rhs.m_[8]));
+ T c2r2((m_[2] * rhs.m_[6]) + (m_[5] * rhs.m_[7]) + (m_[8] * rhs.m_[8]));
+ m_[0] = c0r0;
+ m_[1] = c0r1;
+ m_[2] = c0r2;
+ m_[3] = c1r0;
+ m_[4] = c1r1;
+ m_[5] = c1r2;
+ m_[6] = c2r0;
+ m_[7] = c2r1;
+ m_[8] = c2r2;
+ return *this;
+ }
+
+ const tmat3 operator*(const tmat3& rhs)
+ {
+ return tmat3(*this) *= rhs;
+ }
+
+ tmat3& operator*=(const T& rhs)
+ {
+ m_[0] *= rhs;
+ m_[1] *= rhs;
+ m_[2] *= rhs;
+ m_[3] *= rhs;
+ m_[4] *= rhs;
+ m_[5] *= rhs;
+ m_[6] *= rhs;
+ m_[7] *= rhs;
+ m_[8] *= rhs;
+ return *this;
+ }
+
+ const tmat3 operator*(const T& rhs)
+ {
+ return tmat3(*this) *= rhs;
+ }
+
+ tmat3& operator/=(const T& rhs)
+ {
+ m_[0] /= rhs;
+ m_[1] /= rhs;
+ m_[2] /= rhs;
+ m_[3] /= rhs;
+ m_[4] /= rhs;
+ m_[5] /= rhs;
+ m_[6] /= rhs;
+ m_[7] /= rhs;
+ m_[8] /= rhs;
+ return *this;
+ }
+
+ const tmat3 operator/(const T& rhs)
+ {
+ return tmat3(*this) /= rhs;
+ }
+
+ ArrayProxy<T, 3> operator[](int index)
+ {
+ return ArrayProxy<T, 3>(&m_[index]);
+ }
+ const ArrayProxy<T, 3> operator[](int index) const
+ {
+ return ArrayProxy<T, 3>(const_cast<T*>(&m_[index]));
+ }
+
+private:
+ T m_[9];
+};
+
+template<typename T>
+const tmat3<T> operator*(const T& lhs, const tmat3<T>& rhs)
+{
+ return tmat3<T>(rhs) * lhs;
+}
+
+template<typename T>
+const tvec3<T> operator*(const tvec3<T>& lhs, const tmat3<T>& rhs)
+{
+ T x((lhs.x() * rhs[0][0]) + (lhs.y() * rhs[1][0]) + (lhs.z() * rhs[2][0]));
+ T y((lhs.x() * rhs[0][1]) + (lhs.y() * rhs[1][1]) + (lhs.z() * rhs[2][1]));
+ T z((lhs.x() * rhs[0][2]) + (lhs.y() * rhs[1][2]) + (lhs.z() * rhs[2][2]));
+ return tvec3<T>(x, y, z);
+}
+
+template<typename T>
+const tvec3<T> operator*(const tmat3<T>& lhs, const tvec3<T>& rhs)
+{
+ T x((lhs[0][0] * rhs.x()) + (lhs[0][1] * rhs.y()) + (lhs[0][2] * rhs.z()));
+ T y((lhs[1][0] * rhs.x()) + (lhs[1][1] * rhs.y()) + (lhs[1][2] * rhs.z()));
+ T z((lhs[2][0] * rhs.x()) + (lhs[2][1] * rhs.y()) + (lhs[2][2] * rhs.z()));
+ return tvec3<T>(x, y, z);
+}
+
+template<typename T>
+const tmat3<T> outer(const tvec3<T>& a, const tvec3<T>& b)
+{
+ tmat3<T> product;
+ product[0][0] = a.x() * b.x();
+ product[0][1] = a.x() * b.y();
+ product[0][2] = a.x() * b.z();
+ product[1][0] = a.y() * b.x();
+ product[1][1] = a.y() * b.y();
+ product[1][2] = a.y() * b.z();
+ product[2][0] = a.z() * b.x();
+ product[2][1] = a.z() * b.y();
+ product[2][2] = a.z() * b.z();
+ return product;
+}
+
+template<typename T>
+class tmat4
+{
+public:
+ tmat4()
+ {
+ setIdentity();
+ }
+ tmat4(const tmat4& m)
+ {
+ m_[0] = m.m_[0];
+ m_[1] = m.m_[1];
+ m_[2] = m.m_[2];
+ m_[3] = m.m_[3];
+ m_[4] = m.m_[4];
+ m_[5] = m.m_[5];
+ m_[6] = m.m_[6];
+ m_[7] = m.m_[7];
+ m_[8] = m.m_[8];
+ m_[9] = m.m_[9];
+ m_[10] = m.m_[10];
+ m_[11] = m.m_[11];
+ m_[12] = m.m_[12];
+ m_[13] = m.m_[13];
+ m_[14] = m.m_[14];
+ m_[15] = m.m_[15];
+ }
+ ~tmat4() {}
+
+ void setIdentity()
+ {
+ m_[0] = 1;
+ m_[1] = 0;
+ m_[2] = 0;
+ m_[3] = 0;
+ m_[4] = 0;
+ m_[5] = 1;
+ m_[6] = 0;
+ m_[7] = 0;
+ m_[8] = 0;
+ m_[9] = 0;
+ m_[10] = 1;
+ m_[11] = 0;
+ m_[12] = 0;
+ m_[13] = 0;
+ m_[14] = 0;
+ m_[15] = 1;
+ }
+
+ tmat4& transpose()
+ {
+ T tmp_val = m_[1];
+ m_[1] = m_[4];
+ m_[4] = tmp_val;
+ tmp_val = m_[2];
+ m_[2] = m_[8];
+ m_[8] = tmp_val;
+ tmp_val = m_[3];
+ m_[3] = m_[12];
+ m_[12] = tmp_val;
+ tmp_val = m_[6];
+ m_[6] = m_[9];
+ m_[9] = tmp_val;
+ tmp_val = m_[7];
+ m_[7] = m_[13];
+ m_[13] = tmp_val;
+ tmp_val = m_[11];
+ m_[11] = m_[14];
+ m_[14] = tmp_val;
+ return *this;
+ }
+
+ T determinant()
+ {
+ tmat3<T> minor0(m_[5], m_[6], m_[7], m_[9], m_[10], m_[11], m_[13], m_[14], m_[15]);
+ tmat3<T> minor4(m_[1], m_[2], m_[3], m_[9], m_[10], m_[11], m_[13], m_[14], m_[15]);
+ tmat3<T> minor8(m_[1], m_[2], m_[3], m_[5], m_[6], m_[7], m_[13], m_[14], m_[15]);
+ tmat3<T> minor12(m_[1], m_[2], m_[3], m_[5], m_[6], m_[7], m_[9], m_[10], m_[11]);
+ return (m_[0] * minor0.determinant()) -
+ (m_[4] * minor4.determinant()) +
+ (m_[8] * minor8.determinant()) -
+ (m_[12] * minor12.determinant());
+ }
+
+ tmat4& inverse() throw(std::runtime_error)
+ {
+ T d(determinant());
+ if (d == static_cast<T>(0))
+ {
+ throw std::runtime_error("Matrix is noninvertible!!!!");
+ }
+ tmat3<T> minor0(m_[5], m_[6], m_[7], m_[9], m_[10], m_[11], m_[13], m_[14], m_[15]);
+ tmat3<T> minor1(m_[1], m_[2], m_[3], m_[13], m_[14], m_[15], m_[9], m_[10], m_[11]);
+ tmat3<T> minor2(m_[1], m_[2], m_[3], m_[5], m_[6], m_[7], m_[13], m_[14], m_[15]);
+ tmat3<T> minor3(m_[1], m_[2], m_[3], m_[9], m_[10], m_[11], m_[5], m_[6], m_[7]);
+
+ tmat3<T> minor4(m_[4], m_[6], m_[7], m_[12], m_[14], m_[15], m_[8], m_[10], m_[11]);
+ tmat3<T> minor5(m_[0], m_[2], m_[3], m_[8], m_[10], m_[11], m_[12], m_[14], m_[15]);
+ tmat3<T> minor6(m_[0], m_[2], m_[3], m_[12], m_[14], m_[15], m_[4], m_[6], m_[7]);
+ tmat3<T> minor7(m_[0], m_[2], m_[3], m_[4], m_[6], m_[7], m_[8], m_[10], m_[11]);
+
+ tmat3<T> minor8(m_[4], m_[5], m_[7], m_[8], m_[9], m_[11], m_[12], m_[13], m_[15]);
+ tmat3<T> minor9(m_[0], m_[1], m_[3], m_[12], m_[13], m_[15], m_[8], m_[9], m_[11]);
+ tmat3<T> minor10(m_[0], m_[1], m_[3], m_[4], m_[5], m_[7], m_[12], m_[13], m_[15]);
+ tmat3<T> minor11(m_[0], m_[1], m_[3], m_[8], m_[9], m_[11], m_[4], m_[5], m_[7]);
+
+ tmat3<T> minor12(m_[4], m_[5], m_[6], m_[12], m_[13], m_[14], m_[8], m_[9], m_[10]);
+ tmat3<T> minor13(m_[0], m_[1], m_[2], m_[8], m_[9], m_[10], m_[12], m_[13], m_[14]);
+ tmat3<T> minor14(m_[0], m_[1], m_[2], m_[12], m_[13], m_[14], m_[4], m_[5], m_[6]);
+ tmat3<T> minor15(m_[0], m_[1], m_[2], m_[4], m_[5], m_[6], m_[8], m_[9], m_[10]);
+ m_[0] = minor0.determinant() / d;
+ m_[1] = minor1.determinant() / d;
+ m_[2] = minor2.determinant() / d;
+ m_[3] = minor3.determinant() / d;
+ m_[4] = minor4.determinant() / d;
+ m_[5] = minor5.determinant() / d;
+ m_[6] = minor6.determinant() / d;
+ m_[7] = minor7.determinant() / d;
+ m_[8] = minor8.determinant() / d;
+ m_[9] = minor9.determinant() / d;
+ m_[10] = minor10.determinant() / d;
+ m_[11] = minor11.determinant() / d;
+ m_[12] = minor12.determinant() / d;
+ m_[13] = minor13.determinant() / d;
+ m_[14] = minor14.determinant() / d;
+ m_[15] = minor15.determinant() / d;
+ return *this;
+ }
+
+ void print() const
+ {
+ static const int precision(6);
+ // row 0
+ std::cout << "| ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[0];
+ std::cout << " ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[4];
+ std::cout << " ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[8];
+ std::cout << " ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[12];
+ std::cout << " |" << std::endl;
+ // row 1
+ std::cout << "| ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[1];
+ std::cout << " ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[5];
+ std::cout << " ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[9];
+ std::cout << " ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[13];
+ std::cout << " |" << std::endl;
+ // row 2
+ std::cout << "| ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[2];
+ std::cout << " ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[6];
+ std::cout << " ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[10];
+ std::cout << " ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[14];
+ std::cout << " |" << std::endl;
+ // row 3
+ std::cout << "| ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[3];
+ std::cout << " ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[7];
+ std::cout << " ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[11];
+ std::cout << " ";
+ std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[15];
+ std::cout << " |" << std::endl;
+ }
+
+ operator const T*() const { return &m_[0];}
+
+ bool operator==(const tmat4& rhs) const
+ {
+ return m_[0] == rhs.m_[0] &&
+ m_[1] == rhs.m_[1] &&
+ m_[2] == rhs.m_[2] &&
+ m_[3] == rhs.m_[3] &&
+ m_[4] == rhs.m_[4] &&
+ m_[5] == rhs.m_[5] &&
+ m_[6] == rhs.m_[6] &&
+ m_[7] == rhs.m_[7] &&
+ m_[8] == rhs.m_[8] &&
+ m_[9] == rhs.m_[9] &&
+ m_[10] == rhs.m_[10] &&
+ m_[11] == rhs.m_[11] &&
+ m_[12] == rhs.m_[12] &&
+ m_[13] == rhs.m_[13] &&
+ m_[14] == rhs.m_[14] &&
+ m_[15] == rhs.m_[15];
+ }
+
+ bool operator!=(const tmat4& rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ tmat4& operator=(const tmat4& rhs)
+ {
+ if (this != &rhs)
+ {
+ m_[0] = rhs.m_[0];
+ m_[1] = rhs.m_[1];
+ m_[2] = rhs.m_[2];
+ m_[3] = rhs.m_[3];
+ m_[4] = rhs.m_[4];
+ m_[5] = rhs.m_[5];
+ m_[6] = rhs.m_[6];
+ m_[7] = rhs.m_[7];
+ m_[8] = rhs.m_[8];
+ m_[9] = rhs.m_[9];
+ m_[10] = rhs.m_[10];
+ m_[11] = rhs.m_[11];
+ m_[12] = rhs.m_[12];
+ m_[13] = rhs.m_[13];
+ m_[14] = rhs.m_[14];
+ m_[15] = rhs.m_[15];
+ }
+ return *this;
+ }
+
+ tmat4& operator+=(const tmat4& rhs)
+ {
+ m_[0] += rhs.m_[0];
+ m_[1] += rhs.m_[1];
+ m_[2] += rhs.m_[2];
+ m_[3] += rhs.m_[3];
+ m_[4] += rhs.m_[4];
+ m_[5] += rhs.m_[5];
+ m_[6] += rhs.m_[6];
+ m_[7] += rhs.m_[7];
+ m_[8] += rhs.m_[8];
+ m_[9] += rhs.m_[9];
+ m_[10] += rhs.m_[10];
+ m_[11] += rhs.m_[11];
+ m_[12] += rhs.m_[12];
+ m_[13] += rhs.m_[13];
+ m_[14] += rhs.m_[14];
+ m_[15] += rhs.m_[15];
+ return *this;
+ }
+
+ const tmat4 operator+(const tmat4& rhs)
+ {
+ return tmat4(*this) += rhs;
+ }
+
+ tmat4& operator-=(const tmat4& rhs)
+ {
+ m_[0] -= rhs.m_[0];
+ m_[1] -= rhs.m_[1];
+ m_[2] -= rhs.m_[2];
+ m_[3] -= rhs.m_[3];
+ m_[4] -= rhs.m_[4];
+ m_[5] -= rhs.m_[5];
+ m_[6] -= rhs.m_[6];
+ m_[7] -= rhs.m_[7];
+ m_[8] -= rhs.m_[8];
+ m_[9] -= rhs.m_[9];
+ m_[10] -= rhs.m_[10];
+ m_[11] -= rhs.m_[11];
+ m_[12] -= rhs.m_[12];
+ m_[13] -= rhs.m_[13];
+ m_[14] -= rhs.m_[14];
+ m_[15] -= rhs.m_[15];
+ return *this;
+ }
+
+ const tmat4 operator-(const tmat4& rhs)
+ {
+ return tmat4(*this) -= rhs;
+ }
+
+ tmat4& operator*=(const tmat4& rhs)
+ {
+ T c0r0((m_[0] * rhs.m_[0]) + (m_[4] * rhs.m_[1]) + (m_[8] * rhs.m_[2]) + (m_[12] * rhs.m_[3]));
+ T c0r1((m_[1] * rhs.m_[0]) + (m_[5] * rhs.m_[1]) + (m_[9] * rhs.m_[2]) + (m_[13] * rhs.m_[3]));
+ T c0r2((m_[2] * rhs.m_[0]) + (m_[6] * rhs.m_[1]) + (m_[10] * rhs.m_[2]) + (m_[14] * rhs.m_[3]));
+ T c0r3((m_[3] * rhs.m_[0]) + (m_[7] * rhs.m_[1]) + (m_[11] * rhs.m_[2]) + (m_[15] * rhs.m_[3]));
+ T c1r0((m_[0] * rhs.m_[4]) + (m_[4] * rhs.m_[5]) + (m_[8] * rhs.m_[6]) + (m_[12] * rhs.m_[7]));
+ T c1r1((m_[1] * rhs.m_[4]) + (m_[5] * rhs.m_[5]) + (m_[9] * rhs.m_[6]) + (m_[13] * rhs.m_[7]));
+ T c1r2((m_[2] * rhs.m_[4]) + (m_[6] * rhs.m_[5]) + (m_[10] * rhs.m_[6]) + (m_[14] * rhs.m_[7]));
+ T c1r3((m_[3] * rhs.m_[4]) + (m_[7] * rhs.m_[5]) + (m_[11] * rhs.m_[6]) + (m_[15] * rhs.m_[7]));
+ T c2r0((m_[0] * rhs.m_[8]) + (m_[4] * rhs.m_[9]) + (m_[8] * rhs.m_[10]) + (m_[12] * rhs.m_[11]));
+ T c2r1((m_[1] * rhs.m_[8]) + (m_[5] * rhs.m_[9]) + (m_[9] * rhs.m_[10]) + (m_[13] * rhs.m_[11]));
+ T c2r2((m_[2] * rhs.m_[8]) + (m_[6] * rhs.m_[9]) + (m_[10] * rhs.m_[10]) + (m_[14] * rhs.m_[11]));
+ T c2r3((m_[3] * rhs.m_[8]) + (m_[7] * rhs.m_[9]) + (m_[11] * rhs.m_[10]) + (m_[15] * rhs.m_[11]));
+ T c3r0((m_[0] * rhs.m_[12]) + (m_[4] * rhs.m_[13]) + (m_[8] * rhs.m_[14]) + (m_[12] * rhs.m_[15]));
+ T c3r1((m_[1] * rhs.m_[12]) + (m_[5] * rhs.m_[13]) + (m_[9] * rhs.m_[14]) + (m_[13] * rhs.m_[15]));
+ T c3r2((m_[2] * rhs.m_[12]) + (m_[6] * rhs.m_[13]) + (m_[10] * rhs.m_[14]) + (m_[14] * rhs.m_[15]));
+ T c3r3((m_[3] * rhs.m_[12]) + (m_[7] * rhs.m_[13]) + (m_[11] * rhs.m_[14]) + (m_[15] * rhs.m_[15]));
+ m_[0] = c0r0;
+ m_[1] = c0r1;
+ m_[2] = c0r2;
+ m_[3] = c0r3;
+ m_[4] = c1r0;
+ m_[5] = c1r1;
+ m_[6] = c1r2;
+ m_[7] = c1r3;
+ m_[8] = c2r0;
+ m_[9] = c2r1;
+ m_[10] = c2r2;
+ m_[11] = c2r3;
+ m_[12] = c3r0;
+ m_[13] = c3r1;
+ m_[14] = c3r2;
+ m_[15] = c3r3;
+ return *this;
+ }
+
+ const tmat4 operator*(const tmat4& rhs)
+ {
+ return tmat4(*this) *= rhs;
+ }
+
+ tmat4& operator*=(const T& rhs)
+ {
+ m_[0] *= rhs;
+ m_[1] *= rhs;
+ m_[2] *= rhs;
+ m_[3] *= rhs;
+ m_[4] *= rhs;
+ m_[5] *= rhs;
+ m_[6] *= rhs;
+ m_[7] *= rhs;
+ m_[8] *= rhs;
+ m_[9] *= rhs;
+ m_[10] *= rhs;
+ m_[11] *= rhs;
+ m_[12] *= rhs;
+ m_[13] *= rhs;
+ m_[14] *= rhs;
+ m_[15] *= rhs;
+ return *this;
+ }
+
+ const tmat4 operator*(const T& rhs)
+ {
+ return tmat4(*this) *= rhs;
+ }
+
+ tmat4& operator/=(const T& rhs)
+ {
+ m_[0] /= rhs;
+ m_[1] /= rhs;
+ m_[2] /= rhs;
+ m_[3] /= rhs;
+ m_[4] /= rhs;
+ m_[5] /= rhs;
+ m_[6] /= rhs;
+ m_[7] /= rhs;
+ m_[8] /= rhs;
+ m_[9] /= rhs;
+ m_[10] /= rhs;
+ m_[11] /= rhs;
+ m_[12] /= rhs;
+ m_[13] /= rhs;
+ m_[14] /= rhs;
+ m_[15] /= rhs;
+ return *this;
+ }
+
+ const tmat4 operator/(const T& rhs)
+ {
+ return tmat4(*this) /= rhs;
+ }
+
+ ArrayProxy<T, 4> operator[](int index)
+ {
+ return ArrayProxy<T, 4>(&m_[index]);
+ }
+ const ArrayProxy<T, 4> operator[](int index) const
+ {
+ return ArrayProxy<T, 4>(const_cast<T*>(&m_[index]));
+ }
+
+private:
+ T m_[16];
+};
+
+template<typename T>
+const tmat4<T> operator*(const T& lhs, const tmat4<T>& rhs)
+{
+ return tmat4<T>(rhs) * lhs;
+}
+
+template<typename T>
+const tvec4<T> operator*(const tvec4<T>& lhs, const tmat4<T>& rhs)
+{
+ T x((lhs.x() * rhs[0][0]) + (lhs.y() * rhs[1][0]) + (lhs.z() * rhs[2][0]) + (lhs.w() * rhs[3][0]));
+ T y((lhs.x() * rhs[0][1]) + (lhs.y() * rhs[1][1]) + (lhs.z() * rhs[2][1]) + (lhs.w() * rhs[3][1]));
+ T z((lhs.x() * rhs[0][2]) + (lhs.y() * rhs[1][2]) + (lhs.z() * rhs[2][2]) + (lhs.w() * rhs[3][2]));
+ T w((lhs.x() * rhs[0][3]) + (lhs.y() * rhs[1][3]) + (lhs.z() * rhs[2][3]) + (lhs.w() * rhs[3][3]));
+ return tvec4<T>(x, y, z, w);
+}
+
+template<typename T>
+const tvec4<T> operator*(const tmat4<T>& lhs, const tvec4<T>& rhs)
+{
+ T x((lhs[0][0] * rhs.x()) + (lhs[0][1] * rhs.y()) + (lhs[0][2] * rhs.z()) + (lhs[0][3] * rhs.w()));
+ T y((lhs[1][0] * rhs.x()) + (lhs[1][1] * rhs.y()) + (lhs[1][2] * rhs.z()) + (lhs[1][3] * rhs.w()));
+ T z((lhs[2][0] * rhs.x()) + (lhs[2][1] * rhs.y()) + (lhs[2][2] * rhs.z()) + (lhs[2][3] * rhs.w()));
+ T w((lhs[3][0] * rhs.x()) + (lhs[3][1] * rhs.y()) + (lhs[3][2] * rhs.z()) + (lhs[3][3] * rhs.w()));
+ return tvec4<T>(x, y, z, w);
+}
+
+template<typename T>
+const tmat4<T> outer(const tvec4<T>& a, const tvec4<T>& b)
+{
+ tmat4<T> product;
+ product[0][0] = a.x() * b.x();
+ product[0][1] = a.x() * b.y();
+ product[0][2] = a.x() * b.z();
+ product[0][3] = a.x() * b.w();
+ product[1][0] = a.y() * b.x();
+ product[1][1] = a.y() * b.y();
+ product[1][2] = a.y() * b.z();
+ product[1][3] = a.y() * b.w();
+ product[2][0] = a.z() * b.x();
+ product[2][1] = a.z() * b.y();
+ product[2][2] = a.z() * b.z();
+ product[2][3] = a.z() * b.w();
+ product[3][0] = a.w() * b.x();
+ product[3][1] = a.w() * b.y();
+ product[3][2] = a.w() * b.z();
+ product[3][3] = a.w() * b.w();
+ return product;
+}
+
+//
+// Convenience typedefs. These are here to present a homogeneous view of these
+// objects with respect to shader source.
+//
+typedef tmat2<float> mat2;
+typedef tmat3<float> mat3;
+typedef tmat4<float> mat4;
+
+typedef tmat2<double> dmat2;
+typedef tmat3<double> dmat3;
+typedef tmat4<double> dmat4;
+
+typedef tmat2<int> imat2;
+typedef tmat3<int> imat3;
+typedef tmat4<int> imat4;
+
+typedef tmat2<unsigned int> umat2;
+typedef tmat3<unsigned int> umat3;
+typedef tmat4<unsigned int> umat4;
+
+typedef tmat2<bool> bmat2;
+typedef tmat3<bool> bmat3;
+typedef tmat4<bool> bmat4;
+
+namespace Mat4
+{
+
+//
+// Some functions to generate transformation matrices that used to be provided
+// by OpenGL.
+//
+mat4 translate(float x, float y, float z);
+mat4 scale(float x, float y, float z);
+mat4 rotate(float angle, float x, float y, float z);
+mat4 frustum(float left, float right, float bottom, float top, float near, float far);
+mat4 ortho(float left, float right, float bottom, float top, float near, float far);
+mat4 perspective(float fovy, float aspect, float zNear, float zFar);
+mat4 lookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ);
+
+} // namespace Mat4
+} // namespace LibMatrix
+#endif // MAT_H_
=== added file 'src/libmatrix/matrix_inverse_test.cc'
@@ -0,0 +1,152 @@
+//
+// 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 <iostream>
+#include "mat.h"
+
+using LibMatrix::mat4;
+using LibMatrix::mat3;
+using LibMatrix::mat2;
+using std::cerr;
+using std::cout;
+using std::endl;
+
+bool mat2OK()
+{
+ mat2 m;
+ cout << "Starting with mat2 (should be identity): " << endl << endl;
+ m.print();
+
+ m[0][1] = -2.5;
+
+ cout << endl << "Matrix should now have (0, 1) == -2.500000" << endl << endl;
+ m.print();
+
+ mat2 mi(m);
+
+ cout << endl << "Copy of previous matrix (should have (0, 1) == -2.500000)" << endl << endl;
+ mi.print();
+
+ mi.inverse();
+
+ cout << endl << "Inverse of copy: " << endl << endl;
+ mi.print();
+
+ mat2 i = m * mi;
+
+ cout << endl << "Product of original and inverse (should be identity): " << endl << endl;
+ i.print();
+
+ mat2 ident;
+ if (i != ident)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool mat3OK()
+{
+ mat3 m;
+ cout << "Starting with mat3 (should be identity): " << endl << endl;
+ m.print();
+
+ m[1][2] = -2.5;
+
+ cout << endl << "Matrix should now have (1, 2) == -2.500000" << endl << endl;
+ m.print();
+
+ mat3 mi(m);
+
+ cout << endl << "Copy of previous matrix (should have (1, 2) == -2.500000)" << endl << endl;
+ mi.print();
+
+ mi.inverse();
+
+ cout << endl << "Inverse of copy: " << endl << endl;
+ mi.print();
+
+ mat3 i = m * mi;
+
+ cout << endl << "Product of original and inverse (should be identity): " << endl << endl;
+ i.print();
+
+ mat3 ident;
+ if (i != ident)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool mat4OK()
+{
+ mat4 m;
+ cout << "Starting with mat4 (should be identity): " << endl << endl;
+ m.print();
+
+ m[2][3] = -2.5;
+
+ cout << endl << "Matrix should now have (2, 3) == -2.500000" << endl << endl;
+ m.print();
+
+ mat4 mi(m);
+
+ cout << endl << "Copy of previous matrix (should have (2, 3) == -2.500000)" << endl << endl;
+ mi.print();
+
+ mi.inverse();
+
+ cout << endl << "Inverse of copy: " << endl << endl;
+ mi.print();
+
+ mat4 i = m * mi;
+
+ cout << endl << "Product of original and inverse (should be identity): " << endl << endl;
+ i.print();
+
+ mat4 ident;
+ if (i != ident)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+int
+main(int argc, char** argv)
+{
+ if (!mat2OK())
+ {
+ cerr << "mat2::inverse() does not work!" << endl;
+ return 1;
+ }
+ cout << "mat2::inverse() is okay!" << endl << endl;
+
+ if (!mat3OK())
+ {
+ cerr << "mat3::inverse() does not work!" << endl;
+ return 1;
+ }
+ cout << "mat3::inverse() is okay!" << endl << endl;
+
+ if (!mat4OK())
+ {
+ cerr << "mat4::inverse() does not work!" << endl;
+ return 1;
+ }
+ cout << "mat4::inverse() is okay!" << endl << endl;
+
+ return 0;
+}
=== added file 'src/libmatrix/program.cc'
@@ -0,0 +1,363 @@
+//
+// Copyright (c) 2011 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 <string>
+#include <vector>
+#include <sstream>
+#include <fstream>
+#include <iostream>
+
+#include "oglsdl.h"
+#include "program.h"
+
+using std::string;
+using LibMatrix::mat4;
+using LibMatrix::vec2;
+using LibMatrix::vec3;
+using LibMatrix::vec4;
+
+bool
+gotSource(const string& filename, string& source)
+{
+ using std::ifstream;
+ ifstream inputFile(filename.c_str());
+ if (!inputFile)
+ {
+ std::cerr << "Failed to open \"" << filename << "\"" << std::endl;
+ return false;
+ }
+
+ string curLine;
+ while (getline(inputFile, curLine))
+ {
+ source += curLine;
+ source += '\n';
+ }
+
+ return true;
+}
+
+Shader::Shader(unsigned int type, const string& source) :
+ handle_(0),
+ type_(type),
+ source_(source),
+ ready_(false),
+ valid_(false)
+{
+ // Create our shader and setup the source code.
+ handle_ = glCreateShader(type);
+ if (!handle_)
+ {
+ message_ = string("Failed to create the new shader.");
+ return;
+ }
+ const GLchar* shaderSource = source_.c_str();
+ glShaderSource(handle_, 1, &shaderSource, NULL);
+ GLint param = 0;
+ glGetShaderiv(handle_, GL_SHADER_SOURCE_LENGTH, ¶m);
+ if (static_cast<unsigned int>(param) != source_.length() + 1)
+ {
+ std::ostringstream o(string("Expected shader source length "));
+ o << source_.length() << ", but got " << param << std::endl;
+ message_ = o.str();
+ return;
+ }
+ valid_ = true;
+}
+
+Shader::~Shader()
+{
+ handle_ = 0;
+ type_ = 0;
+ ready_ = false;
+ valid_ = false;
+}
+
+void
+Shader::compile()
+{
+ // Make sure we have a good shader and haven't already compiled it.
+ if (!valid_ || ready_)
+ {
+ return;
+ }
+ glCompileShader(handle_);
+ GLint param = 0;
+ glGetShaderiv(handle_, GL_COMPILE_STATUS, ¶m);
+ if (param == GL_FALSE)
+ {
+ glGetShaderiv(handle_, GL_INFO_LOG_LENGTH, ¶m);
+ GLchar* infoLog = new GLchar[param + 1];
+ glGetShaderInfoLog(handle_, param + 1, NULL, infoLog);
+ message_ = infoLog;
+ delete [] infoLog;
+ return;
+ }
+ ready_ = true;
+}
+
+void
+Shader::attach(unsigned int program)
+{
+ // Shader must be valid and compiled to be attached to a program.
+ if (!valid_ || !ready_)
+ {
+ return;
+ }
+ glAttachShader(program, handle_);
+}
+
+void
+Shader::release()
+{
+ if (handle_)
+ {
+ glDeleteShader(handle_);
+ }
+ handle_ = 0;
+ type_ = 0;
+ ready_ = false;
+ valid_ = false;
+}
+
+Program::Program() :
+ handle_(0),
+ ready_(false),
+ valid_(false)
+{
+}
+
+Program::~Program()
+{
+ // First release all of the shader resources attached to us and clean up
+ // our handle.
+ release();
+}
+
+void
+Program::init()
+{
+ handle_ = glCreateProgram();
+ if (!handle_)
+ {
+ message_ = string("Failed to create the new program");
+ return;
+ }
+
+ valid_ = true;
+}
+
+void
+Program::release()
+{
+ // First delete all of the shader resources attached to us.
+ for (std::vector<Shader>::iterator shaderIt = shaders_.begin(); shaderIt != shaders_.end(); shaderIt++)
+ {
+ shaderIt->release();
+ }
+
+ // Clear out the shader vector so we're ready to reuse it.
+ shaders_.clear();
+
+ // Clear out the error string to make sure we don't return anything stale.
+ message_.clear();
+
+ if (handle_)
+ {
+ glDeleteProgram(handle_);
+ }
+ handle_ = 0;
+ ready_ = false;
+ valid_ = false;
+}
+void
+Program::addShader(unsigned int type, const string& source)
+{
+ if (!valid_)
+ {
+ return;
+ }
+
+ Shader shader(type, source);
+ if (!shader.valid())
+ {
+ message_ = shader.errorMessage();
+ valid_ = false;
+ return;
+ }
+
+ shader.compile();
+
+ if (!shader.ready())
+ {
+ message_ = shader.errorMessage();
+ valid_ = false;
+ return;
+ }
+
+ shader.attach(handle_);
+ shaders_.push_back(shader);
+ return;
+}
+
+void
+Program::build()
+{
+ if (!valid_ || ready_)
+ {
+ return;
+ }
+
+ if (shaders_.empty())
+ {
+ message_ = string("There are no shaders attached to this program");
+ return;
+ }
+
+ glLinkProgram(handle_);
+ GLint param = 1;
+ glGetProgramiv(handle_, GL_LINK_STATUS, ¶m);
+ if (param == GL_FALSE)
+ {
+ glGetProgramiv(handle_, GL_INFO_LOG_LENGTH, ¶m);
+ GLchar* infoLog = new GLchar[param + 1];
+ glGetProgramInfoLog(handle_, param + 1, NULL, infoLog);
+ message_ = infoLog;
+ delete [] infoLog;
+ return;
+ }
+ ready_ = true;
+}
+
+void
+Program::start()
+{
+ if (!valid_ || !ready_)
+ {
+ return;
+ }
+ glUseProgram(handle_);
+}
+
+void
+Program::stop()
+{
+ glUseProgram(0);
+}
+
+void
+Program::loadUniformMatrix(const mat4& m, const string& name)
+{
+ ready_ = false;
+ GLint location = glGetUniformLocation(handle_, name.c_str());
+ if (location < 0)
+ {
+ message_ = string("Failed to get uniform location for \"") + name +
+ string("\"");
+ return;
+ }
+
+ // Our matrix representation is column-major, so transpose is false here.
+ glUniformMatrix4fv(location, 1, GL_FALSE, m);
+ ready_ = true;
+}
+
+void
+Program::loadUniformVector(const vec2& v, const string& name)
+{
+ ready_ = false;
+ GLint location = glGetUniformLocation(handle_, name.c_str());
+ if (location < 0)
+ {
+ message_ = string("Failed to get uniform location for \"") + name +
+ string("\"");
+ return;
+ }
+
+ glUniform2fv(location, 1, v);
+ ready_ = true;
+}
+
+void
+Program::loadUniformVector(const vec3& v, const string& name)
+{
+ ready_ = false;
+ GLint location = glGetUniformLocation(handle_, name.c_str());
+ if (location < 0)
+ {
+ message_ = string("Failed to get uniform location for \"") + name +
+ string("\"");
+ return;
+ }
+
+ glUniform3fv(location, 1, v);
+ ready_ = true;
+}
+
+void
+Program::loadUniformVector(const vec4& v, const string& name)
+{
+ ready_ = false;
+ GLint location = glGetUniformLocation(handle_, name.c_str());
+ if (location < 0)
+ {
+ message_ = string("Failed to get uniform location for \"") + name +
+ string("\"");
+ return;
+ }
+
+ glUniform4fv(location, 1, v);
+ ready_ = true;
+}
+
+void
+Program::loadUniformScalar(const float& f, const string& name)
+{
+ ready_ = false;
+ GLint location = glGetUniformLocation(handle_, name.c_str());
+ if (location < 0)
+ {
+ message_ = string("Failed to get uniform location for \"") + name +
+ string("\"");
+ return;
+ }
+
+ glUniform1f(location, f);
+ ready_ = true;
+}
+
+void
+Program::loadUniformScalar(const int& i, const string& name)
+{
+ ready_ = false;
+ GLint location = glGetUniformLocation(handle_, name.c_str());
+ if (location < 0)
+ {
+ message_ = string("Failed to get uniform location for \"") + name +
+ string("\"");
+ return;
+ }
+
+ glUniform1i(location, i);
+ ready_ = true;
+}
+
+int
+Program::getAttribIndex(const string& name)
+{
+ GLint index = glGetAttribLocation(handle_, name.c_str());
+ if (index < 0)
+ {
+ message_ = string("Failed to get attribute location for \"") + name +
+ string("\"");
+ }
+ return index;
+}
=== added file 'src/libmatrix/program.h'
@@ -0,0 +1,151 @@
+//
+// Copyright (c) 2011 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.
+//
+#ifndef PROGRAM_H_
+#define PROGRAM_H_
+
+#include <string>
+#include <vector>
+#include "mat.h"
+
+// Simple shader container. Abstracts all of the OpenGL bits, but leaves
+// much of the semantics intact. This is typically only referenced directly
+// by the program object.
+class Shader
+{
+public:
+ Shader() :
+ handle_(0),
+ type_(0),
+ ready_(false),
+ valid_(false) {}
+ Shader(const Shader& shader) :
+ handle_(shader.handle_),
+ type_(shader.type_),
+ source_(shader.source_),
+ message_(shader.message_),
+ ready_(shader.ready_),
+ valid_(shader.valid_) {}
+ Shader(unsigned int type, const std::string& source);
+ ~Shader();
+
+ // Compiles the shader source so that it can be linked into a
+ // program.
+ //
+ // Make sure the shader is "valid" before calling this one.
+ void compile();
+
+ // Attaches a compiled shader to a program in preparation for
+ // linking.
+ //
+ // Make sure the shader is "ready" before calling this one.
+ void attach(unsigned int program);
+
+ // Release any resources associated with this shader back to
+ // OpenGL
+ void release();
+
+ // If "valid" then the shader has successfully been created.
+ // If "ready" then the shader has successfully been compiled.
+ // If either is false, then additional information can be obtained
+ // from the error message.
+ bool valid() const { return valid_; }
+ bool ready() const { return ready_; }
+ const std::string& errorMessage() const { return message_; }
+
+private:
+ unsigned int handle_;
+ unsigned int type_;
+ std::string source_;
+ std::string message_;
+ bool ready_;
+ bool valid_;
+};
+
+// Simple program container. Abstracts all of the OpenGL bits, but leaves
+// much of the semantics intact.
+class Program
+{
+public:
+ Program();
+ ~Program();
+
+ // Initialize the program object for use.
+ void init();
+
+ // Release any resources associated with this program back to
+ // OpenGL
+ void release();
+
+ // Create a new shader of the given type and source, compile it and
+ // attach it to the program.
+ //
+ // Make sure the program is "valid" before calling this one.
+ void addShader(unsigned int type, const std::string& source);
+
+ // Link all of the attached shaders into a runnable program for use
+ // in a rendering operation.
+ //
+ // Make sure the program is "valid" and that at least one shader
+ // has been successfully added before calling this one.
+ void build();
+
+ // Bind the program for use by the rendering context (i.e. actually
+ // run it).
+ //
+ // Make sure the program is "ready" before calling this one.
+ void start();
+
+ // Unbind the program from use by the rendering context (i.e. stop
+ // using it).
+ void stop();
+
+ // These members cause data to be bound to program variables, so
+ // the program must be bound for use for these to be effective.
+ //
+ // Load a matrix into the named uniform variable in the program.
+ void loadUniformMatrix(const LibMatrix::mat4& m, const std::string& name);
+ // Load a vector into the named uniform variable in the program.
+ void loadUniformVector(const LibMatrix::vec2& v, const std::string& name);
+ // Load a vector into the named uniform variable in the program.
+ void loadUniformVector(const LibMatrix::vec3& v, const std::string& name);
+ // Load a vector into the named uniform variable in the program.
+ void loadUniformVector(const LibMatrix::vec4& v, const std::string& name);
+ // Load a scalar into the named uniform variable in the program.
+ void loadUniformScalar(const float& f, const std::string& name);
+ // Load a scalar into the named uniform variable in the program.
+ void loadUniformScalar(const int& i, const std::string& name);
+
+ // Get the handle to a named program input (the location in OpenGL
+ // vernacular). Typically used in conjunction with various VertexAttrib
+ // interfaces.
+ int getAttribIndex(const std::string& name);
+
+ // If "valid" then the program has successfully been created.
+ // If "ready" then the program has successfully been built.
+ // If either is false, then additional information can be obtained
+ // from the error message.
+ bool valid() const { return valid_; }
+ bool ready() const { return ready_; }
+ const std::string& errorMessage() const { return message_; }
+
+private:
+ unsigned int handle_;
+ std::vector<Shader> shaders_;
+ std::string message_;
+ bool ready_;
+ bool valid_;
+};
+
+// Handy utility for extracting shader source from a named file
+bool gotSource(const std::string& filename, std::string& sourceOut);
+
+#endif // PROGRAM_H_
=== added file 'src/libmatrix/stack.h'
@@ -0,0 +1,106 @@
+//
+// 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.
+//
+#ifndef STACK_H_
+#define STACK_H_
+
+#include <vector>
+#include "mat.h"
+
+namespace LibMatrix
+{
+//
+// Simple matrix stack implementation suitable for tracking OpenGL matrix
+// state. Default construction puts an identity matrix on the top of the
+// stack.
+//
+template<typename T>
+class MatrixStack
+{
+public:
+ MatrixStack()
+ {
+ theStack_.push_back(T());
+ }
+ MatrixStack(const T& matrix)
+ {
+ theStack_.push_back(matrix);
+ }
+ ~MatrixStack() {}
+
+ const T& getCurrent() const { return theStack_.back(); }
+
+ void push()
+ {
+ theStack_.push_back(theStack_.back());
+ }
+ void pop()
+ {
+ theStack_.pop_back();
+ }
+ void loadIdentity()
+ {
+ theStack_.back().setIdentity();
+ }
+ T& operator*=(const T& rhs)
+ {
+ T& curMatrix = theStack_.back();
+ curMatrix *= rhs;
+ return curMatrix;
+ }
+ void print() const
+ {
+ const T& curMatrix = theStack_.back();
+ curMatrix.print();
+ }
+ unsigned int getDepth() const { return theStack_.size(); }
+private:
+ std::vector<T> theStack_;
+};
+
+class Stack4 : public MatrixStack<mat4>
+{
+public:
+ void translate(float x, float y, float z)
+ {
+ *this *= Mat4::translate(x, y, z);
+ }
+ void scale(float x, float y, float z)
+ {
+ *this *= Mat4::scale(x, y, z);
+ }
+ void rotate(float angle, float x, float y, float z)
+ {
+ *this *= Mat4::rotate(angle, x, y, z);
+ }
+ void frustum(float left, float right, float bottom, float top, float near, float far)
+ {
+ *this *= Mat4::frustum(left, right, bottom, top, near, far);
+ }
+ void ortho(float left, float right, float bottom, float top, float near, float far)
+ {
+ *this *= Mat4::ortho(left, right, bottom, top, near, far);
+ }
+ void perspective(float fovy, float aspect, float zNear, float zFar)
+ {
+ *this *= Mat4::perspective(fovy, aspect, zNear, zFar);
+ }
+ void lookAt(float eyeX, float eyeY, float eyeZ,
+ float centerX, float centerY, float centerZ,
+ float upX, float upY, float upZ)
+ {
+ *this *= Mat4::lookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
+ }
+};
+
+} // namespace LibMatrix
+
+#endif // STACK_H_
=== added file 'src/libmatrix/vec.h'
@@ -0,0 +1,500 @@
+//
+// 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.
+//
+#ifndef VEC_H_
+#define VEC_H_
+
+#include <iostream> // only needed for print() functions...
+#include <math.h>
+
+namespace LibMatrix
+{
+template<typename T>
+class tvec2
+{
+public:
+ tvec2() :
+ x_(0),
+ y_(0) {}
+ tvec2(T t) :
+ x_(t),
+ y_(t) {}
+ tvec2(T x, T y) :
+ x_(x),
+ y_(y) {}
+ tvec2(const tvec2& v) :
+ x_(v.x_),
+ y_(v.y_) {}
+ ~tvec2() {}
+
+ void print() const
+ {
+ std::cout << "| " << x_ << " " << y_ << " |" << std::endl;
+ }
+ operator const T*() const { return &x_;}
+
+ const T x() const { return x_; }
+ const T y() const { return y_; }
+
+ void x(const T& val) { x_ = val; }
+ void y(const T& val) { y_ = val; }
+
+ tvec2& operator=(const tvec2& rhs)
+ {
+ if (this != &rhs)
+ {
+ x_ = rhs.x_;
+ y_ = rhs.y_;
+ }
+ return *this;
+ }
+
+ tvec2& operator/=(const T& rhs)
+ {
+ x_ /= rhs;
+ y_ /= rhs;
+ return *this;
+ }
+
+ const tvec2 operator/(const T& rhs)
+ {
+ return tvec2(*this) /= rhs;
+ }
+
+ tvec2& operator*=(const T& rhs)
+ {
+ x_ *= rhs;
+ y_ *= rhs;
+ return *this;
+ }
+
+ const tvec2 operator*(const T& rhs)
+ {
+ return tvec2(*this) *= rhs;
+ }
+
+ tvec2& operator+=(const T& rhs)
+ {
+ x_ += rhs;
+ y_ += rhs;
+ return *this;
+ }
+
+ const tvec2 operator+(const T& rhs)
+ {
+ return tvec2(*this) += rhs;
+ }
+
+ tvec2& operator+=(const tvec2& rhs)
+ {
+ x_ += rhs.x_;
+ y_ += rhs.y_;
+ return *this;
+ }
+
+ const tvec2 operator+(const tvec2& rhs)
+ {
+ return tvec2(*this) += rhs;
+ }
+
+ tvec2& operator-=(const T& rhs)
+ {
+ x_ -= rhs;
+ y_ -= rhs;
+ return *this;
+ }
+
+ const tvec2 operator-(const T& rhs)
+ {
+ return tvec2(*this) -= rhs;
+ }
+
+ tvec2& operator-=(const tvec2& rhs)
+ {
+ x_ -= rhs.x_;
+ y_ -= rhs.y_;
+ return *this;
+ }
+
+ const tvec2 operator-(const tvec2& rhs)
+ {
+ return tvec2(*this) -= rhs;
+ }
+
+ float length() const
+ {
+ return sqrt(dot(*this, *this));
+ }
+
+ void normalize()
+ {
+ float l = length();
+ x_ /= l;
+ y_ /= l;
+ }
+
+ static T dot(const tvec2& v1, const tvec2& v2)
+ {
+ return (v1.x_ * v2.x_) + (v1.y_ * v2.y_);
+ }
+
+private:
+ T x_;
+ T y_;
+};
+
+template<typename T>
+class tvec3
+{
+public:
+ tvec3() :
+ x_(0),
+ y_(0),
+ z_(0) {}
+ tvec3(T t) :
+ x_(t),
+ y_(t),
+ z_(t) {}
+ tvec3(T x, T y, T z) :
+ x_(x),
+ y_(y),
+ z_(z) {}
+ tvec3(const tvec3& v) :
+ x_(v.x_),
+ y_(v.y_),
+ z_(v.z_) {}
+ ~tvec3() {}
+
+ void print() const
+ {
+ std::cout << "| " << x_ << " " << y_ << " " << z_ << " |" << std::endl;
+ }
+ operator const T*() const { return &x_;}
+
+ const T x() const { return x_; }
+ const T y() const { return y_; }
+ const T z() const { return z_; }
+
+ void x(const T& val) { x_ = val; }
+ void y(const T& val) { y_ = val; }
+ void z(const T& val) { z_ = val; }
+
+ tvec3& operator=(const tvec3& rhs)
+ {
+ if (this != &rhs)
+ {
+ x_ = rhs.x_;
+ y_ = rhs.y_;
+ z_ = rhs.z_;
+ }
+ return *this;
+ }
+
+ tvec3& operator/=(const T& rhs)
+ {
+ x_ /= rhs;
+ y_ /= rhs;
+ z_ /= rhs;
+ return *this;
+ }
+
+ const tvec3 operator/(const T& rhs)
+ {
+ return tvec3(*this) /= rhs;
+ }
+
+ tvec3& operator*=(const T& rhs)
+ {
+ x_ *= rhs;
+ y_ *= rhs;
+ z_ *= rhs;
+ return *this;
+ }
+
+ const tvec3 operator*(const T& rhs)
+ {
+ return tvec3(*this) *= rhs;
+ }
+
+ tvec3& operator+=(const T& rhs)
+ {
+ x_ += rhs;
+ y_ += rhs;
+ z_ += rhs;
+ return *this;
+ }
+
+ const tvec3 operator+(const T& rhs)
+ {
+ return tvec3(*this) += rhs;
+ }
+
+ tvec3& operator+=(const tvec3& rhs)
+ {
+ x_ += rhs.x_;
+ y_ += rhs.y_;
+ z_ += rhs.z_;
+ return *this;
+ }
+
+ const tvec3 operator+(const tvec3& rhs)
+ {
+ return tvec3(*this) += rhs;
+ }
+
+ tvec3& operator-=(const T& rhs)
+ {
+ x_ -= rhs;
+ y_ -= rhs;
+ z_ -= rhs;
+ return *this;
+ }
+
+ const tvec3 operator-(const T& rhs)
+ {
+ return tvec3(*this) -= rhs;
+ }
+
+ tvec3& operator-=(const tvec3& rhs)
+ {
+ x_ -= rhs.x_;
+ y_ -= rhs.y_;
+ z_ -= rhs.z_;
+ return *this;
+ }
+
+ const tvec3 operator-(const tvec3& rhs)
+ {
+ return tvec3(*this) -= rhs;
+ }
+
+ float length() const
+ {
+ return sqrt(dot(*this, *this));
+ }
+
+ void normalize()
+ {
+ float l = length();
+ x_ /= l;
+ y_ /= l;
+ z_ /= l;
+ }
+
+ static T dot(const tvec3& v1, const tvec3& v2)
+ {
+ return (v1.x_ * v2.x_) + (v1.y_ * v2.y_) + (v1.z_ * v2.z_);
+ }
+
+ static tvec3 cross(const tvec3& u, const tvec3& v)
+ {
+ return tvec3((u.y_ * v.z_) - (u.z_ * v.y_),
+ (u.z_ * v.x_) - (u.x_ * v.z_),
+ (u.x_ * v.y_) - (u.y_ * v.x_));
+ }
+
+private:
+ T x_;
+ T y_;
+ T z_;
+};
+
+template<typename T>
+class tvec4
+{
+public:
+ tvec4() :
+ x_(0),
+ y_(0),
+ z_(0),
+ w_(0) {}
+ tvec4(T t) :
+ x_(t),
+ y_(t),
+ z_(t),
+ w_(t) {}
+ tvec4(T x, T y, T z, T w) :
+ x_(x),
+ y_(y),
+ z_(z),
+ w_(w) {}
+ tvec4(const tvec4& v) :
+ x_(v.x_),
+ y_(v.y_),
+ z_(v.z_),
+ w_(v.w_) {}
+ ~tvec4() {}
+
+ void print() const
+ {
+ std::cout << "| " << x_ << " " << y_ << " " << z_ << " " << w_ << " |" << std::endl;
+ }
+ operator const T*() const { return &x_;}
+
+ const T x() const { return x_; }
+ const T y() const { return y_; }
+ const T z() const { return z_; }
+ const T w() const { return w_; }
+
+ void x(const T& val) { x_ = val; }
+ void y(const T& val) { y_ = val; }
+ void z(const T& val) { z_ = val; }
+ void w(const T& val) { w_ = val; }
+
+ tvec4& operator=(const tvec4& rhs)
+ {
+ if (this != &rhs)
+ {
+ x_ = rhs.x_;
+ y_ = rhs.y_;
+ z_ = rhs.z_;
+ w_ = rhs.w_;
+ }
+ return *this;
+ }
+
+ tvec4& operator/=(const T& rhs)
+ {
+ x_ /= rhs;
+ y_ /= rhs;
+ z_ /= rhs;
+ w_ /= rhs;
+ return *this;
+ }
+
+ const tvec4 operator/(const T& rhs)
+ {
+ return tvec4(*this) /= rhs;
+ }
+
+ tvec4& operator*=(const T& rhs)
+ {
+ x_ *= rhs;
+ y_ *= rhs;
+ z_ *= rhs;
+ w_ *= rhs;
+ return *this;
+ }
+
+ const tvec4 operator*(const T& rhs)
+ {
+ return tvec4(*this) *= rhs;
+ }
+
+ tvec4& operator+=(const T& rhs)
+ {
+ x_ += rhs;
+ y_ += rhs;
+ z_ += rhs;
+ w_ += rhs;
+ return *this;
+ }
+
+ const tvec4 operator+(const T& rhs)
+ {
+ return tvec4(*this) += rhs;
+ }
+
+ tvec4& operator+=(const tvec4& rhs)
+ {
+ x_ += rhs.x_;
+ y_ += rhs.y_;
+ z_ += rhs.z_;
+ w_ += rhs.w_;
+ return *this;
+ }
+
+ const tvec4 operator+(const tvec4& rhs)
+ {
+ return tvec4(*this) += rhs;
+ }
+
+ tvec4& operator-=(const T& rhs)
+ {
+ x_ -= rhs;
+ y_ -= rhs;
+ z_ -= rhs;
+ w_ -= rhs;
+ return *this;
+ }
+
+ const tvec4 operator-(const T& rhs)
+ {
+ return tvec4(*this) -= rhs;
+ }
+
+ tvec4& operator-=(const tvec4& rhs)
+ {
+ x_ -= rhs.x_;
+ y_ -= rhs.y_;
+ z_ -= rhs.z_;
+ w_ -= rhs.w_;
+ return *this;
+ }
+
+ const tvec4 operator-(const tvec4& rhs)
+ {
+ return tvec4(*this) -= rhs;
+ }
+
+ float length() const
+ {
+ return sqrt(dot(*this, *this));
+ }
+
+ void normalize()
+ {
+ float l = length();
+ x_ /= l;
+ y_ /= l;
+ z_ /= l;
+ w_ /= l;
+ }
+
+ static T dot(const tvec4& v1, const tvec4& v2)
+ {
+ return (v1.x_ * v2.x_) + (v1.y_ * v2.y_) + (v1.z_ * v2.z_) + (v1.w_ * v2.w_);
+ }
+
+private:
+ T x_;
+ T y_;
+ T z_;
+ T w_;
+};
+
+//
+// Convenience typedefs. These are here to present a homogeneous view of these
+// objects with respect to shader source.
+//
+typedef tvec2<float> vec2;
+typedef tvec3<float> vec3;
+typedef tvec4<float> vec4;
+
+typedef tvec2<double> dvec2;
+typedef tvec3<double> dvec3;
+typedef tvec4<double> dvec4;
+
+typedef tvec2<int> ivec2;
+typedef tvec3<int> ivec3;
+typedef tvec4<int> ivec4;
+
+typedef tvec2<unsigned int> uvec2;
+typedef tvec3<unsigned int> uvec3;
+typedef tvec4<unsigned int> uvec4;
+
+typedef tvec2<bool> bvec2;
+typedef tvec3<bool> bvec3;
+typedef tvec4<bool> bvec4;
+
+} // namespace LibMatrix
+
+#endif // VEC_H_
=== removed file 'src/matrix.cpp'
@@ -1,265 +0,0 @@
-/*
- * Copyright © 2010-2011 Linaro Limited
- *
- * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
- *
- * glmark2 is free software: you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later
- * version.
- *
- * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * glmark2. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Alexandros Frantzis (glmark2)
- */
-#include "matrix.h"
-
-/**
- * Multiply arrays representing 4x4 matrices in column-major order.
- *
- * The result is stored in the first matrix.
- *
- * @param m the first matrix
- * @param n the second matrix
- */
-static void multiply(GLfloat *m, const GLfloat *n)
-{
- GLfloat tmp[16];
- const GLfloat *row, *column;
- div_t d;
- int i, j;
-
- for (i = 0; i < 16; i++) {
- tmp[i] = 0;
- d = div(i, 4);
- row = n + d.quot * 4;
- column = m + d.rem;
- for (j = 0; j < 4; j++)
- tmp[i] += row[j] * column[j * 4];
- }
- memcpy(m, &tmp, sizeof tmp);
-}
-
-/**
- * Multiply this matrix with another.
- *
- * @param pM the matrix to multiply with.
- *
- * @return reference to this matrix (multiplied)
- */
-Matrix4f &Matrix4f::operator*=(const Matrix4f &pM)
-{
- multiply(m, pM.m);
-
- return *this;
-}
-
-/**
- * Rotates a matrix.
- *
- * @param angle the angle to rotate
- * @param x the x component of the rotation axis
- * @param y the y component of the rotation axis
- * @param z the z component of the rotation axis
- *
- * @return reference to the matrix
- */
-Matrix4f &Matrix4f::rotate(GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
-{
- double s, c;
-
- sincos(angle, &s, &c);
-
- GLfloat r[16] = {
- x * x * (1 - c) + c, y * x * (1 - c) + z * s, x * z * (1 - c) - y * s, 0,
- x * y * (1 - c) - z * s, y * y * (1 - c) + c, y * z * (1 - c) + x * s, 0,
- x * z * (1 - c) + y * s, y * z * (1 - c) - x * s, z * z * (1 - c) + c, 0,
- 0, 0, 0, 1
- };
-
- multiply(m, r);
-
- return *this;
-}
-
-/**
- * Translates a matrix.
- *
- * @param x the x component of the translation
- * @param y the y component of the translation
- * @param z the z component of the translation
- *
- * @return reference to the matrix
- */
-Matrix4f &Matrix4f::translate(GLfloat x, GLfloat y, GLfloat z)
-{
- GLfloat t[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 };
-
- multiply(m, t);
-
- return *this;
-}
-
-/**
- * Transposes a matrix.
- *
- * @return reference to the matrix
- */
-Matrix4f &Matrix4f::transpose()
-{
- GLfloat t[16] = {
- m[0], m[4], m[8], m[12],
- m[1], m[5], m[9], m[13],
- m[2], m[6], m[10], m[14],
- m[3], m[7], m[11], m[15]};
-
- memcpy(m, t, sizeof(m));
-
- return *this;
-}
-
-/**
- * Makes this matrix an identity matrix.
- *
- * @return reference to the matrix
- */
-Matrix4f &Matrix4f::identity()
-{
- m[0] = 1.0; m[4] = 0.0; m[8] = 0.0; m[12] = 0.0;
- m[1] = 0.0; m[5] = 1.0; m[9] = 0.0; m[13] = 0.0;
- m[2] = 0.0; m[6] = 0.0; m[10] = 1.0; m[14] = 0.0;
- m[3] = 0.0; m[7] = 0.0; m[11] = 0.0; m[15] = 1.0;
-
- return *this;
-}
-
-/**
- * Makes this matrix a perspective projection matrix.
- *
- * @param fovy field of view angle in degrees in the y direction
- * @param aspect aspect ratio of view
- * @param zNear the distance from the viewer to the near clipping plane
- * @param zFar the distance from the viewer to the far clipping plane
- *
- * @return reference to the matrix
- */
-Matrix4f &Matrix4f::perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar)
-{
- GLfloat sine, cotangent, deltaZ;
- GLfloat radians = fovy / 2 * M_PI / 180;
-
- deltaZ = zFar - zNear;
- sine = sin(radians);
-
- if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) {
- return *this;
- }
-
- cotangent = cos(radians) / sine;
-
- identity();
- m[0] = cotangent / aspect;
- m[5] = cotangent;
- m[10] = -(zFar + zNear) / deltaZ;
- m[11] = -1;
- m[14] = -2 * zNear * zFar / deltaZ;
- m[15] = 0;
-
- return *this;
-}
-
-/**
- * Inverts this matrix.
- *
- * This method can currently handle only pure translation-rotation matrices.
- *
- * @return reference to the matrix
- */
-Matrix4f &Matrix4f::invert()
-{
- // If the bottom row is [0, 0, 0, 1] this is a pure translation-rotation
- // transformation matrix and we can optimize the matrix inversion.
- // Read http://www.gamedev.net/community/forums/topic.asp?topic_id=425118
- // for an explanation.
- if (m[3] == 0.0 && m[7] == 0.0 && m[11] == 0.0 && m[15] == 1.0) {
- // Extract and invert the translation part 't'. The inverse of a
- // translation matrix can be calculated by negating the translation
- // coordinates.
- Matrix4f t(1.0, 1.0, 1.0);
- t.m[12] = -m[12]; t.m[13] = -m[13]; t.m[14] = -m[14];
-
- // Invert the rotation part 'r'. The inverse of a rotation matrix is
- // equal to its transpose.
- m[12] = m[13] = m[14] = 0;
- this->transpose();
-
- // inv(m) = inv(r) * inv(t)
- *this *= t;
- }
- else {
- // Don't care about the general case for now
- }
-
- return *this;
-}
-
-/**
- * Creates an empty matrix.
- *
- * All matrix components are 0.0 expect the lower right
- * which is 1.0.
- */
-Matrix4f::Matrix4f()
-{
- memset(m, 0, sizeof(m));
- m[15] = 1.0;
-}
-
-/**
- * Copy constructor.
- *
- * @param mat the matrix to copy the contents of.
- */
-Matrix4f::Matrix4f(Matrix4f &mat)
-{
- memcpy(m, mat.m, sizeof(m));
-}
-
-/**
- * Creates a matrix with specified values in the diagonal.
- *
- * The lower right value is initialized to 1.0.
- *
- * @param x the x component of the diagonal
- * @param y the y component of the diagonal
- * @param z the z component of the diagonal
- */
-Matrix4f::Matrix4f(GLfloat x, GLfloat y, GLfloat z)
-{
- memset(m, 0, sizeof(m));
- m[0] = x;
- m[5] = y;
- m[10] = z;
- m[15] = 1.0;
-}
-
-/**
- * Displays a matrix.
- *
- * @param str string to display before matrix
- */
-void Matrix4f::display(const char *str)
-{
- int r;
- if (str != NULL)
- printf("%s\n", str);
- for(r = 0; r < 4; r++)
- printf("%f %f %f %f\n", m[r], m[r + 4], m[r + 8], m[r + 12]);
-}
=== removed file 'src/matrix.h'
@@ -1,52 +0,0 @@
-/*
- * Copyright © 2010-2011 Linaro Limited
- *
- * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
- *
- * glmark2 is free software: you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later
- * version.
- *
- * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * glmark2. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Alexandros Frantzis (glmark2)
- */
-#ifndef GLMARK2_MATRIX_H_
-#define GLMARK2_MATRIX_H_
-
-#include "oglsdl.h"
-
-#include <stdio.h>
-#include <math.h>
-
-class Matrix4f
-{
-
-public:
- GLfloat m[16];
-
- Matrix4f();
- Matrix4f(Matrix4f &mat);
- Matrix4f(GLfloat x, GLfloat y, GLfloat z);
-
- Matrix4f &translate(GLfloat x, GLfloat y, GLfloat z);
- Matrix4f &rotate(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
- Matrix4f &transpose();
- Matrix4f &perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar);
- Matrix4f &identity();
- Matrix4f &invert();
-
- Matrix4f &operator*=(const Matrix4f &pM);
-
- void display(const char *str);
-};
-
-#endif
=== modified file 'src/mesh.cpp'
@@ -22,17 +22,7 @@
* Alexandros Frantzis (glmark2)
*/
#include "mesh.h"
-#include "shader.h"
-
-Texel::Texel()
-{
- u = 0; v = 0;
-}
-
-Texel::Texel(GLfloat pU, GLfloat pV)
-{
- u = pU; v = pV;
-}
+
Mesh::Mesh()
{
@@ -74,7 +64,7 @@
unsigned i, j;
unsigned k = 0;
- Vector3f a, b, c, d, n;
+ LibMatrix::vec3 a, b, c, d, n;
mMode = GL_TRIANGLES;
mVertexQty = wraps_qty * per_wrap_qty * 6;
@@ -87,60 +77,66 @@
float phi = 2 * M_PI * wrap_frac;
float theta = 2 * M_PI * (i + wrap_frac) / (float)wraps_qty;
float r = major_radius + minor_radius * (float)cos(phi);
- a.x = (float)sin(theta) * r;
- a.y = minor_radius * (float)sin(phi);
- a.z = (float)cos(theta) * r;
+ a.x((float)sin(theta) * r);
+ a.y(minor_radius * (float)sin(phi));
+ a.z((float)cos(theta) * r);
theta = 2 * M_PI * (i + wrap_frac + 1) / (float)wraps_qty;
- b.x = (float)sin(theta) * r;
- b.y = minor_radius * (float)sin(phi);
- b.z = (float)cos(theta) * r;
+ b.x((float)sin(theta) * r);
+ b.y(minor_radius * (float)sin(phi));
+ b.z((float)cos(theta) * r);
wrap_frac = (j + 1) / (float)per_wrap_qty;
phi = 2 * M_PI * wrap_frac;
theta = 2 * M_PI * (i + wrap_frac) / (float)wraps_qty;
r = major_radius + minor_radius * (float)cos(phi);
- c.x = (float)sin(theta) * r;
- c.y = minor_radius * (float)sin(phi);
- c.z = (float)cos(theta) * r;
+ c.x((float)sin(theta) * r);
+ c.y(minor_radius * (float)sin(phi));
+ c.z((float)cos(theta) * r);
theta = 2 * M_PI * (i + wrap_frac + 1) / (float)wraps_qty;
- d.x = (float)sin(theta) * r;
- d.y = minor_radius * (float)sin(phi);
- d.z = (float)cos(theta) * r;
+ d.x((float)sin(theta) * r);
+ d.y(minor_radius * (float)sin(phi));
+ d.z((float)cos(theta) * r);
- n = normal(a, b, c);
+ n = LibMatrix::vec3::cross(b - a, c - a);
+ n.normalize();
mVertex[k].n = n; mVertex[k].v = a; k++;
mVertex[k].n = n; mVertex[k].v = b; k++;
mVertex[k].n = n; mVertex[k].v = c; k++;
- n = normal(a, b, c);
+ n = LibMatrix::vec3::cross(c - b, d - b);
+ n.normalize();
mVertex[k].n = n; mVertex[k].v = b; k++;
mVertex[k].n = n; mVertex[k].v = c; k++;
mVertex[k].n = n; mVertex[k].v = d; k++;
}
}
-void Mesh::render_array()
+void Mesh::render_array(int vertex_loc, int normal_loc, int texcoord_loc)
{
- // Enable the attributes
- glEnableVertexAttribArray(Shader::VertexAttribLocation);
- glEnableVertexAttribArray(Shader::NormalAttribLocation);
- glEnableVertexAttribArray(Shader::TexCoordAttribLocation);
+ // Enable the attributes (texcoord is optional)
+ glEnableVertexAttribArray(vertex_loc);
+ glEnableVertexAttribArray(normal_loc);
+ if (texcoord_loc >= 0)
+ glEnableVertexAttribArray(texcoord_loc);
glBindBuffer(GL_ARRAY_BUFFER, 0);
- glVertexAttribPointer(Shader::VertexAttribLocation, 3, GL_FLOAT,
- GL_FALSE, sizeof(Vertex), &mVertex[0].v.x);
- glVertexAttribPointer(Shader::NormalAttribLocation, 3, GL_FLOAT,
- GL_FALSE, sizeof(Vertex), &mVertex[0].n.x);
- glVertexAttribPointer(Shader::TexCoordAttribLocation, 2, GL_FLOAT,
- GL_FALSE, sizeof(Vertex), &mVertex[0].t.u);
+ glVertexAttribPointer(vertex_loc, 3, GL_FLOAT, GL_FALSE,
+ 8 * sizeof(float), mVertex[0].v);
+ glVertexAttribPointer(normal_loc, 3, GL_FLOAT, GL_FALSE,
+ 8 * sizeof(float), mVertex[0].n);
+ if (texcoord_loc >= 0) {
+ glVertexAttribPointer(texcoord_loc, 2, GL_FLOAT, GL_FALSE,
+ 8 * sizeof(float), mVertex[0].t);
+ }
glDrawArrays(GL_TRIANGLES, 0, mVertexQty);
// Disable the attributes
- glDisableVertexAttribArray(Shader::TexCoordAttribLocation);
- glDisableVertexAttribArray(Shader::NormalAttribLocation);
- glDisableVertexAttribArray(Shader::VertexAttribLocation);
+ glDisableVertexAttribArray(vertex_loc);
+ glDisableVertexAttribArray(normal_loc);
+ if (texcoord_loc >= 0)
+ glDisableVertexAttribArray(texcoord_loc);
}
void Mesh::build_vbo()
@@ -149,38 +145,43 @@
printf("Building vbo for mesh... ");
#endif
- Vector3f *vertex;
- Texel *texel;
- Vector3f *normal;
+ float *vertex;
+ float *texel;
+ float *normal;
- vertex = new Vector3f[mVertexQty];
- texel = new Texel[mVertexQty];
- normal = new Vector3f[mVertexQty];
+ vertex = new float[mVertexQty * 3];
+ texel = new float[mVertexQty * 2];
+ normal = new float[mVertexQty * 3];
for(unsigned i = 0; i < mVertexQty; i++)
{
- vertex[i] = mVertex[i].v;
- texel[i] = mVertex[i].t;
- normal[i] = mVertex[i].n;
+ vertex[3 * i] = mVertex[i].v.x();
+ vertex[3 * i + 1] = mVertex[i].v.y();
+ vertex[3 * i + 2] = mVertex[i].v.z();
+ texel[2 * i] = mVertex[i].t.x();
+ texel[2 * i + 1] = mVertex[i].t.y();
+ normal[3 * i] = mVertex[i].n.x();
+ normal[3 * i + 1] = mVertex[i].n.y();
+ normal[3 * i + 2] = mVertex[i].n.z();
}
// Generate And Bind The Vertex Buffer
glGenBuffers(1, &mVBOVertices);
glBindBuffer(GL_ARRAY_BUFFER, mVBOVertices);
// Load The Data
- glBufferData(GL_ARRAY_BUFFER, mVertexQty * sizeof(Vector3f), vertex, GL_STATIC_DRAW);
+ glBufferData(GL_ARRAY_BUFFER, mVertexQty * 3 * sizeof(float), vertex, GL_STATIC_DRAW);
// Generate And Bind The normal Buffer
glGenBuffers(1, &mVBONormals);
glBindBuffer(GL_ARRAY_BUFFER, mVBONormals);
// Load The Data
- glBufferData(GL_ARRAY_BUFFER, mVertexQty * sizeof(Vector3f), normal, GL_STATIC_DRAW);
+ glBufferData(GL_ARRAY_BUFFER, mVertexQty * 3 * sizeof(float), normal, GL_STATIC_DRAW);
// Generate And Bind The Texture Coordinate Buffer
glGenBuffers(1, &mVBOTexCoords);
glBindBuffer(GL_ARRAY_BUFFER, mVBOTexCoords);
// Load The Data
- glBufferData(GL_ARRAY_BUFFER, mVertexQty * sizeof(Texel), texel, GL_STATIC_DRAW);
+ glBufferData(GL_ARRAY_BUFFER, mVertexQty * 2 * sizeof(float), texel, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
@@ -200,24 +201,28 @@
glDeleteBuffers(1, &mVBOTexCoords);
}
-void Mesh::render_vbo()
+void Mesh::render_vbo(int vertex_loc, int normal_loc, int texcoord_loc)
{
- // Enable the attributes
- glEnableVertexAttribArray(Shader::VertexAttribLocation);
- glEnableVertexAttribArray(Shader::NormalAttribLocation);
- glEnableVertexAttribArray(Shader::TexCoordAttribLocation);
+ // Enable the attributes (texcoord is optional)
+ glEnableVertexAttribArray(vertex_loc);
+ glEnableVertexAttribArray(normal_loc);
+ if (texcoord_loc >= 0)
+ glEnableVertexAttribArray(texcoord_loc);
glBindBuffer(GL_ARRAY_BUFFER, mVBOVertices);
- glVertexAttribPointer(Shader::VertexAttribLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
+ glVertexAttribPointer(vertex_loc, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, mVBONormals);
- glVertexAttribPointer(Shader::NormalAttribLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
- glBindBuffer(GL_ARRAY_BUFFER, mVBOTexCoords);
- glVertexAttribPointer(Shader::TexCoordAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
+ glVertexAttribPointer(normal_loc, 3, GL_FLOAT, GL_FALSE, 0, 0);
+ if (texcoord_loc >= 0) {
+ glBindBuffer(GL_ARRAY_BUFFER, mVBOTexCoords);
+ glVertexAttribPointer(texcoord_loc, 2, GL_FLOAT, GL_FALSE, 0, 0);
+ }
glDrawArrays(GL_TRIANGLES, 0, mVertexQty);
// Disable the attributes
- glDisableVertexAttribArray(Shader::TexCoordAttribLocation);
- glDisableVertexAttribArray(Shader::NormalAttribLocation);
- glDisableVertexAttribArray(Shader::VertexAttribLocation);
+ glDisableVertexAttribArray(vertex_loc);
+ glDisableVertexAttribArray(normal_loc);
+ if (texcoord_loc >= 0)
+ glDisableVertexAttribArray(texcoord_loc);
}
=== modified file 'src/mesh.h'
@@ -25,26 +25,15 @@
#define GLMARK2_MESH_H_
#include "screen.h"
-#include "vector.h"
+#include "vec.h"
#include <stdio.h>
#include <math.h>
-class Texel
-{
-public:
- GLfloat u, v;
-
- Texel();
- Texel(GLfloat pU, GLfloat pV);
-};
-
-class Vertex
-{
-public:
- Vector3f v;
- Vector3f n;
- Texel t;
+struct Vertex {
+ LibMatrix::vec3 v;
+ LibMatrix::vec3 n;
+ LibMatrix::vec2 t;
};
// Data for a mesh to be rendered by vertex arrays' or vbos' has 3 verticies per
@@ -67,10 +56,10 @@
void reset();
void make_cube();
void make_torus();
- void render_array();
+ void render_array(int vertex_loc, int normal_loc, int texcoord_loc);
void build_vbo();
void delete_vbo();
- void render_vbo();
+ void render_vbo(int vertex_loc, int normal_loc, int texcoord_loc);
};
#endif
=== modified file 'src/model.cpp'
@@ -22,6 +22,7 @@
* Alexandros Frantzis (glmark2)
*/
#include "model.h"
+#include "vec.h"
long filelength(int f)
{
@@ -82,11 +83,13 @@
#ifdef _DEBUG
printf("Calculating normals for model... ");
#endif
- Vector3f n;
+ LibMatrix::vec3 n;
for(unsigned i = 0; i < mPolygonQty; i++)
{
- n = normal(mVertex[mPolygon[i].mA].v, mVertex[mPolygon[i].mB].v, mVertex[mPolygon[i].mC].v);
+ n = LibMatrix::vec3::cross(mVertex[mPolygon[i].mB].v - mVertex[mPolygon[i].mA].v,
+ mVertex[mPolygon[i].mC].v - mVertex[mPolygon[i].mA].v);
+ n.normalize();
mVertex[mPolygon[i].mA].n += n;
mVertex[mPolygon[i].mB].n += n;
mVertex[mPolygon[i].mC].n += n;
@@ -102,21 +105,22 @@
void Model::center()
{
- Vector3f center;
- Vector3f max = mVertex[0].v, min = mVertex[0].v;
+ LibMatrix::vec3 max(mVertex[0].v);
+ LibMatrix::vec3 min(mVertex[0].v);
for(unsigned i = 1; i < mVertexQty; i++)
{
- if(mVertex[i].v.x > max.x) max.x = mVertex[i].v.x;
- if(mVertex[i].v.y > max.y) max.y = mVertex[i].v.y;
- if(mVertex[i].v.z > max.z) max.z = mVertex[i].v.z;
+ if(mVertex[i].v.x() > max.x()) max.x(mVertex[i].v.x());
+ if(mVertex[i].v.y() > max.y()) max.y(mVertex[i].v.y());
+ if(mVertex[i].v.z() > max.z()) max.z(mVertex[i].v.z());
- if(mVertex[i].v.x < min.x) min.x = mVertex[i].v.x;
- if(mVertex[i].v.y < min.y) min.y = mVertex[i].v.y;
- if(mVertex[i].v.z < min.z) min.z = mVertex[i].v.z;
+ if(mVertex[i].v.x() < min.x()) min.x(mVertex[i].v.x());
+ if(mVertex[i].v.y() < min.y()) min.y(mVertex[i].v.y());
+ if(mVertex[i].v.z() < min.z()) min.z(mVertex[i].v.z());
}
- center = (max + min) / 2.0f;
+ LibMatrix::vec3 center(max + min);
+ center /= 2.0f;
for(unsigned i = 0; i < mVertexQty; i++)
mVertex[i].v -= center;
@@ -210,9 +214,11 @@
mVertexQty = l_qty;
mVertex = new Vertex[mVertexQty];
for (i = 0; i < l_qty; i++) {
- nread = fread (&mVertex[i].v.x, sizeof(float), 1, l_file);
- nread = fread (&mVertex[i].v.y, sizeof(float), 1, l_file);
- nread = fread (&mVertex[i].v.z, sizeof(float), 1, l_file);
+ float f[3];
+ nread = fread (f, sizeof(float), 3, l_file);
+ mVertex[i].v.x(f[0]);
+ mVertex[i].v.y(f[1]);
+ mVertex[i].v.z(f[2]);
}
break;
@@ -245,8 +251,10 @@
case 0x4140:
nread = fread (&l_qty, sizeof (unsigned short), 1, l_file);
for (i = 0; i < l_qty; i++) {
- nread = fread (&mVertex[i].t.u, sizeof (float), 1, l_file);
- nread = fread (&mVertex[i].t.v, sizeof (float), 1, l_file);
+ float f[2];
+ nread = fread (f, sizeof(float), 2, l_file);
+ mVertex[i].t.x(f[0]);
+ mVertex[i].t.y(f[1]);
}
break;
=== modified file 'src/scene.cpp'
@@ -22,6 +22,7 @@
* Alexandros Frantzis (glmark2)
*/
#include "scene.h"
+#include "log.h"
#include <sstream>
#include <cmath>
@@ -154,3 +155,50 @@
return std::sqrt(s);
}
+
+bool
+Scene::load_shaders(Program &program,
+ const std::string &vtx_shader_filename,
+ const std::string &frg_shader_filename)
+{
+ std::string vtx_shader;
+ std::string frg_shader;
+
+ if (!gotSource(vtx_shader_filename, vtx_shader))
+ return false;
+
+ if (!gotSource(frg_shader_filename, frg_shader))
+ return false;
+
+ program.init();
+
+ program.addShader(GL_VERTEX_SHADER, vtx_shader);
+ if (!program.valid()) {
+ Log::error("Failed to add vertex shader from file %s:\n %s\n",
+ vtx_shader_filename.c_str(),
+ program.errorMessage().c_str());
+ program.release();
+ return false;
+ }
+
+ program.addShader(GL_FRAGMENT_SHADER, frg_shader);
+ if (!program.valid()) {
+ Log::error("Failed to add fragment shader from file %s:\n %s\n",
+ frg_shader_filename.c_str(),
+ program.errorMessage().c_str());
+ program.release();
+ return false;
+ }
+
+ program.build();
+ if (!program.ready()) {
+ Log::error("Failed to link program created from files %s and %s: %s\n",
+ vtx_shader_filename.c_str(),
+ frg_shader_filename.c_str(),
+ program.errorMessage().c_str());
+ program.release();
+ return false;
+ }
+
+ return true;
+}
=== modified file 'src/scene.h'
@@ -29,7 +29,8 @@
#include "mesh.h"
#include "model.h"
#include "texture.h"
-#include "shader.h"
+#include "vec.h"
+#include "program.h"
#include <math.h>
@@ -90,6 +91,10 @@
virtual ValidationResult validate() { return ValidationUnknown; }
+ static bool load_shaders(Program &program,
+ const std::string &vtx_shader_filename,
+ const std::string &frg_shader_filename);
+
protected:
Scene(Screen &pScreen, const std::string &name);
std::string construct_title(const std::string &title);
@@ -124,7 +129,10 @@
~SceneBuild();
protected:
- Shader mShader;
+ Program mProgram;
+ int mVertexAttribLocation;
+ int mNormalAttribLocation;
+ int mTexcoordAttribLocation;
Mesh mMesh;
float mRotation;
@@ -147,12 +155,15 @@
~SceneTexture();
protected:
- Shader mShader;
+ Program mProgram;
+ int mVertexAttribLocation;
+ int mNormalAttribLocation;
+ int mTexcoordAttribLocation;
Mesh mCubeMesh;
GLuint mTexture;
- Vector3f mRotation;
- Vector3f mRotationSpeed;
+ LibMatrix::vec3 mRotation;
+ LibMatrix::vec3 mRotationSpeed;
};
class SceneShading : public Scene
@@ -170,7 +181,10 @@
~SceneShading();
protected:
- Shader mShader;
+ Program mProgram;
+ int mVertexAttribLocation;
+ int mNormalAttribLocation;
+ int mTexcoordAttribLocation;
Mesh mMesh;
float mRotation;
=== modified file 'src/scenebuild.cpp'
@@ -23,6 +23,8 @@
*/
#include "scene.h"
#include "log.h"
+#include "mat.h"
+#include "stack.h"
#include <cmath>
SceneBuild::SceneBuild(Screen &pScreen) :
@@ -38,6 +40,8 @@
int SceneBuild::load()
{
+ static const std::string vtx_shader_filename(GLMARK_DATA_PATH"/shaders/light-basic.vert");
+ static const std::string frg_shader_filename(GLMARK_DATA_PATH"/shaders/light-basic.frag");
Model model;
if(!model.load_3ds(GLMARK_DATA_PATH"/models/horse.3ds"))
@@ -46,8 +50,12 @@
model.calculate_normals();
model.convert_to_mesh(&mMesh);
- mShader.load(GLMARK_DATA_PATH"/shaders/light-basic.vert",
- GLMARK_DATA_PATH"/shaders/light-basic.frag");
+ if (!Scene::load_shaders(mProgram, vtx_shader_filename, frg_shader_filename))
+ return 0;
+
+ mVertexAttribLocation = mProgram.getAttribIndex("position");
+ mNormalAttribLocation = mProgram.getAttribIndex("normal");
+ mTexcoordAttribLocation = mProgram.getAttribIndex("texcoord");
mRotationSpeed = 36.0f;
@@ -59,34 +67,32 @@
void SceneBuild::unload()
{
mMesh.reset();
- mShader.remove();
- mShader.unload();
+
+ mProgram.stop();
+ mProgram.release();
}
void SceneBuild::setup()
{
Scene::setup();
- GLfloat lightAmbient[] = {0.0f, 0.0f, 0.0f, 1.0f};
- GLfloat lightDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
- GLfloat lightPosition[] = {20.0f, 20.0f, 10.0f, 1.0f};
- GLfloat materialColor[] = {1.0f, 1.0f, 1.0f, 1.0f};
-
+ static const LibMatrix::vec4 lightAmbient(0.0f, 0.0f, 0.0f, 1.0f);
+ static const LibMatrix::vec4 lightDiffuse(0.8f, 0.8f, 0.8f, 1.0f);
+ static const LibMatrix::vec4 lightPosition(20.0f, 20.0f, 10.0f, 1.0f);
+ static const LibMatrix::vec4 materialColor(1.0f, 1.0f, 1.0f, 1.0f);
mUseVbo = (mOptions["use-vbo"].value == "true");
if (mUseVbo)
mMesh.build_vbo();
- mShader.use();
+ mProgram.start();
// Load lighting and material uniforms
- glUniform4fv(mShader.mLocations.LightSourcePosition, 1, lightPosition);
-
- glUniform3fv(mShader.mLocations.LightSourceAmbient, 1, lightAmbient);
- glUniform3fv(mShader.mLocations.LightSourceDiffuse, 1, lightDiffuse);
-
- glUniform4fv(mShader.mLocations.MaterialColor, 1, materialColor);
+ mProgram.loadUniformVector(lightAmbient, "LightSourceAmbient");
+ mProgram.loadUniformVector(lightPosition, "LightSourcePosition");
+ mProgram.loadUniformVector(lightDiffuse, "LightSourceDiffuse");
+ mProgram.loadUniformVector(materialColor, "MaterialColor");
mCurrentFrame = 0;
mRotation = 0.0;
@@ -98,7 +104,7 @@
void
SceneBuild::teardown()
{
- mShader.remove();
+ mProgram.stop();
if (mUseVbo)
mMesh.delete_vbo();
@@ -126,27 +132,33 @@
void SceneBuild::draw()
{
+ LibMatrix::Stack4 model_view;
+
// Load the ModelViewProjectionMatrix uniform in the shader
- Matrix4f model_view(1.0f, 1.0f, 1.0f);
- Matrix4f model_view_proj(mScreen.mProjection);
+ LibMatrix::mat4 model_view_proj(mScreen.mProjection);
model_view.translate(0.0f, 0.0f, -2.5f);
- model_view.rotate(2 * M_PI * mRotation / 360.0, 0.0f, 1.0f, 0.0f);
- model_view_proj *= model_view;
+ model_view.rotate(mRotation, 0.0f, 1.0f, 0.0f);
+ model_view_proj *= model_view.getCurrent();
- glUniformMatrix4fv(mShader.mLocations.ModelViewProjectionMatrix, 1,
- GL_FALSE, model_view_proj.m);
+ mProgram.loadUniformMatrix(model_view_proj, "ModelViewProjectionMatrix");
// Load the NormalMatrix uniform in the shader. The NormalMatrix is the
// inverse transpose of the model view matrix.
- model_view.invert().transpose();
- glUniformMatrix4fv(mShader.mLocations.NormalMatrix, 1,
- GL_FALSE, model_view.m);
+ LibMatrix::mat4 normal_matrix(model_view.getCurrent());
+ normal_matrix.inverse().transpose();
+ mProgram.loadUniformMatrix(normal_matrix, "NormalMatrix");
- if (mUseVbo)
- mMesh.render_vbo();
- else
- mMesh.render_array();
+ if (mUseVbo) {
+ mMesh.render_vbo(mVertexAttribLocation,
+ mNormalAttribLocation,
+ mTexcoordAttribLocation);
+ }
+ else {
+ mMesh.render_array(mVertexAttribLocation,
+ mNormalAttribLocation,
+ mTexcoordAttribLocation);
+ }
}
Scene::ValidationResult
=== modified file 'src/sceneshading.cpp'
@@ -22,7 +22,9 @@
* Alexandros Frantzis (glmark2)
*/
#include "scene.h"
-#include "matrix.h"
+#include "mat.h"
+#include "stack.h"
+#include "vec.h"
#include "log.h"
#include <cmath>
@@ -66,48 +68,55 @@
{
Scene::setup();
- GLfloat lightAmbient[] = {0.1f, 0.1f, 0.1f, 1.0f};
- GLfloat lightDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
- GLfloat lightSpecular[] = {0.8f, 0.8f, 0.8f, 1.0f};
- GLfloat lightPosition[] = {20.0f, 20.0f, 10.0f, 1.0f};
-
- float materialAmbient[] = {1.0f, 1.0f, 1.0f, 1.0f};
- float materialDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
- float materialSpecular[] = {1.0f, 1.0f, 1.0f, 1.0f};
- float materialColor[] = {0.0f, 0.0f, 1.0f, 1.0f};
-
+ static const LibMatrix::vec3 lightAmbient(0.1f, 0.1f, 0.1f);
+ static const LibMatrix::vec3 lightDiffuse(0.8f, 0.8f, 0.8f);
+ static const LibMatrix::vec3 lightSpecular(0.8f, 0.8f, 0.8f);
+ static const LibMatrix::vec4 lightPosition(20.0f, 20.0f, 10.0f, 1.0f);
+
+ static const LibMatrix::vec3 materialAmbient(1.0f, 1.0f, 1.0f);
+ static const LibMatrix::vec3 materialDiffuse(1.0f, 1.0f, 1.0f);
+ static const LibMatrix::vec3 materialSpecular(1.0f, 1.0f, 1.0f);
+ static const LibMatrix::vec4 materialColor(0.0f, 0.0f, 1.0f, 1.0f);
+
+ std::string vtx_shader_filename;
+ std::string frg_shader_filename;
const std::string &shading = mOptions["shading"].value;
if (shading == "gouraud") {
- mShader.load(GLMARK_DATA_PATH"/shaders/light-basic.vert",
- GLMARK_DATA_PATH"/shaders/light-basic.frag");
+ vtx_shader_filename = GLMARK_DATA_PATH"/shaders/light-basic.vert";
+ frg_shader_filename = GLMARK_DATA_PATH"/shaders/light-basic.frag";
}
else if (shading == "phong") {
- mShader.load(GLMARK_DATA_PATH"/shaders/light-advanced.vert",
- GLMARK_DATA_PATH"/shaders/light-advanced.frag");
+ vtx_shader_filename = GLMARK_DATA_PATH"/shaders/light-advanced.vert";
+ frg_shader_filename = GLMARK_DATA_PATH"/shaders/light-advanced.frag";
}
- mShader.use();
+ if (!Scene::load_shaders(mProgram, vtx_shader_filename, frg_shader_filename))
+ return;
+
+ mProgram.start();
+
+ mVertexAttribLocation = mProgram.getAttribIndex("position");
+ mNormalAttribLocation = mProgram.getAttribIndex("normal");
+ mTexcoordAttribLocation = mProgram.getAttribIndex("texcoord");
// Load lighting and material uniforms
- glUniform4fv(mShader.mLocations.LightSourcePosition, 1, lightPosition);
-
- glUniform3fv(mShader.mLocations.LightSourceAmbient, 1, lightAmbient);
- glUniform3fv(mShader.mLocations.LightSourceDiffuse, 1, lightDiffuse);
- glUniform3fv(mShader.mLocations.LightSourceSpecular, 1, lightSpecular);
-
- glUniform3fv(mShader.mLocations.MaterialAmbient, 1, materialAmbient);
- glUniform3fv(mShader.mLocations.MaterialDiffuse, 1, materialDiffuse);
- glUniform3fv(mShader.mLocations.MaterialSpecular, 1, materialSpecular);
- glUniform4fv(mShader.mLocations.MaterialColor, 1, materialColor);
+ mProgram.loadUniformVector(lightAmbient, "LightSourceAmbient");
+ mProgram.loadUniformVector(lightPosition, "LightSourcePosition");
+ mProgram.loadUniformVector(lightDiffuse, "LightSourceDiffuse");
+ mProgram.loadUniformVector(lightSpecular, "LightSourceSpecular");
+
+ mProgram.loadUniformVector(materialAmbient, "MaterialAmbient");
+ mProgram.loadUniformVector(materialDiffuse, "MaterialDiffuse");
+ mProgram.loadUniformVector(materialSpecular, "MaterialSpecular");
+ mProgram.loadUniformVector(materialColor, "MaterialColor");
// Calculate and load the half vector
- Vector3f halfVector = Vector3f(lightPosition[0], lightPosition[1], lightPosition[2]);
- halfVector.normalize();
- halfVector += Vector3f(0.0, 0.0, 1.0);
- halfVector.normalize();
- glUniform3fv(mShader.mLocations.LightSourceHalfVector, 1,
- (GLfloat *)&halfVector);
+ LibMatrix::vec3 halfVector(lightPosition[0], lightPosition[1], lightPosition[2]);
+ halfVector.normalize();
+ halfVector += LibMatrix::vec3(0.0, 0.0, 1.0);
+ halfVector.normalize();
+ mProgram.loadUniformVector(halfVector, "LightSourceHalfVector");
mCurrentFrame = 0;
mRotation = 0.0f;
@@ -118,8 +127,8 @@
void SceneShading::teardown()
{
- mShader.remove();
- mShader.unload();
+ mProgram.stop();
+ mProgram.release();
Scene::teardown();
}
@@ -145,23 +154,24 @@
void SceneShading::draw()
{
// Load the ModelViewProjectionMatrix uniform in the shader
- Matrix4f model_view(1.0f, 1.0f, 1.0f);
- Matrix4f model_view_proj(mScreen.mProjection);
+ LibMatrix::Stack4 model_view;
+ LibMatrix::mat4 model_view_proj(mScreen.mProjection);
model_view.translate(0.0f, 0.0f, -5.0f);
- model_view.rotate(2 * M_PI * mRotation / 360.0, 0.0f, 1.0f, 0.0f);
- model_view_proj *= model_view;
+ model_view.rotate(mRotation, 0.0f, 1.0f, 0.0f);
+ model_view_proj *= model_view.getCurrent();
- glUniformMatrix4fv(mShader.mLocations.ModelViewProjectionMatrix, 1,
- GL_FALSE, model_view_proj.m);
+ mProgram.loadUniformMatrix(model_view_proj, "ModelViewProjectionMatrix");
// Load the NormalMatrix uniform in the shader. The NormalMatrix is the
// inverse transpose of the model view matrix.
- model_view.invert().transpose();
- glUniformMatrix4fv(mShader.mLocations.NormalMatrix, 1,
- GL_FALSE, model_view.m);
+ LibMatrix::mat4 normal_matrix(model_view.getCurrent());
+ normal_matrix.inverse().transpose();
+ mProgram.loadUniformMatrix(normal_matrix, "NormalMatrix");
- mMesh.render_vbo();
+ mMesh.render_vbo(mVertexAttribLocation,
+ mNormalAttribLocation,
+ mTexcoordAttribLocation);
}
Scene::ValidationResult
=== modified file 'src/scenetexture.cpp'
@@ -22,9 +22,12 @@
* Alexandros Frantzis (glmark2)
*/
#include "scene.h"
-#include "matrix.h"
+#include "mat.h"
+#include "stack.h"
+#include "vec.h"
#include "log.h"
+#include "program.h"
#include <cmath>
SceneTexture::SceneTexture(Screen &pScreen) :
@@ -40,6 +43,8 @@
int SceneTexture::load()
{
+ static const std::string vtx_shader_filename(GLMARK_DATA_PATH"/shaders/light-basic.vert");
+ static const std::string frg_shader_filename(GLMARK_DATA_PATH"/shaders/light-basic-tex.frag");
Model model;
if(!model.load_3ds(GLMARK_DATA_PATH"/models/cube.3ds"))
@@ -49,10 +54,14 @@
model.convert_to_mesh(&mCubeMesh);
mCubeMesh.build_vbo();
- mShader.load(GLMARK_DATA_PATH"/shaders/light-basic.vert",
- GLMARK_DATA_PATH"/shaders/light-basic-tex.frag");
-
- mRotationSpeed = Vector3f(36.0f, 36.0f, 36.0f);
+ if (!Scene::load_shaders(mProgram, vtx_shader_filename, frg_shader_filename))
+ return 0;
+
+ mVertexAttribLocation = mProgram.getAttribIndex("position");
+ mNormalAttribLocation = mProgram.getAttribIndex("normal");
+ mTexcoordAttribLocation = mProgram.getAttribIndex("texcoord");
+
+ mRotationSpeed = LibMatrix::vec3(36.0f, 36.0f, 36.0f);
mRunning = false;
@@ -62,17 +71,19 @@
void SceneTexture::unload()
{
mCubeMesh.reset();
- mShader.unload();
+
+ mProgram.stop();
+ mProgram.release();
}
void SceneTexture::setup()
{
Scene::setup();
- GLfloat lightAmbient[] = {0.0f, 0.0f, 0.0f, 1.0f};
- GLfloat lightDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
- GLfloat lightPosition[] = {20.0f, 20.0f, 10.0f, 1.0f};
- GLfloat materialColor[] = {1.0f, 1.0f, 1.0f, 1.0f};
+ static const LibMatrix::vec4 lightAmbient(0.0f, 0.0f, 0.0f, 1.0f);
+ static const LibMatrix::vec4 lightDiffuse(0.8f, 0.8f, 0.8f, 1.0f);
+ static const LibMatrix::vec4 lightPosition(20.0f, 20.0f, 10.0f, 1.0f);
+ static const LibMatrix::vec4 materialColor(1.0f, 1.0f, 1.0f, 1.0f);
// Create texture according to selected filtering
GLint min_filter = GL_NONE;
@@ -95,18 +106,16 @@
Texture::load(GLMARK_DATA_PATH"/textures/crate-base.bmp", &mTexture,
min_filter, mag_filter, 0);
- mShader.use();
+ mProgram.start();
// Load lighting and material uniforms
- glUniform4fv(mShader.mLocations.LightSourcePosition, 1, lightPosition);
-
- glUniform3fv(mShader.mLocations.LightSourceAmbient, 1, lightAmbient);
- glUniform3fv(mShader.mLocations.LightSourceDiffuse, 1, lightDiffuse);
-
- glUniform4fv(mShader.mLocations.MaterialColor, 1, materialColor);
+ mProgram.loadUniformVector(lightAmbient, "LightSourceAmbient");
+ mProgram.loadUniformVector(lightPosition, "LightSourcePosition");
+ mProgram.loadUniformVector(lightDiffuse, "LightSourceDiffuse");
+ mProgram.loadUniformVector(materialColor, "MaterialColor");
mCurrentFrame = 0;
- mRotation = Vector3f();
+ mRotation = LibMatrix::vec3();
mRunning = true;
mStartTime = SDL_GetTicks() / 1000.0;
mLastUpdateTime = mStartTime;
@@ -114,7 +123,7 @@
void SceneTexture::teardown()
{
- mShader.remove();
+ mProgram.stop();
glDeleteTextures(1, &mTexture);
Scene::teardown();
@@ -141,28 +150,29 @@
void SceneTexture::draw()
{
// Load the ModelViewProjectionMatrix uniform in the shader
- Matrix4f model_view(1.0f, 1.0f, 1.0f);
- Matrix4f model_view_proj(mScreen.mProjection);
+ LibMatrix::Stack4 model_view;
+ LibMatrix::mat4 model_view_proj(mScreen.mProjection);
model_view.translate(0.0f, 0.0f, -5.0f);
- model_view.rotate(2 * M_PI * mRotation.x / 360.0, 1.0f, 0.0f, 0.0f);
- model_view.rotate(2 * M_PI * mRotation.y / 360.0, 0.0f, 1.0f, 0.0f);
- model_view.rotate(2 * M_PI * mRotation.z / 360.0, 0.0f, 0.0f, 1.0f);
- model_view_proj *= model_view;
+ model_view.rotate(mRotation.x(), 1.0f, 0.0f, 0.0f);
+ model_view.rotate(mRotation.y(), 0.0f, 1.0f, 0.0f);
+ model_view.rotate(mRotation.z(), 0.0f, 0.0f, 1.0f);
+ model_view_proj *= model_view.getCurrent();
- glUniformMatrix4fv(mShader.mLocations.ModelViewProjectionMatrix, 1,
- GL_FALSE, model_view_proj.m);
+ mProgram.loadUniformMatrix(model_view_proj, "ModelViewProjectionMatrix");
// Load the NormalMatrix uniform in the shader. The NormalMatrix is the
// inverse transpose of the model view matrix.
- model_view.invert().transpose();
- glUniformMatrix4fv(mShader.mLocations.NormalMatrix, 1,
- GL_FALSE, model_view.m);
+ LibMatrix::mat4 normal_matrix(model_view.getCurrent());
+ normal_matrix.inverse().transpose();
+ mProgram.loadUniformMatrix(normal_matrix, "NormalMatrix");
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mTexture);
- mCubeMesh.render_vbo();
+ mCubeMesh.render_vbo(mVertexAttribLocation,
+ mNormalAttribLocation,
+ mTexcoordAttribLocation);
}
Scene::ValidationResult
@@ -170,7 +180,7 @@
{
static const double radius_3d(std::sqrt(3.0));
- if (mRotation.x != 0 || mRotation.y != 0 || mRotation.z != 0)
+ if (mRotation.x() != 0 || mRotation.y() != 0 || mRotation.z() != 0)
return Scene::ValidationUnknown;
Screen::Pixel ref;
=== modified file 'src/screen-sdl.cpp'
@@ -61,10 +61,11 @@
SDL_WM_SetCaption("glmark2 " GLMARK_VERSION, NULL);
- mProjection.perspective(60.0, mWidth / (float)mHeight, 1.0, 1024.0);
+ mProjection = LibMatrix::Mat4::perspective(60.0, mWidth / (float)mHeight,
+ 1.0, 1024.0);
#ifdef _DEBUG
- mProjection.display("Projection");
+ mProjection.print();
#endif
mInitSuccess = 1;
=== modified file 'src/screen.h'
@@ -25,7 +25,7 @@
#define GLMARK2_SCREEN_H_
#include "oglsdl.h"
-#include "matrix.h"
+#include "mat.h"
#include <string>
#include <stdio.h>
@@ -58,7 +58,7 @@
int mHeight;
int mBpp;
int mFullScreen;
- Matrix4f mProjection;
+ LibMatrix::mat4 mProjection;
int mInitSuccess;
virtual void clear() {}
=== removed file 'src/shader.cpp'
@@ -1,179 +0,0 @@
-/*
- * Copyright © 2008 Ben Smith
- * Copyright © 2010-2011 Linaro Limited
- *
- * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
- *
- * glmark2 is free software: you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later
- * version.
- *
- * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * glmark2. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Ben Smith (original glmark benchmark)
- * Alexandros Frantzis (glmark2)
- */
-#include "shader.h"
-
-char *readShaderFile(const char *FileName)
-{
- FILE *fp;
- char *DATA = NULL;
-
- int flength = 0;
-
- fp = fopen(FileName,"rt");
-
- fseek(fp, 0, SEEK_END);
-
- flength = ftell(fp);
-
- rewind(fp);
-
-
- DATA = (char *)malloc(sizeof(char) * (flength+1));
- flength = fread(DATA, sizeof(char), flength, fp);
- DATA[flength] = '\0';
-
- fclose(fp);
-
- return DATA;
-}
-
-Shader::~Shader()
-{
- unload();
-}
-
-void Shader::load(const char *pVertexShaderFileName, const char *pFragmentShaderFileName)
-{
- char *vertex_shader_source, *fragment_shader_source;
- char msg[512];
- GLint status;
-
- mVertexShader = glCreateShader(GL_VERTEX_SHADER);
- mFragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
-
- vertex_shader_source = readShaderFile(pVertexShaderFileName);
-
- fragment_shader_source = readShaderFile(pFragmentShaderFileName);
-
- const char *vs = vertex_shader_source;
- const char *fs = fragment_shader_source;
-
- glShaderSource(mVertexShader, 1, &vs, NULL);
- glShaderSource(mFragmentShader, 1, &fs, NULL);
-
- free(vertex_shader_source);
- free(fragment_shader_source);
-
- glCompileShader(mVertexShader);
- glGetShaderiv(mVertexShader, GL_COMPILE_STATUS, &status);
- if (status == GL_FALSE) {
- glGetShaderInfoLog(mVertexShader, sizeof msg, NULL, msg);
- fprintf(stderr, "Error compiling %s: %s", pVertexShaderFileName,
- strlen(msg) > 0 ? msg : "[No info]");
- }
-
- glCompileShader(mFragmentShader);
- glGetShaderiv(mFragmentShader, GL_COMPILE_STATUS, &status);
- if (status == GL_FALSE) {
- glGetShaderInfoLog(mFragmentShader, sizeof msg, NULL, msg);
- fprintf(stderr, "Error compiling %s: %s", pFragmentShaderFileName,
- strlen(msg) > 0 ? msg : "[No info]");
- }
-
- mShaderProgram = glCreateProgram();
- glAttachShader(mShaderProgram, mFragmentShader);
- glAttachShader(mShaderProgram, mVertexShader);
- glBindAttribLocation(mShaderProgram, VertexAttribLocation, "position");
- glBindAttribLocation(mShaderProgram, NormalAttribLocation, "normal");
- glBindAttribLocation(mShaderProgram, TexCoordAttribLocation, "texcoord");
-
- glLinkProgram(mShaderProgram);
- glGetProgramiv(mShaderProgram, GL_LINK_STATUS, &status);
- if (status == GL_FALSE) {
- glGetProgramInfoLog(mShaderProgram, sizeof msg, NULL, msg);
- fprintf(stderr, "Error linking shader program: %s",
- strlen(msg) > 0 ? msg : "[No info]");
- }
-
- mLocations.ModelViewProjectionMatrix = glGetUniformLocation(mShaderProgram,
- "ModelViewProjectionMatrix");
- mLocations.NormalMatrix = glGetUniformLocation(mShaderProgram,
- "NormalMatrix");
- mLocations.LightSourcePosition = glGetUniformLocation(mShaderProgram,
- "LightSourcePosition");
- mLocations.LightSourceHalfVector = glGetUniformLocation(mShaderProgram,
- "LightSourceHalfVector");
-
- mLocations.LightSourceAmbient = glGetUniformLocation(mShaderProgram,
- "LightSourceAmbient");
- mLocations.LightSourceDiffuse = glGetUniformLocation(mShaderProgram,
- "LightSourceDiffuse");
- mLocations.LightSourceSpecular = glGetUniformLocation(mShaderProgram,
- "LightSourceSpecular");
-
- mLocations.MaterialAmbient = glGetUniformLocation(mShaderProgram,
- "MaterialAmbient");
- mLocations.MaterialDiffuse = glGetUniformLocation(mShaderProgram,
- "MaterialDiffuse");
- mLocations.MaterialSpecular = glGetUniformLocation(mShaderProgram,
- "MaterialSpecular");
- mLocations.MaterialColor = glGetUniformLocation(mShaderProgram,
- "MaterialColor");
- mLocations.MaterialTexture0 = glGetUniformLocation(mShaderProgram,
- "MaterialTexture0");
- glUseProgram(mShaderProgram);
- glUniform1i(mLocations.MaterialTexture0, 0);
- glUseProgram(0);
-
-#ifdef _DEBUG
- printf("Uniform Locations: %d %d %d %d %d %d %d %d %d %d %d %d\n",
- mLocations.ModelViewProjectionMatrix,
- mLocations.NormalMatrix,
- mLocations.LightSourcePosition,
- mLocations.LightSourceHalfVector,
- mLocations.LightSourceAmbient,
- mLocations.LightSourceDiffuse,
- mLocations.LightSourceSpecular,
- mLocations.MaterialAmbient,
- mLocations.MaterialDiffuse,
- mLocations.MaterialSpecular,
- mLocations.MaterialColor,
- mLocations.MaterialTexture0);
-#endif
-
-}
-
-void Shader::use()
-{
- glUseProgram(mShaderProgram);
-}
-
-void Shader::remove()
-{
- glUseProgram(0);
-}
-
-void Shader::unload()
-{
- glDetachShader(mShaderProgram, mVertexShader);
- glDetachShader(mShaderProgram, mFragmentShader);
-
- glDeleteShader(mVertexShader);
- glDeleteShader(mFragmentShader);
- glDeleteProgram(mShaderProgram);
-
- mVertexShader = 0;
- mFragmentShader = 0;
- mShaderProgram = 0;
-}
=== removed file 'src/shader.h'
@@ -1,67 +0,0 @@
-/*
- * Copyright © 2008 Ben Smith
- * Copyright © 2010-2011 Linaro Limited
- *
- * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
- *
- * glmark2 is free software: you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later
- * version.
- *
- * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * glmark2. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Ben Smith (original glmark benchmark)
- * Alexandros Frantzis (glmark2)
- */
-#ifndef GLMARK2_SHADER_H_
-#define GLMARK2_SHADER_H_
-
-#include "oglsdl.h"
-
-#include <fcntl.h>
-#include <unistd.h>
-
-class Shader
-{
-public:
- ~Shader();
- void load(const char *pVertexShaderFileName, const char *pFragmentShaderFileName);
- void unload();
-
- void use();
- void remove();
-
- GLuint mVertexShader;
- GLuint mFragmentShader;
- int mShaderProgram;
- struct {
- GLint ModelViewProjectionMatrix;
- GLint NormalMatrix;
- GLint LightSourcePosition;
- GLint LightSourceHalfVector;
- GLint LightSourceAmbient;
- GLint LightSourceDiffuse;
- GLint LightSourceSpecular;
- GLint MaterialAmbient;
- GLint MaterialDiffuse;
- GLint MaterialSpecular;
- GLint MaterialColor;
- GLint MaterialTexture0;
- } mLocations;
-
- enum {
- VertexAttribLocation = 0,
- NormalAttribLocation = 1,
- TexCoordAttribLocation = 2
- };
-};
-
-#endif
=== removed file 'src/vector.cpp'
@@ -1,148 +0,0 @@
-/*
- * Copyright © 2008 Ben Smith
- * Copyright © 2010-2011 Linaro Limited
- *
- * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
- *
- * glmark2 is free software: you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later
- * version.
- *
- * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * glmark2. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Ben Smith (original glmark benchmark)
- * Alexandros Frantzis (glmark2)
- */
-#include "vector.h"
-
-Vector3f::Vector3f()
-{
- x = 0.0f; y = 0.0f; z = 0.0f;
-}
-
-Vector3f::Vector3f(GLfloat pX, GLfloat pY, GLfloat pZ)
-{
- x = pX; y = pY; z = pZ;
-}
-
-void Vector3f::display()
-{
- printf("(%f, %f, %f)\n", x, y, z);
-}
-
-float Vector3f::length()
-{
- return sqrt(x * x + y * y + z * z);
-}
-
-void Vector3f::normalize()
-{
- GLfloat l = length();
- x /= l; y /= l; z /= l;
-}
-
-Vector3f &Vector3f::operator=(const Vector3f &pV)
-{
- x = pV.x;
- y = pV.y;
- z = pV.z;
- return *this;
-}
-
-Vector3f &Vector3f::operator+=(const Vector3f &pV)
-{
- x += pV.x;
- y += pV.y;
- z += pV.z;
- return *this;
-}
-
-Vector3f &Vector3f::operator-=(const Vector3f &pV)
-{
- x -= pV.x;
- y -= pV.y;
- z -= pV.z;
- return *this;
-}
-
-Vector3f &Vector3f::operator*=(float pF)
-{
- x *= pF;
- y *= pF;
- z *= pF;
- return *this;
-}
-
-Vector3f &Vector3f::operator*=(double pF)
-{
- x *= pF;
- y *= pF;
- z *= pF;
- return *this;
-}
-
-Vector3f &Vector3f::operator/=(float pF)
-{
- x /= pF;
- y /= pF;
- z /= pF;
- return *this;
-}
-
-Vector3f operator+(const Vector3f &pA, const Vector3f &pB)
-{
- Vector3f v = pA;
- return v += pB;
-}
-
-Vector3f operator-(const Vector3f &pA, const Vector3f &pB)
-{
- Vector3f v = pA;
- return v -= pB;
-}
-
-Vector3f operator*(const Vector3f &pA, const float &pB)
-{
- Vector3f v = pA;
- return v *= pB;
-}
-
-Vector3f operator/(const Vector3f &pA, const float &pB)
-{
- Vector3f v = pA;
- return v /= pB;
-}
-
-Vector3f operator*(const Vector3f &pA, const double &pB)
-{
- Vector3f v = pA;
- return v *= pB;
-}
-
-Vector3f cross(const Vector3f &pA, const Vector3f &pB)
-{
- return Vector3f(pA.y * pB.z - pA.z * pB.y,
- pA.z * pB.x - pA.x * pB.z,
- pA.x * pB.y - pA.y * pB.x);
-}
-
-float dot(const Vector3f &pA, const Vector3f &pB)
-{
- return pA.x * pB.x + pA.y * pB.y + pA.z * pB.z;
-}
-
-Vector3f normal(const Vector3f &pA, const Vector3f &pB, const Vector3f &pC)
-{
- Vector3f n = cross(pB - pA, pC - pA);
- n.normalize();
- return n;
-}
-
=== removed file 'src/vector.h'
@@ -1,68 +0,0 @@
-/*
- * Copyright © 2008 Ben Smith
- * Copyright © 2010-2011 Linaro Limited
- *
- * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
- *
- * glmark2 is free software: you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later
- * version.
- *
- * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * glmark2. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Ben Smith (original glmark benchmark)
- * Alexandros Frantzis (glmark2)
- */
-#ifndef GLMARK2_VECTOR_H_
-#define GLMARK2_VECTOR_H_
-
-#include "oglsdl.h"
-
-#include <stdio.h>
-#include <math.h>
-
-class Vector3f
-{
- union
- {
- struct { GLfloat x; GLfloat y; GLfloat z; };
- GLfloat v[3];
- };
-
-public:
-
- Vector3f();
- Vector3f(GLfloat pX, GLfloat pY, GLfloat pZ);
-
- void display();
- float length();
- void normalize();
-
- Vector3f &operator=(const Vector3f &pV);
- Vector3f &operator+=(const Vector3f &pV);
- Vector3f &operator-=(const Vector3f &pV);
- Vector3f &operator*=(float pF);
- Vector3f &operator/=(float pF);
- Vector3f &operator*=(double pF);
-};
-
-extern Vector3f operator+(const Vector3f &pA, const Vector3f &pB);
-extern Vector3f operator-(const Vector3f &pA, const Vector3f &pB);
-extern Vector3f operator*(const Vector3f &pA, const float &pB);
-extern Vector3f operator/(const Vector3f &pA, const float &pB);
-
-extern Vector3f operator*(const Vector3f &pA, const double &pB);
-
-extern float dot(const Vector3f &pA, const Vector3f &pB);
-extern Vector3f cross(const Vector3f &pA, const Vector3f &pB);
-extern Vector3f normal(const Vector3f &pA, const Vector3f &pB, const Vector3f &pC);
-
-#endif
=== modified file 'src/wscript_build'
@@ -2,19 +2,39 @@
common_sources = [f for f in all_sources if f.name.find('screen-') == -1]
gl_sources = ['screen-sdl.cpp', 'screen-sdl-gl.cpp']
glesv2_sources = ['screen-sdl.cpp', 'screen-sdl-glesv2.cpp']
+libmatrix_sources = [f for f in bld.path.ant_glob('libmatrix/*.cc')
+ if not f.name.endswith('test.cc')]
if bld.env.USE_GL:
bld(
+ features = ['cxx', 'cxxstlib'],
+ source = libmatrix_sources,
+ target = 'matrix',
+ lib = ['m'],
+ includes = ['.'],
+ export_includes = 'libmatrix',
+ defines = ['USE_GL']
+ )
+ bld(
features = ['cxx', 'cprogram'],
source = common_sources + gl_sources,
target = 'glmark2',
- uselib = ['sdl', 'gl'],
+ use = ['sdl', 'gl', 'matrix'],
lib = ['m'],
defines = ['USE_GL']
)
if bld.env.USE_GLESv2:
bld(
+ features = ['cxx', 'cxxstlib'],
+ source = libmatrix_sources,
+ target = 'matrix-es2',
+ lib = ['m'],
+ includes = ['.'],
+ export_includes = 'libmatrix',
+ defines = ['USE_GLESv2']
+ )
+ bld(
features = ['c', 'cstlib'],
source = bld.path.ant_glob('sdlgles/*.c'),
target = 'sdlgles',
@@ -24,8 +44,7 @@
features = ['cxx', 'cprogram'],
source = common_sources + glesv2_sources,
target = 'glmark2-es2',
- uselib = ['sdl', 'glesv2'],
- use = ['sdlgles'],
+ use = ['sdl', 'glesv2', 'sdlgles', 'matrix-es2'],
lib = ['m', 'dl'],
defines = ['USE_GLESv2']
)