PDA

View Full Version : OpenGL 3.0 model-view transformation



RigoN
02-12-2009, 07:43 PM
Hello ALL!!!
Please help in converting to opengl 3.0. Especially with regard to model-view transformation. Given that glPushMatrix, glPopMatrix, glTranslate, glRotate, glScale declared as "deprecated". Please attach a small example of code.

Zengar
02-12-2009, 10:22 PM
You can use deprecated stuff in OpenGL 3.0 contexts. Why would you want to move to "pure" 3.x anyway? The only reason I see is adopting all-shader approach, but if you had that goal you wouldn't be asking this questions in the first place.

marshats
02-12-2009, 10:35 PM
Suppose you have a basic vertex shader with uniform variables you must control that accomplishes the same functionality as glPushMatrix, glTranslate, etc since 3.0 doesn't do this for you anymore. The most basic shader would then be:

const GLchar *g_vertexShader[] = {"#version 130\n",
"uniform mat4 glm_ProjectionMatrix;\n",
"uniform mat4 glm_ModelViewMatrix;\n",
"in vec4 dgl_Vertex;\n",
"void main(void)\n",
"{\n",
" gl_Position = glm_ProjectionMatrix*glm_ModelViewMatrix*dgl_Verte x;\n",
"}\n"
};

In essence, you now have to explicitly define your our matrices and vertex names (glm_ProjectionMatrix, glm_ModelViewMatrix, dgl_Vertex) to replace the deprecated ones of similar name that existed already.

Then in your code you must set a uniform 4x4 matrix for the
glm_ProjectionMatrix and glm_ModelViewMatrix explicitly with
glUniformMatrix4fv(glm_ProjectionMatrix_id, 1, false, address(glm_ProjectionMatrix.top()) );

