OpenGL Mathematics (GLM)
http://people.inf.elte.hu/stbqaai/szGraf/GL/glm-0.9.B.1/
VSML
vsml in action
http://www.lighthouse3d.com/very-simple-libs/vsml/vsml-in-action/
vsml source code
vsml.h
/** ----------------------------------------------------------
* /class VSML
*
* Lighthouse3D
*
* VSML - Very Simple Matrix Library
*
* Full documentation at
* http://www.lighthouse3d.com/very-simple-libs
*
* This class aims at easing geometric transforms, camera
* placement and projection definition for programmers
* working with OpenGL core versions.
*
* This lib requires:
*
* GLEW (http://glew.sourceforge.net/)
*
---------------------------------------------------------------*/
#ifndef __VSML__
#define __VSML__
// uncomment this if you want VSML to always update
// the matrices for you. Otherwise you'll have to call
// a matrixTo* function to get them updated before
// calling OpenGL draw commands
//#define VSML_ALWAYS_SEND_TO_OPENGL
#include <vector>
#include <GL/glew.h>
class VSML {
public:
/// Enumeration of the matrix types
enum MatrixTypes{
MODELVIEW,
PROJECTION
} ;
/// Singleton pattern
static VSML* gInstance;
/// Call this to get the single instance of VSML
static VSML* getInstance (void);
~VSML();
/** Call this function to init the library for a particular
* program shader if using uniform variables
*
* /param modelviewLoc location of the uniform variable
* for the modelview matrix
*
* /param projLoc location of the uniform variable
* for the projection matrix
*/
void initUniformLocs(GLuint modelviewLoc, GLuint projLoc);
/** Call this function to init the library for a particular
* program shader if using uniform blocks
*
* /param buffer index of the uniform buffer
* /param modelviewOffset offset within the buffer of
* the modelview matrix
* /param projOffset offset within the buffer of
* the projection matrix
*/
void initUniformBlock(GLuint buffer, GLuint modelviewOffset, GLuint projOffset);
/** Similar to glTranslate*. Can be applied to both MODELVIEW
* and PROJECTION matrices.
*
* /param aType either MODELVIEW or PROJECTION
* /param x,y,z vector to perform the translation
*/
void translate(MatrixTypes aType, float x, float y, float z);
/** Similar to glTranslate*. Applied to MODELVIEW only.
*
* /param x,y,z vector to perform the translation
*/
void translate(float x, float y, float z);
/** Similar to glScale*. Can be applied to both MODELVIEW
* and PROJECTION matrices.
*
* /param aType either MODELVIEW or PROJECTION
* /param x,y,z scale factors
*/
void scale(MatrixTypes aType, float x, float y, float z);
/** Similar to glScale*. Applied to MODELVIEW only.
*
* /param x,y,z scale factors
*/
void scale(float x, float y, float z);
/** Similar to glTotate*. Can be applied to both MODELVIEW
* and PROJECTION matrices.
*
* /param aType either MODELVIEW or PROJECTION
* /param angle rotation angle in degrees
* /param x,y,z rotation axis in degrees
*/
void rotate(MatrixTypes aType, float angle, float x, float y, float z);
/** Similar to glRotate*. Applied to MODELVIEW only.
*
* /param angle rotation angle in degrees
* /param x,y,z rotation axis in degrees
*/
void rotate(float angle, float x, float y, float z);
/** Similar to glLoadIdentity.
*
* /param aType either MODELVIEW or PROJECTION
*/
void loadIdentity(MatrixTypes aType);
/** Similar to glMultMatrix.
*
* /param aType either MODELVIEW or PROJECTION
* /param aMatrix matrix in column major order data, float[16]
*/
void multMatrix(MatrixTypes aType, float *aMatrix);
/** Similar to gLoadMatrix.
*
* /param aType either MODELVIEW or PROJECTION
* /param aMatrix matrix in column major order data, float[16]
*/
void loadMatrix(MatrixTypes aType, float *aMatrix);
/** Similar to glPushMatrix
*
* /param aType either MODELVIEW or PROJECTION
*/
void pushMatrix(MatrixTypes aType);
/** Similar to glPopMatrix
*
* /param aType either MODELVIEW or PROJECTION
*/
void popMatrix(MatrixTypes aType);
/** Similar to gluLookAt
*
* /param xPos, yPos, zPos camera position
* /param xLook, yLook, zLook point to aim the camera at
* /param xUp, yUp, zUp camera's up vector
*/
void lookAt(float xPos, float yPos, float zPos,
float xLook, float yLook, float zLook,
float xUp, float yUp, float zUp);
/** Similar to gluPerspective
*
* /param fov vertical field of view
* /param ratio aspect ratio of the viewport or window
* /param nearp,farp distance to the near and far planes
*/
void perspective(float fov, float ratio, float nearp, float farp);
/** Similar to glOrtho and gluOrtho2D (just leave the last two params blank).
*
* /param left,right coordinates for the left and right vertical clipping planes
* /param bottom,top coordinates for the bottom and top horizontal clipping planes
* /param nearp,farp distance to the near and far planes
*/
void ortho(float left, float right, float bottom, float top, float nearp=-1.0f, float farp=1.0f);
/** Similar to glFrustum
*
* /param left,right coordinates for the left and right vertical clipping planes
* /param bottom,top coordinates for the bottom and top horizontal clipping planes
* /param nearp,farp distance to the near and far planes
*/
void frustum(float left, float right, float bottom, float top, float nearp, float farp);
/** Similar to glGet
*
* /param aType either MODELVIEW or PROJECTION
* /returns pointer to the matrix (float[16])
*/
float *get(MatrixTypes aType);
/** Updates the uniform buffer data
*
* /param aType either MODELVIEW or PROJECTION
*/
void matrixToBuffer(MatrixTypes aType);
/** Updates the uniform variables
*
* /param aType either MODELVIEW or PROJECTION
*/
void matrixToUniform(MatrixTypes aType);
/** Updates either the buffer or the uniform variables
* based on which init* function was called last
*
* /param aType either MODELVIEW or PROJECTION
*/
void matrixToGL(MatrixTypes aType);
protected:
VSML();
/// Has an init* function been called?
bool mInit;
/// Using uniform blocks?
bool mBlocks;
///brief Matrix stacks for modelview and projection matrices
std::vector<float *> mMatrixStack[2];
/// The storage for the two matrices
float mMatrix[2][16];
/// Storage for the uniform locations
GLuint mUniformLoc[2];
/// Storage for the buffer index
GLuint mBuffer;
/// Storage for the offsets within the buffer
GLuint mOffset[2];
/** Set a float* to an identity matrix
*
* /param size the order of the matrix
*/
void setIdentityMatrix( float *mat, int size=4);
/** vector cross product
*
* res = a x b
*/
void crossProduct( float *a, float *b, float *res);
/// normalize a vec3
void normalize(float *a);
};
#endif
vsml.cpp
/* --------------------------------------------------
Lighthouse3D
VSML - Very Simple Matrix Library
http://www.lighthouse3d.com/very-simple-libs
----------------------------------------------------*/
#include "vsml.h"
#include <math.h>
// This var keeps track of the single instance of VSML
VSML* VSML::gInstance = 0;
#define M_PI 3.14159265358979323846f
static inline float
DegToRad(float degrees)
{
return (float)(degrees * (M_PI / 180.0f));
};
// Singleton implementation
// use this function to get the instance of VSML
VSML*
VSML::getInstance (void) {
if (0 != gInstance)
return gInstance;
else
gInstance = new VSML();
return gInstance;
}
// VSML constructor
VSML::VSML():
mInit(false),
mBlocks(false)
{
}
// VSML destructor
VSML::~VSML()
{
}
// send the buffer data and offsets to VSML
void
VSML::initUniformBlock(GLuint buffer, GLuint modelviewOffset, GLuint projOffset)
{
mInit = true;
mBlocks = true;
mBuffer = buffer;
mOffset[MODELVIEW] = modelviewOffset;
mOffset[PROJECTION] = projOffset;
}
// send the uniform locations to VSML
void
VSML::initUniformLocs(GLuint modelviewLoc, GLuint projLoc)
{
mInit = true;
mBlocks = false;
mUniformLoc[MODELVIEW] = modelviewLoc;
mUniformLoc[PROJECTION] = projLoc;
}
// glPushMatrix implementation
void
VSML::pushMatrix(MatrixTypes aType) {
float *aux = (float *)malloc(sizeof(float) * 16);
memcpy(aux, mMatrix[aType], sizeof(float) * 16);
mMatrixStack[aType].push_back(aux);
}
// glPopMatrix implementation
void
VSML::popMatrix(MatrixTypes aType) {
float *m = mMatrixStack[aType][mMatrixStack[aType].size()-1];
memcpy(mMatrix[aType], m, sizeof(float) * 16);
mMatrixStack[aType].pop_back();
free(m);
#ifdef VSML_ALWAYS_SEND_TO_OPENGL
matrixToGL(aType);
#endif
}
// glLoadIdentity implementation
void
VSML::loadIdentity(MatrixTypes aType)
{
setIdentityMatrix(mMatrix[aType]);
#ifdef VSML_ALWAYS_SEND_TO_OPENGL
matrixToGL(aType);
#endif
}
// glMultMatrix implementation
void
VSML::multMatrix(MatrixTypes aType, float *aMatrix)
{
float *a, *b, res[16];
a = mMatrix[aType];
b = aMatrix;
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
res[j*4 + i] = 0.0f;
for (int k = 0; k < 4; ++k) {
res[j*4 + i] += a[k*4 + i] * b[j*4 + k];
}
}
}
memcpy(mMatrix[aType], res, 16 * sizeof(float));
#ifdef VSML_ALWAYS_SEND_TO_OPENGL
matrixToGL(aType);
#endif
}
// glLoadMatrix implementation
void
VSML::loadMatrix(MatrixTypes aType, float *aMatrix)
{
memcpy(mMatrix[aType], aMatrix, 16 * sizeof(float));
#ifdef VSML_ALWAYS_SEND_TO_OPENGL
matrixToGL(aType);
#endif
}
// glTranslate implementation with matrix selection
void
VSML::translate(MatrixTypes aType, float x, float y, float z)
{
float mat[16];
setIdentityMatrix(mat);
mat[12] = x;
mat[13] = y;
mat[14] = z;
multMatrix(aType,mat);
#ifdef VSML_ALWAYS_SEND_TO_OPENGL
matrixToGL(aType);
#endif
}
// glTranslate on the MODELVIEW matrix
void
VSML::translate(float x, float y, float z)
{
translate(MODELVIEW, x,y,z);
}
// glScale implementation with matrix selection
void
VSML::scale(MatrixTypes aType, float x, float y, float z)
{
float mat[16];
setIdentityMatrix(mat,4);
mat[0] = x;
mat[5] = y;
mat[10] = z;
multMatrix(aType,mat);
#ifdef VSML_ALWAYS_SEND_TO_OPENGL
matrixToGL(aType);
#endif
}
// glScale on the MODELVIEW matrix
void
VSML::scale(float x, float y, float z)
{
scale(MODELVIEW, x, y, z);
}
// glRotate implementation with matrix selection
void
VSML::rotate(MatrixTypes aType, float angle, float x, float y, float z)
{
float mat[16];
float radAngle = DegToRad(angle);
float co = cos(radAngle);
float si = sin(radAngle);
float x2 = x*x;
float y2 = y*y;
float z2 = z*z;
mat[0] = x2 + (y2 + z2) * co;
mat[4] = x * y * (1 - co) - z * si;
mat[8] = x * z * (1 - co) + y * si;
mat[12]= 0.0f;
mat[1] = x * y * (1 - co) + z * si;
mat[5] = y2 + (x2 + z2) * co;
mat[9] = y * z * (1 - co) - x * si;
mat[13]= 0.0f;
mat[2] = x * z * (1 - co) - y * si;
mat[6] = y * z * (1 - co) + x * si;
mat[10]= z2 + (x2 + y2) * co;
mat[14]= 0.0f;
mat[3] = 0.0f;
mat[7] = 0.0f;
mat[11]= 0.0f;
mat[15]= 1.0f;
multMatrix(aType,mat);
#ifdef VSML_ALWAYS_SEND_TO_OPENGL
matrixToGL(aType);
#endif
}
// glRotate implementation in the MODELVIEW matrix
void
VSML::rotate(float angle, float x, float y, float z)
{
rotate(MODELVIEW,angle,x,y,z);
}
// gluLookAt implementation
void
VSML::lookAt(float xPos, float yPos, float zPos,
float xLook, float yLook, float zLook,
float xUp, float yUp, float zUp)
{
float dir[3], right[3], up[3];
up[0] = xUp; up[1] = yUp; up[2] = zUp;
dir[0] = (xLook - xPos);
dir[1] = (yLook - yPos);
dir[2] = (zLook - zPos);
normalize(dir);
crossProduct(dir,up,right);
normalize(right);
crossProduct(right,dir,up);
normalize(up);
float m1[16],m2[16];
m1[0] = right[0];
m1[4] = right[1];
m1[8] = right[2];
m1[12] = 0.0f;
m1[1] = up[0];
m1[5] = up[1];
m1[9] = up[2];
m1[13] = 0.0f;
m1[2] = -dir[0];
m1[6] = -dir[1];
m1[10] = -dir[2];
m1[14] = 0.0f;
m1[3] = 0.0f;
m1[7] = 0.0f;
m1[11] = 0.0f;
m1[15] = 1.0f;
setIdentityMatrix(m2,4);
m2[12] = -xPos;
m2[13] = -yPos;
m2[14] = -zPos;
multMatrix(MODELVIEW, m1);
multMatrix(MODELVIEW, m2);
#ifdef VSML_ALWAYS_SEND_TO_OPENGL
matrixToGL(MODELVIEW);
#endif
}
// gluPerspective implementation
void
VSML::perspective(float fov, float ratio, float nearp, float farp)
{
float projMatrix[16];
float f = 1.0f / tan (fov * (M_PI / 360.0f));
setIdentityMatrix(projMatrix,4);
projMatrix[0] = f / ratio;
projMatrix[1 * 4 + 1] = f;
projMatrix[2 * 4 + 2] = (farp + nearp) / (nearp - farp);
projMatrix[3 * 4 + 2] = (2.0f * farp * nearp) / (nearp - farp);
projMatrix[2 * 4 + 3] = -1.0f;
projMatrix[3 * 4 + 3] = 0.0f;
multMatrix(PROJECTION, projMatrix);
#ifdef VSML_ALWAYS_SEND_TO_OPENGL
matrixToGL(PROJECTION);
#endif
}
// glOrtho implementation
void
VSML::ortho(float left, float right, float bottom, float top, float nearp, float farp)
{
float m[16];
setIdentityMatrix(m,4);
m[0 * 4 + 0] = 2 / (right - left);
m[1 * 4 + 1] = 2 / (top - bottom);
m[2 * 4 + 2] = -2 / (farp - nearp);
m[3 * 4 + 0] = -(right + left) / (right - left);
m[3 * 4 + 1] = -(top + bottom) / (top - bottom);
m[3 * 4 + 2] = -(farp + nearp) / (farp - nearp);
multMatrix(PROJECTION, m);
#ifdef VSML_ALWAYS_SEND_TO_OPENGL
matrixToGL(PROJECTION);
#endif
}
// glFrustum implementation
void
VSML::frustum(float left, float right, float bottom, float top, float nearp, float farp)
{
float m[16];
setIdentityMatrix(m,4);
m[0 * 4 + 0] = 2 * nearp / (right-left);
m[1 * 4 + 1] = 2 * nearp / (top - bottom);
m[2 * 4 + 0] = (right + left) / (right - left);
m[2 * 4 + 1] = (top + bottom) / (top - bottom);
m[2 * 4 + 2] = - (farp + nearp) / (farp - nearp);
m[2 * 4 + 3] = -1.0f;
m[3 * 4 + 2] = - 2 * farp * nearp / (farp-nearp);
m[3 * 4 + 3] = 0.0f;
multMatrix(PROJECTION, m);
#ifdef VSML_ALWAYS_SEND_TO_OPENGL
matrixToGL(PROJECTION);
#endif
}
// returns a pointer to the requested matrix
float *
VSML::get(MatrixTypes aType)
{
return mMatrix[aType];
}
/* -----------------------------------------------------
SEND MATRICES TO OPENGL
------------------------------------------------------*/
// to be used with uniform blocks
void
VSML::matrixToBuffer(MatrixTypes aType)
{
if (mInit && mBlocks) {
glBindBuffer(GL_UNIFORM_BUFFER,mBuffer);
glBufferSubData(GL_UNIFORM_BUFFER, mOffset[aType], 16 * sizeof(float), mMatrix[aType]);
glBindBuffer(GL_UNIFORM_BUFFER,0);
}
}
// to be used with uniform variables
void
VSML::matrixToUniform(MatrixTypes aType)
{
if (mInit && !mBlocks) {
glUniformMatrix4fv(mUniformLoc[aType], 1, false, mMatrix[aType]);
}
}
// universal
void
VSML::matrixToGL(MatrixTypes aType)
{
if (mInit) {
if (mBlocks) {
glBindBuffer(GL_UNIFORM_BUFFER,mBuffer);
glBufferSubData(GL_UNIFORM_BUFFER, mOffset[aType], 16 * sizeof(float), mMatrix[aType]);
glBindBuffer(GL_UNIFORM_BUFFER,0);
}
else {
glUniformMatrix4fv(mUniformLoc[aType], 1, false, mMatrix[aType]);
}
}
}
// -----------------------------------------------------
// AUX functions
// -----------------------------------------------------
// sets the square matrix mat to the identity matrix,
// size refers to the number of rows (or columns)
void
VSML::setIdentityMatrix( float *mat, int size) {
// fill matrix with 0s
for (int i = 0; i < size * size; ++i)
mat[i] = 0.0f;
// fill diagonal with 1s
for (int i = 0; i < size; ++i)
mat[i + i * size] = 1.0f;
}
// res = a cross b;
void
VSML::crossProduct( float *a, float *b, float *res) {
res[0] = a[1] * b[2] - b[1] * a[2];
res[1] = a[2] * b[0] - b[2] * a[0];
res[2] = a[0] * b[1] - b[0] * a[1];
}
// Normalize a vec3
void
VSML::normalize(float *a) {
float mag = sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
a[0] /= mag;
a[1] /= mag;
a[2] /= mag;
}