But how do you set and manipulate these two matrices? I found a nice library called OpenGL Mathematics ( http://glm.g-truc.net/ ) that is a set of C++ headers that work nicely for me.

Basically all the openGL functions that you mention map nicely using this library.
I use the c++ STD library to get the push/pop functionality using the std::stack

#include <stack>

std::stack<mat4> glm_ProjectionMatrix;
std::stack<mat4> glm_ModelViewMatrix;

//glMatrixMode(GL_MODELVIEW); // unecessary since use matrix by name
glm_ModelViewMatrix.top() = mat4(1.0); // glLoadIdentity
glm_ModelViewMatrix.top() *= lookAt( vec3(eyeX, eyeY, eyeZ), vec3(centerX, centerY, centerZ), vec3(upX, upY, upZ)); //=gluLookAt()
glm_ModelViewMatrix.push(glm_ModelViewMatrix.top() ); // = glPushMatrix();
glm_ModelViewMatrix.top() *=translate( vec3(0.0, 0.0, 0.25) ); //= glTranslate()
glm_ModelViewMatrix.top() *=rotate(45.0f, vec3(1.0, 1.0, 0.0) ); //=same as glRotate()
glm_ModelViewMatrix.top() *=scale( vec3(0.2, 0.2, 0.2) ); //=same as glScale()

glUniformMatrix4fv(glm_ModelViewMatrix_id, 1, false, address(glm_ModelViewMatrix.top()) ); // set the shader value

Draw_vao(1);

glm_ModelViewMatrix.pop(); //= glPopMatrix()

and GLM even has all the lookat, perspective, ortho, frustrum gl commands too!

//glMatrixMode(GL_PROJECTION); // unecessary since use matrix by name
glm_ProjectionMatrix.top() = mat4(1.0); //glLoadIdentity
glm_ProjectionMatrix.top() *= perspective(20.0f,ratio,1.0f,3.0f); //=glPerspective
glUniformMatrix4fv(glm_ProjectionMatrix_id, 1, false, address(glm_ProjectionMatrix.top()) ); // set the shader value

This all seems complicated if your seeing shaders for the first time but in my opinion GLM has some great aspects for helping fill the "matrix" gap left by the 3.0 void. Note, the .top() is part of the c++ standard template library
and is used to get the topmost matrix on the stack.

I saw some good background reading material at http://www.songho.ca/opengl/gl_transform.html
explaining how openGL does the matrix transformations in the prior openGL 3.0 era.

marshats
02-12-2009, 11:38 PM
Here is a complete code example that I have been using to learn what the consequences of opengl 3.0 might be. This uses glm, freeglut, and glew libraries. I am using g++ compiler ... hope seeing the code helps explain a little better my previous post.

Once compiled and running change the camera view:
press t,T to rotate camera theta
press p,P to rotate camera phi




//on linux or mingw: g++ demo.cpp -lglut -lGLEW
// modified to use GLM library from http://pheatt.emporia.edu/courses/2005/cs410f05/hand14/hand14.htm
// modified to use camera at begining of MODELVIEW Transformations, not in the Projection Transform! see http://www.sjbaker.org/steve/omniv/projection_abuse.html
#include <GL/glew.h> // great opengl extensions helper
#include <GL/freeglut.h> // use of opengl 3.0 context requires freeglut from svn!

#include <glm/glm.h> //OpenGL Mathematics (GLM). A C++ mathematics library for 3D graphics.
#include <glm/glmext.h>
#include <glm/GLM_VIRTREV_address.h> // gives helper function address(X) instead of using &amp;X[0][0]
namespace glm
{
// read glm/gtx/transform.h for function prototypes
using GLM_GTX_transform;
using GLM_GTX_transform2; // for lookAt
using GLM_GTX_matrix_projection;
}
using namespace glm;

#include <cstdio>
#include <cmath>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <stack>
#include <cstring>
#include <cassert>

namespace global {
int theta = 0;
int phi = 0;
GLfloat ratio = 1.0;
int width = 512;
int height = 512;
};

class CustomGraphicsPipeline
{
GLuint shader_id;
std::stack<mat4> glm_ProjectionMatrix; //cpu-side
GLint glm_ProjectionMatrix_id; //cpu-side hook to shader uniform
std::stack<mat4> glm_ModelViewMatrix; //cpu-side
GLint glm_ModelViewMatrix_id; //cpu-side hook to shader uniform
GLuint vao_id[2]; // vertex array object hook id
GLuint vao_elementcount[2]; // number of attribute elements in vao ie number of vertices
GLuint vao_primitivetype[2]; // type [GL_LINE_LOOP|GL_TRIANGLES|etc]
public:
CustomGraphicsPipeline() :
shader_id(NULL),
glm_ProjectionMatrix_id(NULL),
glm_ModelViewMatrix_id(NULL)
{
glm_ProjectionMatrix.push( mat4(1.0f) ); // identity matrix
glm_ModelViewMatrix.push( mat4(1.0f) ), // identity matrix
vao_id[0]=NULL;
vao_id[1]=NULL;
vao_elementcount[0]=0;
vao_elementcount[1]=0;
vao_primitivetype[0] = GL_LINE_LOOP;
vao_primitivetype[1] = GL_TRIANGLES;
}
~CustomGraphicsPipeline() {}

bool Init() // All Setup For OpenGL Goes Here
{
GLint ret = true; // optimistic return value upon completion of execution

std::cout << "GL_VERSION: " << glGetString(GL_VERSION) << std::endl;
std::cout << "GL_EXTENSIONS: " << glGetString(GL_EXTENSIONS) << std::endl;
std::cout << "GL_RENDERER: " << glGetString(GL_RENDERER) << std::endl;
std::cout << "GL_VENDOR: " << glGetString(GL_VENDOR) << std::endl;
std::cout << "GLU_VERSION: " << gluGetString(GLU_VERSION) << std::endl;
std::cout << "GLU_EXTENSIONS: " << gluGetString(GLU_EXTENSIONS) << std::endl;
std::cout << "GLUT_API_VERSION: " << GLUT_API_VERSION << std::endl;
#ifdef GLUT_XLIB_IMPLEMENTATION
std::cout << "GLUT_XLIB_IMPLEMENTATION: " << GLUT_XLIB_IMPLEMENTATION << std::endl;
#endif
std::cout << "press t,T to rotate camera theta" << std::endl;
std::cout << "press p,P to rotate camera phi" << std::endl;

glEnable(GL_DEPTH_TEST);
glClearColor(0.2f, 0.2f, 0.2f, 0.5f);

//Datas destioned for video memory, can be local (and lost after bound to GPU!).
GLfloat vertices0[] = { // dgl_Vertex
1.0, -1.0, 0.0, 1.0, // xyzw
-1.0, -1.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0
};
size_t Nbytes_vertices0=sizeof(vertices0);

GLfloat colors0[] = { // dgl_Color
0.0, 0.0, 1.0, 1.0, //rgba
0.0, 1.0, 0.0, 1.0,
1.0, 0.0, 0.0, 1.0
};
size_t Nbytes_colors0=sizeof(colors0);

GLfloat vertices1[] = { // dgl_Vertex
0.5, -0.5, 0.0, 1.0, // xyzw
-0.5, -0.5, 0.0, 1.0,
0.0, 0.5, 0.0, 1.0
};
size_t Nbytes_vertices1=sizeof(vertices1);

GLfloat colors1[] = { // dgl_Color
0.0, 0.0, 1.0, 1.0, //rgba
0.0, 1.0, 0.0, 1.0,
1.0, 0.0, 0.0, 1.0
};
size_t Nbytes_colors1=sizeof(colors1);

const GLchar *g_vertexShader[] = {"#version 130\n",
"uniform mat4 glm_ProjectionMatrix;\n", // replaces deprecated gl_ProjectionMatrix see http://www.lighthouse3d.com/opengl/glsl/index.php?minimal
"uniform mat4 glm_ModelViewMatrix;\n", // replaces deprecated gl_ModelViewMatrix
"in vec4 dgl_Vertex;\n", // replaces deprecated gl_Vertex
"in vec4 dgl_Color;\n", // replaces deprecated gl_Color
"invariant out vec4 Color;\n", // to fragment shader
"void main(void)\n",
"{\n",
" Color = dgl_Color;\n",
" gl_Position = glm_ProjectionMatrix*glm_ModelViewMatrix*dgl_Verte x;\n", // replaces deprecated ftransform() see http://www.songho.ca/opengl/gl_transform.html
"}\n"
};

const GLchar *g_fragmentShader[] = {"#version 130\n",
"invariant in vec4 Color;\n", // from vertex shader
"out vec4 dgl_FragColor;\n", // replaces deprecated gl_FragColor
"void main(void)\n",
"{\n",
" dgl_FragColor = Color;\n", // gl_FragColor is deprecated
"}\n"
};

// compile Vertex shader
GLuint m_vxShaderId = glCreateShader(GL_VERTEX_SHADER);
GLsizei nlines_vx = sizeof(g_vertexShader)/sizeof(const GLchar*);
glShaderSource(m_vxShaderId, nlines_vx, (const GLchar**)g_vertexShader, NULL);
glCompileShader(m_vxShaderId);
CheckShader(m_vxShaderId, GL_COMPILE_STATUS, &amp;ret, "unable to compile the vertex shader!");

// compile Fragment shader
GLuint m_fgShaderId = glCreateShader(GL_FRAGMENT_SHADER);
GLsizei nlines_fg = sizeof(g_fragmentShader)/sizeof(const GLchar*);
glShaderSource(m_fgShaderId, nlines_fg, (const GLchar**)g_fragmentShader, NULL);
glCompileShader(m_fgShaderId);
CheckShader(m_fgShaderId, GL_COMPILE_STATUS, &amp;ret, "unable to compile the fragment shader!");

// link shaders
shader_id = glCreateProgram();
glAttachShader(shader_id, m_vxShaderId);
glAttachShader(shader_id, m_fgShaderId);
glLinkProgram(shader_id);
CheckShader(shader_id, GL_LINK_STATUS, &amp;ret, "unable to link the program!");

//hooks from CPU to GPU
//define Uniform hooks
glm_ProjectionMatrix_id = glGetUniformLocation(shader_id, "glm_ProjectionMatrix");
glm_ModelViewMatrix_id = glGetUniformLocation(shader_id, "glm_ModelViewMatrix");

//guard that all attributes have same number of elements
assert(Nbytes_vertices0/4/sizeof(GLfloat)==Nbytes_colors0/4/sizeof(GLfloat));
vao_elementcount[0]=Nbytes_vertices0/4/sizeof(GLfloat); // number of elements for first VAO
assert(Nbytes_vertices1/4/sizeof(GLfloat)==Nbytes_colors1/4/sizeof(GLfloat));
vao_elementcount[1]=Nbytes_vertices1/4/sizeof(GLfloat); // number of elements for second VAO

//create and define vertex array objects
glGenVertexArrays(2, &amp;vao_id[0]); // vao_id[#] will be referenced in Draw()
defineVertexArrayObject(vao_id[0],Nbytes_vertices0,4,GL_FLOAT,vertices0,colors0); //VertexAttribArray: vertices0, colors0
defineVertexArrayObject(vao_id[1],Nbytes_vertices1,4,GL_FLOAT,vertices1,colors1); //VertexAttribArray: vertices1, colors1

// finally, use the shader for rendering
glUseProgram(shader_id); // select the shaders program

return ret; // Initialization Went OK?
}

void defineVertexArrayObject(GLuint vaoId, size_t Nbytes, GLint size, GLenum type, GLfloat *vertices, GLfloat *colors)
{
//enable vertex array object to be defined
glBindVertexArray(vaoId);

//generate VBO foreach 'in'; dgl_Vertex and dgl_Color
GLuint m_vboId[2];
glGenBuffers(2, &amp;m_vboId[0]);

//"in vec4 dgl_Vertex;",
glBindBuffer(GL_ARRAY_BUFFER, m_vboId[0] ); // enable the 1st VBO
glBufferData(GL_ARRAY_BUFFER, Nbytes, vertices, GL_STATIC_DRAW); // fill the VBO with vertices data
const GLuint index_mPosition = glGetAttribLocation(shader_id,"dgl_Vertex"); // get ID for "dgl_Vertex"
glVertexAttribPointer(index_mPosition, size, type, GL_FALSE, 0, 0); // VBO point to the "dgl_Vertex" attribute
glEnableVertexAttribArray(index_mPosition); // enable VBO vertex attribute ("dgl_Vertex")

//"in vec4 dgl_Color;",
glBindBuffer(GL_ARRAY_BUFFER, m_vboId[1]); // enable the 2nd VBO
glBufferData(GL_ARRAY_BUFFER, Nbytes , colors, GL_STATIC_DRAW); // fill the 2nd VBO with colors data
const GLuint index_mcolor = glGetAttribLocation(shader_id,"dgl_Color"); // get ID for "dgl_Color"
glVertexAttribPointer(index_mcolor, size, type, GL_FALSE, 0, 0); // VBO point to the "dgl_Color" attribute
glEnableVertexAttribArray(index_mcolor); // enable VBO vertex attribute ("dgl_Color")
}

void CheckShader(GLuint id, GLuint type, GLint *ret, const char *onfail)
{
//Check if something is wrong with the shader
switch(type) {
case(GL_COMPILE_STATUS):
glGetShaderiv(id, type, ret);
if(*ret == false){
int infologLength = 0;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &amp;infologLength);
GLchar buffer[infologLength];
GLsizei charsWritten = 0;
std::cout << onfail << std::endl;
glGetShaderInfoLog(id, infologLength, &amp;charsWritten, buffer);
std::cout << buffer << std::endl;
}
break;
case(GL_LINK_STATUS):
glGetProgramiv(id, type, ret);
if(*ret == false){
int infologLength = 0;
glGetProgramiv(id, GL_INFO_LOG_LENGTH, &amp;infologLength);
GLchar buffer[infologLength];
GLsizei charsWritten = 0;
std::cout << onfail << std::endl;
glGetProgramInfoLog(id, infologLength, &amp;charsWritten, buffer);
std::cout << buffer << std::endl;
}
default:
break;
};
}

void Draw_vao(size_t index)
{
glBindVertexArray(vao_id[index]); // select the vertex array object:vao_id[index] by definiton using vertices_index,colors_index
glDrawArrays(vao_primitivetype[index], 0, vao_elementcount[index]); // draw the array (at the speed of light)
}

void Draw() // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

glUniformMatrix4fv(glm_ProjectionMatrix_id, 1, false, &amp;glm_ProjectionMatrix.top()[0][0] ); // set the rotation/translation/scale matrix
//glUniformMatrix4fv(glm_ProjectionMatrix_id, 1, false, address(glm_ProjectionMatrix.top()) ); // set the rotation/translation/scale matrix

{
glm_ModelViewMatrix.push(glm_ModelViewMatrix.top() );
//glm_ModelViewMatrix.top() *= translate( vec3(0.5, 0.5, 0.0) );
glm_ModelViewMatrix.top() *= rotate(45.0f, vec3(0.0, 0.0, 1.0) );
glm_ModelViewMatrix.top() *= scale( vec3(0.2, 0.2, 0.2) );

glUniformMatrix4fv(glm_ModelViewMatrix_id, 1, false, &amp;glm_ModelViewMatrix.top()[0][0] ); // set the rotation/translation/scale matrix
//glUniformMatrix4fv(glm_ModelViewMatrix_id, 1, false, address(glm_ModelViewMatrix.top()) ); // set the rotation/translation/scale matrix

Draw_vao(0);

glm_ModelViewMatrix.pop();
}

{
glm_ModelViewMatrix.push(glm_ModelViewMatrix.top() );
glm_ModelViewMatrix.top() *= translate( vec3(0.0, 0.0, 0.25) );
//glm_ModelViewMatrix.top() *= rotate(45.0f, vec3(1.0, 1.0, 0.0) );
glm_ModelViewMatrix.top() *= scale( vec3(0.2, 0.2, 0.2) );

glUniformMatrix4fv(glm_ModelViewMatrix_id, 1, false, &amp;glm_ModelViewMatrix.top()[0][0] ); // set the rotation/translation/scale matrix
//glUniformMatrix4fv(glm_ModelViewMatrix_id, 1, false, address(glm_ModelViewMatrix.top()) ); // set the rotation/translation/scale matrix

Draw_vao(1);

glm_ModelViewMatrix.pop();
}
}

bool Reshape(GLfloat ratio)
{
//glMatrixMode(GL_PROJECTION);
glm_ProjectionMatrix.top() = mat4(1.0); //glLoadIdentity
glm_ProjectionMatrix.top() *= perspective(20.0f,ratio,1.0f,3.0f);
//glLoadMatrixf(address(glm_ProjectionMatrix.top())) ;
glUniformMatrix4fv(glm_ProjectionMatrix_id, 1, false, &amp;glm_ProjectionMatrix.top()[0][0] ); // set the rotation/translation/scale matrix
}

bool SetCamera(GLfloat theta, GLfloat phi)
{
//////////////
// Set the camera view.
static const double radianFactor = acos(0.0) / 90.0;
float r = 1.0f*2.0; // approx. want half way between near + far (see perspective)
float eyeX = r * sin(theta * radianFactor) * cos(phi * radianFactor);
float eyeY = r * sin(theta * radianFactor) * sin(phi * radianFactor);
float eyeZ = r * cos(radianFactor * theta);

float centerX = 0, centerY = 0, centerZ = 0;
float upX = 0, upY = 1.0f, upZ = 0;

//glMatrixMode(GL_MODELVIEW);
glm_ModelViewMatrix.top() = mat4(1.0); // LoadIdentity
glm_ModelViewMatrix.top() *= lookAt( vec3(eyeX, eyeY, eyeZ), vec3(centerX, centerY, centerZ), vec3(upX, upY, upZ));
//glLoadMatrixf(address(glm_ModelViewMatrix.top()));
glUniformMatrix4fv(glm_ModelViewMatrix_id, 1, false, &amp;glm_ModelViewMatrix.top()[0][0] );

return true;
}
};

// GLOBAL ///////////////////////////////////////////////////////////
CustomGraphicsPipeline Scene;
/////////////////////////////////////////////////////////////////////

static void timer(int dt_msec)
{
static GLfloat time_msec = 0.0;
time_msec += dt_msec; // absolute time

Scene.SetCamera(global::theta, global::phi);

glutPostRedisplay();
glutTimerFunc(30,timer,30); // come back in 30msec
}

static void display(void)
{
Scene.Draw();
glutSwapBuffers();
}

static void reshape(int w, int h)
{
// Set the viewport to be the entire window
glViewport(0, 0, w, h);

// Prevent a divide by zero, when window is too short
if(h == 0) h = 1;

global::width = w;
global::height = h;
global::ratio = 1.0 * w / h;

Scene.Reshape(global::ratio);
}

static void keyboard(unsigned char k, int x, int y)
{
switch (k) {
case 't' : global::theta++; if(global::theta > 360) global::theta = 1; break;
case 'p' : global::phi++; if(global::phi > 360) global::phi = 1; break;
case 'T' : global::theta--; if(global::theta < 0) global::theta = 359; break;
case 'P' : global::phi--; if(global::phi < 0) global::phi = 359; break;
case 27 : exit(0); break;
}
}

int main( int argc, char *argv[] )
{
glutInit( &amp;argc, argv );
//opengl 3.0 with freeglut requires to install latest version from svn
//but not necessary to actually get openGL context since code will run anyhow.
//glutInitContextVersion( 3, 0 ); // freeglut is so cool! get openGL 3.0 context
//glutInitContextFlags( int flags )
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(global::width, global::height);
glutCreateWindow("demo opengl 3.0 matrix transformations");

glewInit();

assert( Scene.Init() ); // bail if scene initialization fails

glutTimerFunc(0,timer,0);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);

glutMainLoop();

return 0;
}

LangFox
02-23-2009, 07:23 PM
Great example!Thanks marshats!!

marshats
07-31-2009, 09:35 PM
As an update dealing with the newer headers for openGL 3, I found I had to add the gl3.h header explicitly and a -DGL3_PROTOTYPES on the command line to remove errors at compile time.

Here is the updated code that compiles and runs again:


//on linux or mingw: g++ demo.cpp -lglut -lGLEW -DGL3_PROTOTYPES
// modified to use GLM library from http://pheatt.emporia.edu/courses/2005/cs410f05/hand14/hand14.htm
// modified to use camera at begining of MODELVIEW Transformations, not in the Projection Transform! see http://www.sjbaker.org/steve/omniv/projection_abuse.html
#include <GL/glew.h> // great opengl extensions helper
#include <GL/gl3.h>
#include <GL/freeglut.h> // use of opengl 3.0 context requires freeglut from svn!

#include <glm/glm.h> //OpenGL Mathematics (GLM). A C++ mathematics library for 3D graphics.
#include <glm/glmext.h>
#include <glm/GLM_VIRTREV_address.h> // gives helper function address(X) instead of using &amp;X[0][0]
namespace glm
{
// read glm/gtx/transform.h for function prototypes
using GLM_GTX_transform;
using GLM_GTX_transform2; // for lookAt
using GLM_GTX_matrix_projection;
}
using namespace glm;

#include <cstdio>
#include <cmath>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <stack>
#include <cstring>
#include <cassert>

namespace global {
int theta = 0;
int phi = 0;
GLfloat ratio = 1.0;
int width = 512;
int height = 512;
};

class CustomGraphicsPipeline
{
GLuint shader_id;
std::stack<mat4> glm_ProjectionMatrix; //cpu-side
GLint glm_ProjectionMatrix_id; //cpu-side hook to shader uniform
std::stack<mat4> glm_ModelViewMatrix; //cpu-side
GLint glm_ModelViewMatrix_id; //cpu-side hook to shader uniform
GLuint vao_id[2]; // vertex array object hook id
GLuint vao_elementcount[2]; // number of attribute elements in vao ie number of vertices
GLuint vao_primitivetype[2]; // type [GL_LINE_LOOP|GL_TRIANGLES|etc]
public:
CustomGraphicsPipeline() :
shader_id(NULL),
glm_ProjectionMatrix_id(NULL),
glm_ModelViewMatrix_id(NULL)
{
glm_ProjectionMatrix.push( mat4(1.0f) ); // identity matrix
glm_ModelViewMatrix.push( mat4(1.0f) ), // identity matrix
vao_id[0]=NULL;
vao_id[1]=NULL;
vao_elementcount[0]=0;
vao_elementcount[1]=0;
vao_primitivetype[0] = GL_LINE_LOOP;
vao_primitivetype[1] = GL_TRIANGLES;
}
~CustomGraphicsPipeline() {}

bool Init() // All Setup For OpenGL Goes Here
{
GLint ret = true; // optimistic return value upon completion of execution

std::cout << "GL_VERSION: " << glGetString(GL_VERSION) << std::endl;
std::cout << "GL_EXTENSIONS: " << glGetString(GL_EXTENSIONS) << std::endl;
std::cout << "GL_RENDERER: " << glGetString(GL_RENDERER) << std::endl;
std::cout << "GL_VENDOR: " << glGetString(GL_VENDOR) << std::endl;
std::cout << "GLU_VERSION: " << gluGetString(GLU_VERSION) << std::endl;
std::cout << "GLU_EXTENSIONS: " << gluGetString(GLU_EXTENSIONS) << std::endl;
std::cout << "GLUT_API_VERSION: " << GLUT_API_VERSION << std::endl;
#ifdef GLUT_XLIB_IMPLEMENTATION
std::cout << "GLUT_XLIB_IMPLEMENTATION: " << GLUT_XLIB_IMPLEMENTATION << std::endl;
#endif
std::cout << "press t,T to rotate camera theta" << std::endl;
std::cout << "press p,P to rotate camera phi" << std::endl;

glEnable(GL_DEPTH_TEST);
glClearColor(0.2f, 0.2f, 0.2f, 0.5f);

//Datas destioned for video memory, can be local (and lost after bound to GPU!).
GLfloat vertices0[] = { // dgl_Vertex
1.0, -1.0, 0.0, 1.0, // xyzw
-1.0, -1.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0
};
size_t Nbytes_vertices0=sizeof(vertices0);

GLfloat colors0[] = { // dgl_Color
0.0, 0.0, 1.0, 1.0, //rgba
0.0, 1.0, 0.0, 1.0,
1.0, 0.0, 0.0, 1.0
};
size_t Nbytes_colors0=sizeof(colors0);

GLfloat vertices1[] = { // dgl_Vertex
0.5, -0.5, 0.0, 1.0, // xyzw
-0.5, -0.5, 0.0, 1.0,
0.0, 0.5, 0.0, 1.0
};
size_t Nbytes_vertices1=sizeof(vertices1);

GLfloat colors1[] = { // dgl_Color
0.0, 0.0, 1.0, 1.0, //rgba
0.0, 1.0, 0.0, 1.0,
1.0, 0.0, 0.0, 1.0
};
size_t Nbytes_colors1=sizeof(colors1);

const GLchar *g_vertexShader[] = {"#version 130\n",
"uniform mat4 glm_ProjectionMatrix;\n", // replaces deprecated gl_ProjectionMatrix see http://www.lighthouse3d.com/opengl/glsl/index.php?minimal
"uniform mat4 glm_ModelViewMatrix;\n", // replaces deprecated gl_ModelViewMatrix
"in vec4 dgl_Vertex;\n", // replaces deprecated gl_Vertex
"in vec4 dgl_Color;\n", // replaces deprecated gl_Color
"invariant out vec4 Color;\n", // to fragment shader
"void main(void)\n",
"{\n",
" Color = dgl_Color;\n",
" gl_Position = glm_ProjectionMatrix*glm_ModelViewMatrix*dgl_Verte x;\n", // replaces deprecated ftransform() see http://www.songho.ca/opengl/gl_transform.html
"}\n"
};

const GLchar *g_fragmentShader[] = {"#version 130\n",
"invariant in vec4 Color;\n", // from vertex shader
"out vec4 dgl_FragColor;\n", // replaces deprecated gl_FragColor
"void main(void)\n",
"{\n",
" dgl_FragColor = Color;\n", // gl_FragColor is deprecated
"}\n"
};

// compile Vertex shader
GLuint m_vxShaderId = glCreateShader(GL_VERTEX_SHADER);
GLsizei nlines_vx = sizeof(g_vertexShader)/sizeof(const GLchar*);
glShaderSource(m_vxShaderId, nlines_vx, (const GLchar**)g_vertexShader, NULL);
glCompileShader(m_vxShaderId);
CheckShader(m_vxShaderId, GL_COMPILE_STATUS, &amp;ret, "unable to compile the vertex shader!");

// compile Fragment shader
GLuint m_fgShaderId = glCreateShader(GL_FRAGMENT_SHADER);
GLsizei nlines_fg = sizeof(g_fragmentShader)/sizeof(const GLchar*);
glShaderSource(m_fgShaderId, nlines_fg, (const GLchar**)g_fragmentShader, NULL);
glCompileShader(m_fgShaderId);
CheckShader(m_fgShaderId, GL_COMPILE_STATUS, &amp;ret, "unable to compile the fragment shader!");

// link shaders
shader_id = glCreateProgram();
glAttachShader(shader_id, m_vxShaderId);
glAttachShader(shader_id, m_fgShaderId);
glLinkProgram(shader_id);
CheckShader(shader_id, GL_LINK_STATUS, &amp;ret, "unable to link the program!");

//hooks from CPU to GPU
//define Uniform hooks
glm_ProjectionMatrix_id = glGetUniformLocation(shader_id, "glm_ProjectionMatrix");
glm_ModelViewMatrix_id = glGetUniformLocation(shader_id, "glm_ModelViewMatrix");

//guard that all attributes have same number of elements
assert(Nbytes_vertices0/4/sizeof(GLfloat)==Nbytes_colors0/4/sizeof(GLfloat));
vao_elementcount[0]=Nbytes_vertices0/4/sizeof(GLfloat); // number of elements for first VAO
assert(Nbytes_vertices1/4/sizeof(GLfloat)==Nbytes_colors1/4/sizeof(GLfloat));
vao_elementcount[1]=Nbytes_vertices1/4/sizeof(GLfloat); // number of elements for second VAO

//create and define vertex array objects
glGenVertexArrays(2, &amp;vao_id[0]); // vao_id[#] will be referenced in Draw()
defineVertexArrayObject(vao_id[0],Nbytes_vertices0,4,GL_FLOAT,vertices0,colors0); //VertexAttribArray: vertices0, colors0
defineVertexArrayObject(vao_id[1],Nbytes_vertices1,4,GL_FLOAT,vertices1,colors1); //VertexAttribArray: vertices1, colors1

// finally, use the shader for rendering
glUseProgram(shader_id); // select the shaders program

return ret; // Initialization Went OK?
}

void defineVertexArrayObject(GLuint vaoId, size_t Nbytes, GLint size, GLenum type, GLfloat *vertices, GLfloat *colors)
{
//enable vertex array object to be defined
glBindVertexArray(vaoId);

//generate VBO foreach 'in'; dgl_Vertex and dgl_Color
GLuint m_vboId[2];
glGenBuffers(2, &amp;m_vboId[0]);

//"in vec4 dgl_Vertex;",
glBindBuffer(GL_ARRAY_BUFFER, m_vboId[0] ); // enable the 1st VBO
glBufferData(GL_ARRAY_BUFFER, Nbytes, vertices, GL_STATIC_DRAW); // fill the VBO with vertices data
const GLuint index_mPosition = glGetAttribLocation(shader_id,"dgl_Vertex"); // get ID for "dgl_Vertex"
glVertexAttribPointer(index_mPosition, size, type, GL_FALSE, 0, 0); // VBO point to the "dgl_Vertex" attribute
glEnableVertexAttribArray(index_mPosition); // enable VBO vertex attribute ("dgl_Vertex")

//"in vec4 dgl_Color;",
glBindBuffer(GL_ARRAY_BUFFER, m_vboId[1]); // enable the 2nd VBO
glBufferData(GL_ARRAY_BUFFER, Nbytes , colors, GL_STATIC_DRAW); // fill the 2nd VBO with colors data
const GLuint index_mcolor = glGetAttribLocation(shader_id,"dgl_Color"); // get ID for "dgl_Color"
glVertexAttribPointer(index_mcolor, size, type, GL_FALSE, 0, 0); // VBO point to the "dgl_Color" attribute
glEnableVertexAttribArray(index_mcolor); // enable VBO vertex attribute ("dgl_Color")
}

void CheckShader(GLuint id, GLuint type, GLint *ret, const char *onfail)
{
//Check if something is wrong with the shader
switch(type) {
case(GL_COMPILE_STATUS):
glGetShaderiv(id, type, ret);
if(*ret == false){
int infologLength = 0;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &amp;infologLength);
GLchar buffer[infologLength];
GLsizei charsWritten = 0;
std::cout << onfail << std::endl;
glGetShaderInfoLog(id, infologLength, &amp;charsWritten, buffer);
std::cout << buffer << std::endl;
}
break;
case(GL_LINK_STATUS):
glGetProgramiv(id, type, ret);
if(*ret == false){
int infologLength = 0;
glGetProgramiv(id, GL_INFO_LOG_LENGTH, &amp;infologLength);
GLchar buffer[infologLength];
GLsizei charsWritten = 0;
std::cout << onfail << std::endl;
glGetProgramInfoLog(id, infologLength, &amp;charsWritten, buffer);
std::cout << buffer << std::endl;
}
default:
break;
};
}

void Draw_vao(size_t index)
{
glBindVertexArray(vao_id[index]); // select the vertex array object:vao_id[index] by definiton using vertices_index,colors_index
glDrawArrays(vao_primitivetype[index], 0, vao_elementcount[index]); // draw the array (at the speed of light)
}

void Draw() // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

glUniformMatrix4fv(glm_ProjectionMatrix_id, 1, false, &amp;glm_ProjectionMatrix.top()[0][0] ); // set the rotation/translation/scale matrix
//glUniformMatrix4fv(glm_ProjectionMatrix_id, 1, false, address(glm_ProjectionMatrix.top()) ); // set the rotation/translation/scale matrix

{
glm_ModelViewMatrix.push(glm_ModelViewMatrix.top() );
//glm_ModelViewMatrix.top() *= translate( vec3(0.5, 0.5, 0.0) );
glm_ModelViewMatrix.top() *= rotate(45.0f, vec3(0.0, 0.0, 1.0) );
glm_ModelViewMatrix.top() *= scale( vec3(0.2, 0.2, 0.2) );

glUniformMatrix4fv(glm_ModelViewMatrix_id, 1, false, &amp;glm_ModelViewMatrix.top()[0][0] ); // set the rotation/translation/scale matrix
//glUniformMatrix4fv(glm_ModelViewMatrix_id, 1, false, address(glm_ModelViewMatrix.top()) ); // set the rotation/translation/scale matrix

Draw_vao(0);

glm_ModelViewMatrix.pop();
}

{
glm_ModelViewMatrix.push(glm_ModelViewMatrix.top() );
glm_ModelViewMatrix.top() *= translate( vec3(0.0, 0.0, 0.25) );
//glm_ModelViewMatrix.top() *= rotate(45.0f, vec3(1.0, 1.0, 0.0) );
glm_ModelViewMatrix.top() *= scale( vec3(0.2, 0.2, 0.2) );

glUniformMatrix4fv(glm_ModelViewMatrix_id, 1, false, &amp;glm_ModelViewMatrix.top()[0][0] ); // set the rotation/translation/scale matrix
//glUniformMatrix4fv(glm_ModelViewMatrix_id, 1, false, address(glm_ModelViewMatrix.top()) ); // set the rotation/translation/scale matrix

Draw_vao(1);

glm_ModelViewMatrix.pop();
}
}

bool Reshape(GLfloat ratio)
{
//glMatrixMode(GL_PROJECTION);
glm_ProjectionMatrix.top() = mat4(1.0); //glLoadIdentity
glm_ProjectionMatrix.top() *= perspective(20.0f,ratio,1.0f,3.0f);
//glLoadMatrixf(address(glm_ProjectionMatrix.top())) ;
glUniformMatrix4fv(glm_ProjectionMatrix_id, 1, false, &amp;glm_ProjectionMatrix.top()[0][0] ); // set the rotation/translation/scale matrix
}

bool SetCamera(GLfloat theta, GLfloat phi)
{
//////////////
// Set the camera view.
static const double radianFactor = acos(0.0) / 90.0;
float r = 1.0f*2.0; // approx. want half way between near + far (see perspective)
float eyeX = r * sin(theta * radianFactor) * cos(phi * radianFactor);
float eyeY = r * sin(theta * radianFactor) * sin(phi * radianFactor);
float eyeZ = r * cos(radianFactor * theta);

float centerX = 0, centerY = 0, centerZ = 0;
float upX = 0, upY = 1.0f, upZ = 0;

//glMatrixMode(GL_MODELVIEW);
glm_ModelViewMatrix.top() = mat4(1.0); // LoadIdentity
glm_ModelViewMatrix.top() *= lookAt( vec3(eyeX, eyeY, eyeZ), vec3(centerX, centerY, centerZ), vec3(upX, upY, upZ));
//glLoadMatrixf(address(glm_ModelViewMatrix.top()));
glUniformMatrix4fv(glm_ModelViewMatrix_id, 1, false, &amp;glm_ModelViewMatrix.top()[0][0] );

return true;
}
};

// GLOBAL ///////////////////////////////////////////////////////////
CustomGraphicsPipeline Scene;
/////////////////////////////////////////////////////////////////////

static void timer(int dt_msec)
{
static GLfloat time_msec = 0.0;
time_msec += dt_msec; // absolute time

Scene.SetCamera(global::theta, global::phi);

glutPostRedisplay();
glutTimerFunc(30,timer,30); // come back in 30msec
}

static void display(void)
{
Scene.Draw();
glutSwapBuffers();
}

static void reshape(int w, int h)
{
// Set the viewport to be the entire window
glViewport(0, 0, w, h);

// Prevent a divide by zero, when window is too short
if(h == 0) h = 1;

global::width = w;
global::height = h;
global::ratio = 1.0 * w / h;

Scene.Reshape(global::ratio);
}

static void keyboard(unsigned char k, int x, int y)
{
switch (k) {
case 't' : global::theta++; if(global::theta > 360) global::theta = 1; break;
case 'p' : global::phi++; if(global::phi > 360) global::phi = 1; break;
case 'T' : global::theta--; if(global::theta < 0) global::theta = 359; break;
case 'P' : global::phi--; if(global::phi < 0) global::phi = 359; break;
case 27 : exit(0); break;
}
}

int main( int argc, char *argv[] )
{
glutInit( &amp;argc, argv );
//opengl 3.0 with freeglut requires to install latest version from svn
//but not necessary to actually get openGL context since code will run anyhow.
//glutInitContextVersion( 3, 0 ); // freeglut is so cool! get openGL 3.0 context
//glutInitContextFlags( int flags )
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(global::width, global::height);
glutCreateWindow("demo opengl 3.0 matrix transformations");

glewInit();

assert( Scene.Init() ); // bail if scene initialization fails

glutTimerFunc(0,timer,0);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);

glutMainLoop();

return 0;
}

Dj3hut1
06-07-2011, 06:39 AM
Hello, is there a similar library for matrix manipulation in C?