diff mbox

[Branch,~glmark2-dev/glmark2/trunk] Rev 1: Initial release of original OpenGL code.

Message ID 20110721123629.17019.49876.launchpad@loganberry.canonical.com
State Accepted
Headers show

Commit Message

Alexandros Frantzis July 21, 2011, 12:36 p.m. UTC
------------------------------------------------------------
revno: 1
committer: Alexandros Frantzis <alf82@freemail.gr>
timestamp: Wed 2010-07-07 13:32:18 +0300
message:
  Initial release of original OpenGL code.
added:
  data/
  data/models/
  data/models/cat.3ds
  data/models/cube.3ds
  data/models/horse.3ds
  data/shaders/
  data/shaders/light-advanced.frag
  data/shaders/light-advanced.vert
  data/shaders/light-basic.frag
  data/shaders/light-basic.vert
  data/textures/
  data/textures/crate-base.bmp
  main.cpp
  makefile
  mesh.cpp
  mesh.h
  model.cpp
  model.h
  oglsdl.h
  readme
  release
  scene.cpp
  scene.h
  scenebuild.cpp
  sceneshading.cpp
  scenetexture.cpp
  screen.cpp
  screen.h
  shader.cpp
  shader.h
  texture.cpp
  texture.h
  vector.cpp
  vector.h


--
lp:glmark2
https://code.launchpad.net/~glmark2-dev/glmark2/trunk

You are subscribed to branch lp:glmark2.
To unsubscribe from this branch go to https://code.launchpad.net/~glmark2-dev/glmark2/trunk/+edit-subscription
diff mbox

Patch

=== added directory 'data'
=== added directory 'data/models'
=== added file 'data/models/cat.3ds'
Binary files data/models/cat.3ds	1970-01-01 00:00:00 +0000 and data/models/cat.3ds	2010-07-07 10:32:18 +0000 differ
=== added file 'data/models/cube.3ds'
Binary files data/models/cube.3ds	1970-01-01 00:00:00 +0000 and data/models/cube.3ds	2010-07-07 10:32:18 +0000 differ
=== added file 'data/models/horse.3ds'
Binary files data/models/horse.3ds	1970-01-01 00:00:00 +0000 and data/models/horse.3ds	2010-07-07 10:32:18 +0000 differ
=== added directory 'data/shaders'
=== added file 'data/shaders/light-advanced.frag'
--- data/shaders/light-advanced.frag	1970-01-01 00:00:00 +0000
+++ data/shaders/light-advanced.frag	2010-07-07 10:32:18 +0000
@@ -0,0 +1,94 @@ 
+// Make sure you remember to add the varying variables:
+// varying vec3 Normal;
+// varying vec3 Light;
+// varying vec3 HalfVector;
+// To the fragment shader so that we can read them in.
+
+// First off here, we have to make sure that our Normal
+// has been normalized so to make sure, we are just going
+// to normalize it with the line:
+// Normal = normalize(Normal);
+
+// Next off we want to calculate our diffuse portion of 
+// the lighting. Now unlike the basic lighting tutorial,
+// I am going to take into account the materials we have
+// attached to the object, and the settings we have applied
+// to our light.
+
+// Now for our diffuse portion of our equation we get the line:
+// float Diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse * max(dot(Normal, Light),0.0);
+// Now the variable gl_FrontMaterial.diffuse is the diffuse
+// material we have assigned to the front face of our object,
+// and to get the diffuse portion of our light, we call the 
+// variable gl_LightSource[0].diffuse. Then to take into account
+// how intense this should be, we multiply it by:
+// max(dot(Normal, Light),0.0)
+// Which from our previous tutorial, we used to calculate how
+// intense the light should be, using the angle of the surface
+// compared to the position of the light.
+
+// Seeing as though we now have the diffuse part of our lighting
+// we now need the Ambient term. In this term there are no real
+// calculations like the dot product, used in the diffuse term.
+// Here we are just taking values set inside our OpenGL program
+// and applying them to our object. The variables that we need
+// to use are:
+// gl_FrontMaterial.ambient
+// gl_LightSource[0].ambient
+// gl_LightModel.ambient
+// For our Ambient term to work, we need to multiply
+// gl_FrontMaterial.ambient and gl_LightSource[0].ambient
+// and then add the product of gl_LightModel.ambient and
+// gl_FrontMaterial.ambient
+// So our equation looks like:
+// float Ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;
+// Ambient += gl_LightModel.ambient * gl_FrontMaterial.ambient;
+
+// In this tutorial, I am not going to cover the emissive term
+// that OpenGL supports (I will in a later tutorial), so I am 
+// going to jump straight to the most complicated term in the
+// lighting equation. Which is the specular term. The reason
+// that this term is the most complicated, is that it needs
+// to find the reflection of the lighting from the surface of
+// the object, to the 'camera'. The first part of the equation
+// is similar to the start of the previous equations and takes
+// the materials specular term, and the lights specular term
+// and multiplies them together to look like:
+// gl_FrontMaterial.specular * gl_LightSource[0].specular
+// and then comes the tricky part, we need to multiply this by
+// pow(max(dot(Normal,HalfVector),0.0), gl_FrontMaterial.shininess);
+// This takes the dot product of our Normal and HalfVector, and as
+// we have seen in the diffuse term, sets a max of 0.0
+// With the number we have just calculated, we need to raise that
+// to the power of our shininess term set inside our OpenGL program.
+
+// Because we are using the halfVector at this stage, we don't need
+// to use the reflect() expression, but we will when we get into
+// normal mapping.
+
+// So in the end our specular expression looks like:
+// float Specular = gl_FrontMaterial.specular * gl_LightSource[0].specular * pow(max(dot(Normal,HalfVector),0.0), gl_FrontMaterial.shininess);
+
+// Now for the combining of all the expressions. We still need to
+// multiply the diffuse term by the objects color. And with that
+// we then need to add the Ambient term and the Specular term.
+// So our final gl_FragColor call looks like:
+// gl_FragColor = Ambient + (Diffuse * vec4(1,0,0,1)) + Specular;
+
+varying vec3 Normal;
+varying vec3 Light;
+varying vec3 HalfVector;
+
+void main(void)
+{	
+	Normal = normalize(Normal);
+
+	float Diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse * max(dot(Normal, Light),0.0);
+
+	float Ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;
+	Ambient += gl_LightModel.ambient * gl_FrontMaterial.ambient;
+
+	float Specular = gl_FrontMaterial.specular * gl_LightSource[0].specular * pow(max(dot(Normal,HalfVector),0.0), gl_FrontMaterial.shininess);
+
+	gl_FragColor = Ambient + (Diffuse * vec4(1,0,0,1)) + Specular;
+}

=== added file 'data/shaders/light-advanced.vert'
--- data/shaders/light-advanced.vert	1970-01-01 00:00:00 +0000
+++ data/shaders/light-advanced.vert	2010-07-07 10:32:18 +0000
@@ -0,0 +1,51 @@ 
+// First off, I am going to explain a little thing
+// with shaders, that will help you to optimize them
+// in the future. Vertex shaders are called for every
+// vertex passed through, and Fragment shaders are
+// called for every pixel on the screen. Because of this
+// it is wise to do as many calculations in the vertex
+// shader as possible, as they are called less, and if
+// the calculation does not need to be called on a per
+// pixel basis, why do it?
+
+// Now as for the tutorial, you will see that I have
+// removed the variable Diffuse from our vertex shader.
+// This is because we are now going to calculate that in
+// the fragment shader so we can get per pixel lighting.
+
+// In our vertex shader, I have added the varying variables:
+// varying vec3 Normal;
+// varying vec3 Light;
+// varying vec3 HalfVector;
+// These hold the surface normal of our vertex, the direction
+// vector of the light source, and the half vector of the
+// light source (you may want to look into the maths behind
+// lighting, I may add something in the maths section at a 
+// later date).
+
+// These variables are going to be calculated here, and passed
+// through to our fragment shader. This is because these variables
+// will not change, so there is no need calculating them on a
+// per pixel basis.
+
+// Now that we have these variables, we need to calculate them.
+// Our Normal and Light variables stay exactly the same
+// as in the previous tutorial. The only new one is the HalfVector
+// which is called similar to our Light variable, just replace
+// position with halfVector, and we get the light sources half
+// vector supplied by OpenGL.
+
+varying vec3 Normal;
+varying vec3 Light;
+varying vec3 HalfVector;
+
+void main(void)
+{			
+	Normal = normalize(gl_NormalMatrix * gl_Normal);
+
+	Light = normalize(gl_LightSource[0].position.xyz);
+
+	HalfVector = normalize(gl_LightSource[0].halfVector.xyz);
+
+	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+}
\ No newline at end of file

=== added file 'data/shaders/light-basic.frag'
--- data/shaders/light-basic.frag	1970-01-01 00:00:00 +0000
+++ data/shaders/light-basic.frag	2010-07-07 10:32:18 +0000
@@ -0,0 +1,24 @@ 
+// Because we are using the varying float Diffuse in
+// our vertex shader, if we wish to read it in here, we
+// need to set the same variable, so I have done this 
+// first.
+
+// After that, I am simply changing the line:
+// gl_FragColor = vec4(0,0,1,1) 
+// to
+// gl_FragColor = Diffuse * vec4(0,0,1,1);
+// This multiplies the intensity of the light by the
+// color we originally set the cube to.
+
+// This can or cannot eliminate the need for materials,
+// depending on your needs, but just for the record 
+// (and future tutorials), materials are worth while
+// and can be read from inside GLSL :)
+
+varying float Diffuse;
+
+void main(void)
+{	
+//Multiply the light Diffuse intensity by the color of the cube 
+	gl_FragColor = Diffuse * vec4(0,0,1,1);
+}

=== added file 'data/shaders/light-basic.vert'
--- data/shaders/light-basic.vert	1970-01-01 00:00:00 +0000
+++ data/shaders/light-basic.vert	2010-07-07 10:32:18 +0000
@@ -0,0 +1,72 @@ 
+// For this tutorial, I am going show you how to perform per
+// vertex lighting using shaders. Yes, shaders support per pixel
+// but this is just a starting point.
+
+// First I am going to teach you about varying variables. These
+// are variables that can be shared between the vertex and fragment
+// shaders. These variables are set inside the vertex shader, and 
+// then read from the fragment shader. In this case we are going
+// to share a float type variable from the Vertex shader to the 
+// Fragment shader. This variable is going to be called Diffuse
+// and will hold a number that will tell us how lit our vertex 
+// should be.
+
+// Because we are using per vertex lighting, the GLSL shader will
+// automatically interpolate the color between the vertices. Just
+// like OpenGL does.
+
+// Now first off we need to know the surface normal of the current
+// vertex. Because I am using a GLUT cube, these are already 
+// calculated and sent off with the glNormal command. Any numbers
+// sent from OpenGL through glNormal(1,2,3); can be read with
+// the variable gl_Normal. In later tutorials, I will be using
+// self calculated normals, using my own normal generation code.
+
+// Now as for our normal, I am storing it in the variable vec3 Normal.
+// But first, I have to multiply the surface normal (gl_Normal) by
+// the gl_NormalMatrix. This places the normal in coordinates that
+// we can use. (Later on I will show you how to use tangent space
+// normals). We also then have to normalize this multiplication so
+// that all of the normal vectors are between (and including) -1 and 1.
+// This makes sure that we have no scaling errors.
+
+// Next on, we are going to work with our light. I am storing this
+// in a variable called vec3 Light. In this, I am calling for the
+// position of glLight0. This is gathered by the call:
+// gl_LightSource[0].position.xyz
+// This gives us the position of glLight0, and to get the position of
+// any other light, we just change the number 0 to the light number we
+// are after. We do not need to multiply this expression by the 
+// gl_NormalMatrix, but we do have to normalize it still.
+
+// Now that we have our surface Normal and the position of our Light.
+// We can now calculate the Diffuse value of our lighting at the 
+// given vertex. To do this we need to take the dot product of both
+// the Normal and the Light together. If you have any idea on
+// calculating Normals, then you should have a fair idea of what the
+// dot product does. It works as such:
+// dot(a,b) = (x1 * x2) + (y1 * y2) + (z1 * z3)
+// If this happens to be equal to 0, then the vectors a and b are 
+// perpendicular (the light meets the surface at a 90 degree angle).
+// Because this point is when the light is at its brightest, we need
+// to set the maximum value for our diffuse value to 0.0.
+// So our Diffuse equation becomes:
+// Diffuse = max(dot(Normal, Light),0.0);
+
+// And from that, we have now calculated the intensity of the light
+// at the given vertex. That started to turn into a bit of a maths
+// lesson, but it even cleared up some stuff for me without even
+// thinking about it. GO MATHS :)
+
+varying float Diffuse;
+
+void main(void)
+{			
+	Normal = normalize(gl_NormalMatrix * gl_Normal);
+
+	Light = normalize(gl_LightSource[0].position.xyz);
+
+	Diffuse = max(dot(Normal, Light),0.0);
+
+	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+}
\ No newline at end of file

=== added directory 'data/textures'
=== added file 'data/textures/crate-base.bmp'
Binary files data/textures/crate-base.bmp	1970-01-01 00:00:00 +0000 and data/textures/crate-base.bmp	2010-07-07 10:32:18 +0000 differ
=== added file 'main.cpp'
--- main.cpp	1970-01-01 00:00:00 +0000
+++ main.cpp	2010-07-07 10:32:18 +0000
@@ -0,0 +1,106 @@ 
+#include "oglsdl.h"
+
+#include "screen.h"
+#include "scene.h"
+
+int main(int argc, char *argv[])
+{
+    SDL_Event event;
+    int running = 1;
+    unsigned current_scene = 0;
+    Screen screen;
+   
+    SceneBuild scenebuild;
+    SceneTexture scenetexture;
+    SceneShading sceneshading;
+ 
+    printf("===================================================\n");
+    printf("    GLMark 08\n");
+    printf("===================================================\n");
+    
+    printf("Enter screen width:  ");
+    scanf("%d", &screen.mWidth);
+    printf("Enter screen height: ");
+    scanf("%d", &screen.mHeight);
+    printf("Enter screen bpp:    ");
+    scanf("%d", &screen.mBpp);
+    printf("Enter '1' for fullscreen '0' for windowed: ");
+    scanf("%d", &screen.mFullScreen);
+    
+
+    printf("===================================================\n");
+    if(!screen.init())
+        return 0;
+    printf("===================================================\n");
+
+    if(!scenebuild.load() || !scenetexture.load() || !sceneshading.load())
+        return 0;
+
+    while(running)
+    {
+        while(SDL_PollEvent(&event))
+        {
+            switch(event.type)
+            {
+            case SDL_QUIT:
+                running = 0;
+                break;
+            case SDL_KEYDOWN:
+                if(event.key.keysym.sym == SDLK_ESCAPE)
+                    running = 0;
+                break;
+            }
+        }
+
+        screen.clear();
+
+        switch(current_scene)
+        {
+        case 0:
+            current_scene++;
+            scenebuild.start();
+//            scenebuild.mRunning = false;
+            break;
+        case 1:
+            scenebuild.update();
+            scenebuild.draw();
+            if(!scenebuild.mRunning)
+            {
+                current_scene++;
+                scenetexture.start();
+//                scenetexture.mRunning = false;
+            }
+            break;
+        case 2:
+            scenetexture.update();
+            scenetexture.draw();
+            if(!scenetexture.mRunning)
+            {
+                current_scene++;
+                sceneshading.start();
+//                sceneshading.mRunning = false;
+            }
+            break;
+        case 3:
+            sceneshading.update();
+            sceneshading.draw();
+            if(!sceneshading.mRunning)
+                running = false;
+            break;
+        }
+        
+        screen.update();
+    }
+    
+    scenebuild.calculate_score();
+    scenetexture.calculate_score();
+    sceneshading.calculate_score();
+    
+    unsigned score = scenebuild.mScore + scenetexture.mScore + sceneshading.mScore;
+
+    printf("===================================================\n");
+    printf("Your GLMark08 Score is %u  ^_^\n", score);
+    printf("===================================================\n");
+
+    return 0;
+}

=== added file 'makefile'
--- makefile	1970-01-01 00:00:00 +0000
+++ makefile	2010-07-07 10:32:18 +0000
@@ -0,0 +1,2 @@ 
+all:
+	g++ *.cpp -o glmark -Wall -lSDL -lGL -lGLU -lGLEW

=== added file 'mesh.cpp'
--- mesh.cpp	1970-01-01 00:00:00 +0000
+++ mesh.cpp	2010-07-07 10:32:18 +0000
@@ -0,0 +1,240 @@ 
+#include "mesh.h"
+
+Texel::Texel()
+{
+    u = 0;  v = 0;
+}
+
+Texel::Texel(GLfloat pU, GLfloat pV)
+{
+    u = pU; v = pV;
+}
+    
+Mesh::Mesh()
+{
+    mPolygonQty = 0;
+    mVertexQty = 0;
+    mMode = GL_QUADS;
+    mVertex = 0;
+}
+
+Mesh::~Mesh()
+{
+    delete [] mVertex;
+    glDeleteLists(1, mBuildList);
+    //deleteArray
+}
+
+void Mesh::make_cube()
+{
+    mPolygonQty = 6;
+    mVertexQty = 4 * mPolygonQty;
+    mMode = GL_QUADS;
+    mVertex = new Vertex[mVertexQty];
+    
+    mVertex[0].v = Vector3f( 1.0f, 1.0f,-1.0f);
+    mVertex[1].v = Vector3f(-1.0f, 1.0f,-1.0f);
+    mVertex[2].v = Vector3f(-1.0f, 1.0f, 1.0f);
+    mVertex[3].v = Vector3f( 1.0f, 1.0f, 1.0f);
+
+    mVertex[4].v = Vector3f( 1.0f,-1.0f, 1.0f);
+    mVertex[5].v = Vector3f(-1.0f,-1.0f, 1.0f);
+    mVertex[6].v = Vector3f(-1.0f,-1.0f,-1.0f);
+    mVertex[7].v = Vector3f( 1.0f,-1.0f,-1.0f);
+    
+    mVertex[8].v =  Vector3f( 1.0f, 1.0f, 1.0f);
+    mVertex[9].v =  Vector3f(-1.0f, 1.0f, 1.0f);
+    mVertex[10].v = Vector3f(-1.0f,-1.0f, 1.0f);
+    mVertex[11].v = Vector3f( 1.0f,-1.0f, 1.0f);
+
+    mVertex[12].v = Vector3f( 1.0f,-1.0f,-1.0f);
+    mVertex[13].v = Vector3f(-1.0f,-1.0f,-1.0f);
+    mVertex[14].v = Vector3f(-1.0f, 1.0f,-1.0f);
+    mVertex[15].v = Vector3f( 1.0f, 1.0f,-1.0f);
+
+    mVertex[16].v = Vector3f(-1.0f, 1.0f, 1.0f);
+    mVertex[17].v = Vector3f(-1.0f, 1.0f,-1.0f);
+    mVertex[18].v = Vector3f(-1.0f,-1.0f,-1.0f);
+    mVertex[19].v = Vector3f(-1.0f,-1.0f, 1.0f);
+
+    mVertex[20].v = Vector3f(-1.0f, 1.0f, 1.0f);
+    mVertex[21].v = Vector3f(-1.0f, 1.0f,-1.0f);
+    mVertex[22].v = Vector3f(-1.0f,-1.0f,-1.0f);
+    mVertex[23].v = Vector3f(-1.0f,-1.0f, 1.0f);
+
+    for(unsigned i = 0; i < mVertexQty / 4; i += 4)
+    {
+        Vector3f n;
+        n = normal(mVertex[i].v, mVertex[i + 1].v, mVertex[i + 2].v);
+        for(unsigned j = 0; j < 4; j++)
+            mVertex[i + j].n = n;
+        mVertex[i + 0].t = Texel(0.0f, 0.0f);
+        mVertex[i + 1].t = Texel(1.0f, 0.0f);
+        mVertex[i + 2].t = Texel(1.0f, 1.0f);
+        mVertex[i + 3].t = Texel(0.0f, 1.0f);
+    }
+}
+
+void Mesh::make_torus()
+{
+    unsigned wraps_qty = 64;
+    unsigned per_wrap_qty = 64;
+    float major_radius = 0.8;
+    float minor_radius = 0.4;
+    unsigned i, j;
+    unsigned k = 0;
+    
+    Vector3f a, b, c, d, n;
+
+    mMode = GL_TRIANGLES;
+    mVertexQty = wraps_qty * per_wrap_qty * 6;
+    mVertex = new Vertex[mVertexQty];
+    
+    for(i = 0; i < wraps_qty; i++)
+        for(j = 0; j < per_wrap_qty; j++)
+        {
+            float wrap_frac = j / (float)per_wrap_qty;
+            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;
+            
+            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;
+
+            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;
+
+            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;
+
+            n = normal(a, b, c);
+            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);
+            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()
+{
+    glBegin(mMode);
+    glColor3f(1.0f, 0.0f, 0.0f);
+    for(unsigned i = 0; i < mVertexQty; i++)
+    {
+        glNormal3f(mVertex[i].n.x, mVertex[i].n.y, mVertex[i].n.z);
+        glTexCoord2f(mVertex[i].t.u, mVertex[i].t.v);
+        glVertex3f(mVertex[i].v.x, mVertex[i].v.y, mVertex[i].v.z);
+    }
+    glEnd();
+}
+
+void Mesh::render_array()
+{
+    glEnableClientState(GL_VERTEX_ARRAY);
+    glEnableClientState(GL_NORMAL_ARRAY);
+
+    glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &mVertex[0].v.x);
+    glNormalPointer(GL_FLOAT, sizeof(Vertex), &mVertex[0].n.x);
+    glDrawArrays(mMode, 0, mVertexQty);
+
+    glDisableClientState(GL_VERTEX_ARRAY);
+    glDisableClientState(GL_NORMAL_ARRAY);
+}
+
+void Mesh::build_list()
+{
+#ifdef _DEBUG
+    printf("Building list for mesh...        ");
+#endif
+
+    mBuildList = glGenLists(1);
+    glNewList(mBuildList, GL_COMPILE);
+    render();
+    glEndList();
+
+#ifdef _DEBUG
+    printf("[ Done ]\n");
+#endif
+}
+
+void Mesh::build_vbo()
+{
+#ifdef _DEBUG
+    printf("Building vbo for mesh...         ");
+#endif
+
+    Vector3f *vertex;
+    Texel *texel;
+    Vector3f *normal;
+    
+    vertex = new Vector3f[mVertexQty];
+    texel = new Texel[mVertexQty];
+    normal = new Vector3f[mVertexQty];
+    
+    for(unsigned i = 0; i < mVertexQty; i++)
+    {
+        vertex[i] = mVertex[i].v;
+        texel[i] = mVertex[i].t;
+        normal[i] = mVertex[i].n;
+    }
+
+	// Generate And Bind The Vertex Buffer
+	glGenBuffersARB(1, &mVBOVertices);                          // Get A Valid Name
+	glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVBOVertices);         // Bind The Buffer
+	// Load The Data
+	glBufferDataARB(GL_ARRAY_BUFFER_ARB, mVertexQty * sizeof(Vector3f), vertex, GL_STATIC_DRAW_ARB);
+
+	// Generate And Bind The normal Buffer
+	glGenBuffersARB(1, &mVBONormals);                          // Get A Valid Name
+	glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVBONormals);         // Bind The Buffer
+	// Load The Data
+	glBufferDataARB(GL_ARRAY_BUFFER_ARB, mVertexQty * sizeof(Vector3f), normal, GL_STATIC_DRAW_ARB);
+
+	// Generate And Bind The Texture Coordinate Buffer
+	glGenBuffersARB(1, &mVBOTexCoords);                       // Get A Valid Name
+	glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVBOTexCoords);      // Bind The Buffer
+	// Load The Data
+	glBufferDataARB(GL_ARRAY_BUFFER_ARB, mVertexQty * sizeof(Texel), texel, GL_STATIC_DRAW_ARB);
+
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    
+    delete [] vertex;
+    delete [] texel;
+    delete [] normal;
+#ifdef _DEBUG
+    printf("[ Done ]\n");
+#endif
+}
+
+void Mesh::render_vbo()
+{
+    glEnableClientState(GL_VERTEX_ARRAY);
+    glEnableClientState(GL_NORMAL_ARRAY);
+
+    glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVBONormals);
+    glNormalPointer(GL_FLOAT, 0, 0);
+    glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVBOVertices);
+    glVertexPointer(3, GL_FLOAT, 0, 0);
+
+    glDrawArrays(GL_TRIANGLES, 0, mVertexQty);
+
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+    glDisableClientState(GL_NORMAL_ARRAY);
+    glDisableClientState(GL_VERTEX_ARRAY); 
+}

=== added file 'mesh.h'
--- mesh.h	1970-01-01 00:00:00 +0000
+++ mesh.h	2010-07-07 10:32:18 +0000
@@ -0,0 +1,55 @@ 
+#ifndef _MESH_H
+#define _MESH_H
+
+#include "screen.h"
+#include "vector.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;
+};
+
+// Data for a mesh to be rendered by vertex arrays' or vbos' has 3 verticies per
+// polygon and no polygonal data
+class Mesh
+{
+public:
+    unsigned mVertexQty;         // Quantity of Verticies
+    unsigned mPolygonQty;        // Quantity of polygons, not really needed
+    GLenum mMode;           // Polygon mode, eg GL_QUADS, GL_TRIANGLES etc...
+    Vertex *mVertex;        // Storage for the verticies
+
+    GLuint mBuildList;      // Build list name
+
+	GLuint mVBOVertices;    // Vertex VBO name
+	GLuint mVBONormals;     // Texture coordinate VBO name
+	GLuint mVBOTexCoords;   // Texture coordinate VBO name
+    
+    Mesh();                 // Default Constructor, should set pointers to null
+    ~Mesh();
+    
+    void make_cube();
+    void make_torus();
+    void render();
+    void render_array();
+    void build_list();
+    void build_vbo();
+    void render_vbo();
+};
+
+#endif

=== added file 'model.cpp'
--- model.cpp	1970-01-01 00:00:00 +0000
+++ model.cpp	2010-07-07 10:32:18 +0000
@@ -0,0 +1,254 @@ 
+#include "model.h"
+
+long filelength(int f)
+{
+    struct stat buf;
+    fstat(f, &buf);
+    return(buf.st_size);
+}
+
+Model::Model()
+{
+    mPolygonQty = 0;
+    mVertexQty = 0;
+    mVertex = 0;        // Set pointer to null
+    mPolygon = 0;       // Set pointer to null
+}
+
+Model::~Model()
+{
+    delete [] mVertex;
+    delete [] mPolygon;
+}
+
+void Model::convert_to_mesh(Mesh *pMesh)
+{
+#ifdef _DEBUG
+    printf("Converting model to mesh...      ");
+#endif
+    pMesh->mVertexQty = 3 * mPolygonQty;
+    pMesh->mPolygonQty = mPolygonQty;
+    pMesh->mMode = GL_TRIANGLES;
+    
+    pMesh->mVertex = new Vertex[pMesh->mVertexQty];
+    
+    for(unsigned i = 0; i < pMesh->mVertexQty; i += 3)
+    {
+        pMesh->mVertex[i + 0].v = mVertex[mPolygon[i / 3].mA].v;
+        pMesh->mVertex[i + 1].v = mVertex[mPolygon[i / 3].mB].v;
+        pMesh->mVertex[i + 2].v = mVertex[mPolygon[i / 3].mC].v;
+        
+        pMesh->mVertex[i + 0].n = mVertex[mPolygon[i / 3].mA].n;
+        pMesh->mVertex[i + 1].n = mVertex[mPolygon[i / 3].mB].n;
+        pMesh->mVertex[i + 2].n = mVertex[mPolygon[i / 3].mC].n;
+
+        pMesh->mVertex[i + 0].t = mVertex[mPolygon[i / 3].mA].t;
+        pMesh->mVertex[i + 1].t = mVertex[mPolygon[i / 3].mB].t;
+        pMesh->mVertex[i + 2].t = mVertex[mPolygon[i / 3].mC].t;
+    }
+    
+#ifdef _DEBUG
+    printf("[ Done ]\n");
+#endif
+}
+
+void Model::calculate_normals()
+{
+#ifdef _DEBUG
+    printf("Calculating normals for model... ");
+#endif
+    Vector3f 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);
+        mVertex[mPolygon[i].mA].n += n;
+        mVertex[mPolygon[i].mB].n += n;
+        mVertex[mPolygon[i].mC].n += n;
+    }
+
+    for(unsigned i = 0; i < mVertexQty; i++)
+        mVertex[i].n.normalize();
+
+#ifdef _DEBUG
+    printf("[ Done ]\n");
+#endif
+}
+
+void Model::center()
+{
+    Vector3f center;
+    Vector3f max = mVertex[0].v, 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 < 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;
+
+    for(unsigned i = 0; i < mVertexQty; i++)
+        mVertex[i].v -= center;
+}
+
+void Model::scale(GLfloat pAmount)
+{
+    for(unsigned i = 1; i < mVertexQty; i++)
+        mVertex[i].v *= pAmount;
+}
+
+int Model::load_3ds(const char *pFileName)
+{
+#ifdef _DEBUG
+    printf("Loading model from 3ds file...   ");
+#endif
+   	int i; //Index variable
+	
+	FILE *l_file; //File pointer
+	
+	unsigned short l_chunk_id; //Chunk identifier
+	unsigned int l_chunk_lenght; //Chunk lenght
+
+	unsigned char l_char; //Char variable
+	unsigned short l_qty; //Number of elements in each chunk
+
+	if ((l_file=fopen (pFileName, "rb"))== NULL)
+	{
+#ifdef _DEBUG
+	    printf("[ Fail ]\n");
+#else
+        printf("Could not open 3ds file\n");
+#endif
+	    return 0;
+	}
+
+	while (ftell (l_file) < filelength (fileno (l_file))) //Loop to scan the whole file
+	//while(!EOF)
+	{
+		//getch(); //Insert this command for debug (to wait for keypress for each chuck reading)
+
+		fread (&l_chunk_id, 2, 1, l_file); //Read the chunk header
+		fread (&l_chunk_lenght, 4, 1, l_file); //Read the lenght of the chunk
+
+		switch (l_chunk_id)
+        {
+			//----------------- MAIN3DS -----------------
+			// Description: Main chunk, contains all the other chunks
+			// Chunk ID: 4d4d 
+			// Chunk Lenght: 0 + sub chunks
+			//-------------------------------------------
+			case 0x4d4d: 
+			break;    
+
+			//----------------- EDIT3DS -----------------
+			// Description: 3D Editor chunk, objects layout info 
+			// Chunk ID: 3d3d (hex)
+			// Chunk Lenght: 0 + sub chunks
+			//-------------------------------------------
+			case 0x3d3d:
+			break;
+			
+			//--------------- EDIT_OBJECT ---------------
+			// Description: Object block, info for each object
+			// Chunk ID: 4000 (hex)
+			// Chunk Lenght: len(object name) + sub chunks
+			//-------------------------------------------
+			case 0x4000: 
+				i=0;
+				do
+				{
+					fread (&l_char, 1, 1, l_file);
+                    mName[i] = l_char;
+					i++;
+                } while(l_char != '\0' && i<20);
+			break;
+
+			//--------------- OBJ_TRIMESH ---------------
+			// Description: Triangular mesh, contains chunks for 3d mesh info
+			// Chunk ID: 4100 (hex)
+			// Chunk Lenght: 0 + sub chunks
+			//-------------------------------------------
+			case 0x4100:
+			break;
+			
+			//--------------- TRI_VERTEXL ---------------
+			// Description: Vertices list
+			// Chunk ID: 4110 (hex)
+			// Chunk Lenght: 1 x unsigned short (number of vertices) 
+			//             + 3 x float (vertex coordinates) x (number of vertices)
+			//             + sub chunks
+			//-------------------------------------------
+			case 0x4110: 
+				fread (&l_qty, sizeof (unsigned short), 1, l_file);
+                mVertexQty = l_qty;
+                mVertex = new Vertex[mVertexQty];
+                for (i=0; i<l_qty; i++)
+                {
+					fread (&mVertex[i].v.x, sizeof(float), 1, l_file);
+                    fread (&mVertex[i].v.y, sizeof(float), 1, l_file);
+					fread (&mVertex[i].v.z, sizeof(float), 1, l_file);
+				}
+				break;
+
+			//--------------- TRI_FACEL1 ----------------
+			// Description: Polygons (faces) list
+			// Chunk ID: 4120 (hex)
+			// Chunk Lenght: 1 x unsigned short (number of polygons) 
+			//             + 3 x unsigned short (polygon points) x (number of polygons)
+			//             + sub chunks
+			//-------------------------------------------
+			case 0x4120:
+				fread (&l_qty, sizeof (unsigned short), 1, l_file);
+                mPolygonQty = l_qty;
+                mPolygon = new Polygon[mPolygonQty];
+                for (i=0; i<l_qty; i++)
+                {
+					fread (&mPolygon[i].mA, sizeof (unsigned short), 1, l_file);
+					fread (&mPolygon[i].mB, sizeof (unsigned short), 1, l_file);
+					fread (&mPolygon[i].mC, sizeof (unsigned short), 1, l_file);
+					fread (&mPolygon[i].mFaceFlags, sizeof (unsigned short), 1, l_file);
+				}
+                break;
+
+			//------------- TRI_MAPPINGCOORS ------------
+			// Description: Vertices list
+			// Chunk ID: 4140 (hex)
+			// Chunk Lenght: 1 x unsigned short (number of mapping points) 
+			//             + 2 x float (mapping coordinates) x (number of mapping points)
+			//             + sub chunks
+			//-------------------------------------------
+			case 0x4140:
+				fread (&l_qty, sizeof (unsigned short), 1, l_file);
+				for (i=0; i<l_qty; i++)
+				{
+					fread (&mVertex[i].t.u, sizeof (float), 1, l_file);
+                    fread (&mVertex[i].t.v, sizeof (float), 1, l_file);
+				}
+                break;
+
+			//----------- Skip unknow chunks ------------
+			//We need to skip all the chunks that currently we don't use
+			//We use the chunk lenght information to set the file pointer
+			//to the same level next chunk
+			//-------------------------------------------
+			default:
+				 fseek(l_file, l_chunk_lenght-6, SEEK_CUR);
+        } 
+	}
+	fclose(l_file); // Closes the file stream
+
+#ifdef _DEBUG
+    printf("[ Success ]\n");
+	printf("    Model Information\n");
+	printf("    Name:          %s\n", mName);
+	printf("    Vertex count:  %d\n", mVertexQty);
+	printf("    Polygon count: %d\n", mPolygonQty);
+#endif 
+    return 1;
+}

=== added file 'model.h'
--- model.h	1970-01-01 00:00:00 +0000
+++ model.h	2010-07-07 10:32:18 +0000
@@ -0,0 +1,37 @@ 
+#ifndef _MODEL_H
+#define _MODEL_H
+
+#include "mesh.h"
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+class Polygon
+{
+public:
+    unsigned short mA, mB, mC;
+    unsigned short mFaceFlags;
+};
+
+// A model as loaded from a 3ds file
+class Model
+{
+public:
+    unsigned mPolygonQty;
+    unsigned mVertexQty;
+    Vertex *mVertex;
+    Polygon *mPolygon;
+    char mName[20];
+
+    Model();
+    ~Model();
+
+    int load_3ds(const char *pFileName);
+    void calculate_normals();
+    void center();
+    void scale(GLfloat pAmount);
+    void convert_to_mesh(Mesh *pMesh);
+};
+
+#endif

=== added file 'oglsdl.h'
--- oglsdl.h	1970-01-01 00:00:00 +0000
+++ oglsdl.h	2010-07-07 10:32:18 +0000
@@ -0,0 +1,7 @@ 
+#ifndef _OGLSDL_H
+#define _OGLSDL_H
+
+#include <SDL/SDL.h>
+#include <GL/glew.h>
+
+#endif

=== added file 'readme'
--- readme	1970-01-01 00:00:00 +0000
+++ readme	2010-07-07 10:32:18 +0000
@@ -0,0 +1,11 @@ 
+requires development libarays
+	sdl		libsdl1.2-dev
+	gl      libgl1-mesa-dev
+	glu     libglu1-mesa-dev
+    glew    libglew1.5-dev
+
+compile with
+	make
+
+execute with
+	./glmark

=== added file 'release'
--- release	1970-01-01 00:00:00 +0000
+++ release	2010-07-07 10:32:18 +0000
@@ -0,0 +1,51 @@ 
+GLMark 0.5.2
+========================
+- current tests
+    no precompilation
+    build lists
+    vertex arrays
+    vertex buffer objects
+    nearest texture filtering
+    linear texture filtering
+    mipmapped texture filtering
+    smooth shader model
+    glsl per vertex lighting
+    glsl per pixel lighting
+    
+Updates 26-04-2008
+========================
+- Added GLSL shader tests
+- Fixed some memory leaks
+- Cleaned up the code a bit
+
+Updates 25-04-2008
+========================
+- Readded the texture filter test
+- Improved score system
+
+Updates 24-04-2008
+========================
+- Completly rewritten source
+- Now c++
+- 3dsloader
+- vertex buffer objects
+- havent done texture tests yet
+- select any resolution, fullscreen or windowed
+
+Updates 20-04-2008
+========================
+- Selected color depth used instead of desktop depth
+- Simple makefile included
+- Torus model, which actually tests the different methods of precompilation
+
+Updates 19-04-2008
+========================
+- Tests now run for 30 seconds
+- The score is calculated properly, thanks to Shuffle777.
+- It is now possible to select resolution, color depth and fullscreen/windowed.
+
+Updates
+========================
+- Tests now run for 60 seconds
+- A score is calculated at the end of the benchmark, based on my computer
+(I get exactly 5000) :).

=== added file 'scene.cpp'
--- scene.cpp	1970-01-01 00:00:00 +0000
+++ scene.cpp	2010-07-07 10:32:18 +0000
@@ -0,0 +1,21 @@ 
+#include "scene.h"
+
+Scene::Scene()
+{
+}
+
+Scene::~Scene()
+{
+    delete [] mPartDuration;
+    delete [] mAverageFPS;
+    delete [] mScoreScale;
+}
+
+void Scene::calculate_score()
+{
+    mScore = 0;
+    for(unsigned i = 0; i < mPartsQty; i++)
+        mScore += mAverageFPS[i] * mScoreScale[i];
+}
+
+

=== added file 'scene.h'
--- scene.h	1970-01-01 00:00:00 +0000
+++ scene.h	2010-07-07 10:32:18 +0000
@@ -0,0 +1,84 @@ 
+#ifndef _SCENE_H
+#define _SCENE_H
+
+#include "oglsdl.h"
+
+#include "mesh.h"
+#include "model.h"
+#include "texture.h"
+#include "shader.h"
+
+#include <math.h>
+
+class Scene
+{
+public:
+    Scene();
+    ~Scene();
+    
+    unsigned mPartsQty;         // How many parts for the scene
+    unsigned mCurrentPart;      // The current part being rendered
+    double *mPartDuration;      // Duration per part in seconds
+
+    double mLastTime, mCurrentTime, mDt;
+    unsigned mCurrentFrame;
+    bool mRunning;
+    
+    unsigned *mAverageFPS;      // Average FPS per part
+    float *mScoreScale;
+    unsigned mScore;            // Score
+    
+    void calculate_score();
+    
+protected:
+    double mStartTime;
+    double mElapsedTime;
+};
+
+class SceneBuild : public Scene
+{
+public:
+    int load();
+    void start();
+    void update();
+    void draw();
+    
+    Mesh mMesh;
+    float mRotation;
+    float mRotationSpeed;
+};
+
+class SceneTexture : public Scene
+{
+public:
+    int load();
+    void start();
+    void update();
+    void draw();
+    
+    ~SceneTexture();
+    
+    Mesh mCubeMesh;
+    GLuint mTexture[3];
+    Vector3f mRotation;
+    Vector3f mRotationSpeed;
+};
+
+class SceneShading : public Scene
+{
+public:
+    int load();
+    void start();
+    void update();
+    void draw();
+    
+    ~SceneShading();
+    
+    Shader mShader[2];
+
+    Mesh mMesh;
+    float mRotation;
+    float mRotationSpeed;
+};
+
+#endif

=== added file 'scenebuild.cpp'
--- scenebuild.cpp	1970-01-01 00:00:00 +0000
+++ scenebuild.cpp	2010-07-07 10:32:18 +0000
@@ -0,0 +1,120 @@ 
+#include "scene.h"
+
+int SceneBuild::load()
+{
+    Model model;
+    
+    if(!model.load_3ds("data/models/horse.3ds"))
+        return 0;
+        
+    model.calculate_normals();
+    model.convert_to_mesh(&mMesh);
+    
+    mMesh.build_list();
+    mMesh.build_vbo();
+
+    mRotationSpeed = 36.0f;
+    
+    mRunning = false;
+    
+    mPartsQty = 4;
+    mPartDuration = new double[mPartsQty];
+    mAverageFPS = new unsigned[mPartsQty];
+    mScoreScale = new float[mPartsQty];
+
+    mScoreScale[0] = 1.898f;
+    mScoreScale[1] = 0.540f;
+    mScoreScale[2] = 0.488f;
+    mScoreScale[3] = 0.420f;
+
+    mScore = 0;
+    
+    mPartDuration[0] = 10.0;
+    mPartDuration[1] = 10.0;
+    mPartDuration[2] = 10.0;
+    mPartDuration[3] = 10.0;
+    
+    mCurrentPart = 0;
+    
+    return 1;
+}
+
+void SceneBuild::start()
+{
+    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};
+
+    glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
+    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
+    glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
+    glEnable(GL_LIGHT0);
+    glEnable(GL_LIGHTING);
+
+    mCurrentFrame = 0;
+    mRunning = true;
+    mStartTime = SDL_GetTicks() / 1000.0;
+    mLastTime = mStartTime;
+}
+
+void SceneBuild::update()
+{
+    mCurrentTime = SDL_GetTicks() / 1000.0;
+    mDt = mCurrentTime - mLastTime;
+    mLastTime = mCurrentTime;
+    
+    mElapsedTime = mCurrentTime - mStartTime;
+    
+    if(mElapsedTime >= mPartDuration[mCurrentPart])
+    {
+        mAverageFPS[mCurrentPart] = mCurrentFrame / mElapsedTime;
+        
+        switch(mCurrentPart)
+        {
+        case 0:
+            printf("Precompilation\n");
+            printf("    No Precompilation             FPS: %u\n", mAverageFPS[mCurrentPart]);
+            break;
+        case 1:
+            printf("    Build list                    FPS: %u\n", mAverageFPS[mCurrentPart]);
+            break;
+        case 2:
+            printf("    Vertex array                  FPS: %u\n", mAverageFPS[mCurrentPart]);
+            break;
+        case 3:
+            printf("    Vertex buffer object          FPS: %u\n", mAverageFPS[mCurrentPart]);
+            break;
+        }
+        mScore += mAverageFPS[mCurrentPart];
+        mCurrentPart++;
+        start();
+        if(mCurrentPart >= mPartsQty)
+            mRunning = false;
+    }
+    
+    mRotation += mRotationSpeed * mDt;
+    
+    mCurrentFrame++;
+}
+
+void SceneBuild::draw()
+{
+    glTranslatef(0.0f, 0.0f,-2.5f);
+    glRotated(mRotation, 0.0f, 1.0, 0.0f);
+
+    glColor3f(0.0f, 1.0f, 1.0f);
+    switch(mCurrentPart)
+    {
+    case 0:
+        mMesh.render();
+        break;
+    case 1:
+        glCallList(mMesh.mBuildList);
+    case 2:
+        mMesh.render_array();
+        break;
+    case 3:
+        mMesh.render_vbo();
+        break;
+    }    
+}

=== added file 'sceneshading.cpp'
--- sceneshading.cpp	1970-01-01 00:00:00 +0000
+++ sceneshading.cpp	2010-07-07 10:32:18 +0000
@@ -0,0 +1,140 @@ 
+#include "scene.h"
+
+SceneShading::~SceneShading()
+{
+}
+
+int SceneShading::load()
+{
+    Model model;
+    
+    if(!model.load_3ds("data/models/cat.3ds"))
+        return 0;
+        
+    model.calculate_normals();
+    model.convert_to_mesh(&mMesh);
+    
+    mMesh.build_vbo();
+    
+    mShader[0].load("data/shaders/light-basic.vert", "data/shaders/light-basic.frag");
+    mShader[1].load("data/shaders/light-advanced.vert", "data/shaders/light-advanced.frag");
+
+    mRotationSpeed = 36.0f;
+    mRotation = 0.0f;
+    
+    mRunning = false;
+    
+    mPartsQty = 3;
+    mPartDuration = new double[mPartsQty];
+    mAverageFPS = new unsigned[mPartsQty];
+    mScoreScale = new float[mPartsQty];
+
+    mScoreScale[0] = 0.534f;
+    mScoreScale[1] = 0.532f;
+    mScoreScale[2] = 0.556f;
+    
+    mScore = 0;
+    
+    mPartDuration[0] = 10.0;
+    mPartDuration[1] = 10.0;
+    mPartDuration[2] = 10.0;
+    
+    mCurrentPart = 0;
+    
+    return 1;
+}
+
+void SceneShading::start()
+{
+    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};
+
+    float no_mat[] = {0.0f, 0.0f, 0.0f, 1.0f};
+    float mat_diffuse[] = {0.1f, 0.5f, 0.8f, 1.0f};
+    float mat_specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
+    float high_shininess = 100.0f;
+    
+    glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
+    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
+    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
+    glMaterialf(GL_FRONT, GL_SHININESS, high_shininess);
+    glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
+        
+        
+    glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
+    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
+    glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
+    glEnable(GL_LIGHT0);
+
+    switch(mCurrentPart)
+    {
+    case 0:
+        glDisable(GL_TEXTURE_2D);
+        glShadeModel(GL_SMOOTH);
+        break;
+    case 1:
+        glDisable(GL_TEXTURE_2D);
+       	mShader[0].use();
+        break;
+    case 2:
+        glDisable(GL_TEXTURE_2D);
+       	mShader[1].use();
+        break;
+    };
+    
+    mCurrentFrame = 0;
+    mRunning = true;
+    mStartTime = SDL_GetTicks() / 1000.0;
+    mLastTime = mStartTime;
+}
+
+void SceneShading::update()
+{
+    mCurrentTime = SDL_GetTicks() / 1000.0;
+    mDt = mCurrentTime - mLastTime;
+    mLastTime = mCurrentTime;
+    
+    mElapsedTime = mCurrentTime - mStartTime;
+    
+    if(mElapsedTime >= mPartDuration[mCurrentPart])
+    {
+        mAverageFPS[mCurrentPart] = mCurrentFrame / mElapsedTime;
+        
+        switch(mCurrentPart)
+        {
+        case 0:
+            printf("Shading\n");
+            printf("    Smooth shader model      FPS: %u\n", mAverageFPS[mCurrentPart]);
+            break;
+        case 1:
+            printf("    GLSL per vertex lighting FPS: %u\n", mAverageFPS[mCurrentPart]);
+            break;
+        case 2:
+            printf("    GLSL per pixel lighting  FPS: %u\n", mAverageFPS[mCurrentPart]);
+            break;
+        }
+        mScore += mAverageFPS[mCurrentPart];
+        mCurrentPart++;
+        start();
+        if(mCurrentPart >= mPartsQty)
+            mRunning = false;
+    }
+    
+    mRotation += mRotationSpeed * mDt;
+    
+    mCurrentFrame++;
+}
+
+void SceneShading::draw()
+{
+    glTranslatef(0.0f, 0.0f,-5.0f);
+    glRotated(mRotation, 0.0f, 1.0, 0.0f);
+
+    glColor3f(0.0f, 1.0f, 1.0f);
+
+    mMesh.render_vbo();
+}
+
+
+

=== added file 'scenetexture.cpp'
--- scenetexture.cpp	1970-01-01 00:00:00 +0000
+++ scenetexture.cpp	2010-07-07 10:32:18 +0000
@@ -0,0 +1,127 @@ 
+#include "scene.h"
+
+SceneTexture::~SceneTexture()
+{
+    for(unsigned i = 0; i < 3; i++)
+        glDeleteTextures(1, &mTexture[i]);
+}
+
+int SceneTexture::load()
+{
+    Model model;
+    
+    if(!model.load_3ds("data/models/cube.3ds"))
+        return 0;
+    
+    if(!load_texture("data/textures/crate-base.bmp", mTexture))
+        return 0;
+    
+    model.calculate_normals();
+    model.convert_to_mesh(&mCubeMesh);
+    mCubeMesh.build_list();
+    
+    mRotationSpeed = Vector3f(36.0f, 36.0f, 36.0f);
+    
+    mRunning = false;
+    
+    mPartsQty = 3;
+    mPartDuration = new double[mPartsQty];
+    mAverageFPS = new unsigned[mPartsQty];
+    mScoreScale = new float[mPartsQty];
+    
+    mScoreScale[0] = 0.471f;
+    mScoreScale[1] = 0.533f;
+    mScoreScale[2] = 0.405f;
+    
+    mScore = 0;
+    
+    mPartDuration[0] = 10.0;
+    mPartDuration[1] = 10.0;
+    mPartDuration[2] = 10.0;
+    
+    mCurrentPart = 0;
+    
+    return 1;
+}
+
+void SceneTexture::start()
+{
+    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};
+    
+    glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
+    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
+    glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
+    glEnable(GL_LIGHT0);
+    
+    glEnable(GL_TEXTURE_2D);
+    
+    mCurrentFrame = 0;
+    mRunning = true;
+    mStartTime = SDL_GetTicks() / 1000.0;
+    mLastTime = mStartTime;
+}
+
+void SceneTexture::update()
+{
+    mCurrentTime = SDL_GetTicks() / 1000.0;
+    mDt = mCurrentTime - mLastTime;
+    mLastTime = mCurrentTime;
+    
+    mElapsedTime = mCurrentTime - mStartTime;
+    
+    if(mElapsedTime >= mPartDuration[mCurrentPart])
+    {
+        mAverageFPS[mCurrentPart] = mCurrentFrame / mElapsedTime;
+        
+        switch(mCurrentPart)
+        {
+        case 0:
+            printf("Texture filtering\n");
+            printf("    Nearest                       FPS: %u\n",  mAverageFPS[mCurrentPart]);
+            break;
+        case 1:
+            printf("    Linear                        FPS: %u\n",  mAverageFPS[mCurrentPart]);
+            break;
+        case 2:
+            printf("    Mipmapped                     FPS: %u\n",  mAverageFPS[mCurrentPart]);
+            break;
+        }
+        mScore += mAverageFPS[mCurrentPart];
+        mCurrentPart++;
+        start();
+        if(mCurrentPart >= mPartsQty)
+            mRunning = false;
+    }
+    
+    mRotation += mRotationSpeed * mDt;
+    
+    mCurrentFrame++;
+}
+
+void SceneTexture::draw()
+{
+    glLoadIdentity();
+    glColor3f(1.0f, 1.0f, 1.0f);
+    glTranslatef(0.0f, 0.0f, -4.0f);
+    
+    glRotatef(mRotation.x, 1.0f, 0.0f, 0.0f);
+    glRotatef(mRotation.y, 0.0f, 1.0f, 0.0f);
+    glRotatef(mRotation.z, 0.0f, 0.0f, 1.0f);
+    
+    switch(mCurrentPart)
+    {
+    case 0:
+        glBindTexture(GL_TEXTURE_2D, mTexture[0]);
+        glCallList(mCubeMesh.mBuildList);
+        break;
+    case 1:
+        glBindTexture(GL_TEXTURE_2D, mTexture[1]);
+        glCallList(mCubeMesh.mBuildList);
+    case 2:
+        glBindTexture(GL_TEXTURE_2D, mTexture[2]);
+        glCallList(mCubeMesh.mBuildList);
+        break;
+    }    
+}

=== added file 'screen.cpp'
--- screen.cpp	1970-01-01 00:00:00 +0000
+++ screen.cpp	2010-07-07 10:32:18 +0000
@@ -0,0 +1,116 @@ 
+#include "screen.h"
+
+Screen::Screen()
+{
+    mWidth = 800;
+    mHeight = 600;
+    mBpp = 24;
+    mFlags = SDL_OPENGL;
+    mFullScreen = false;
+
+    mInfo = SDL_GetVideoInfo();
+}
+
+Screen::~Screen()
+{
+    SDL_Quit();
+}
+
+Screen::Screen(int pWidth, int pHeight, int pBpp, int pFlags)
+{
+    mWidth = pWidth;
+    mHeight = pHeight;
+    mBpp = pBpp;
+    mFlags = SDL_OPENGL | pFlags;
+
+    mInfo = SDL_GetVideoInfo();
+}
+
+int Screen::init()
+{
+#ifdef _DEBUG
+    printf("Initializing Screen...           ");
+#endif
+    if(SDL_Init(SDL_INIT_VIDEO) < 0)
+    {
+        fprintf(stderr, "[ Fail ] - Video initialization failed: %s\n", SDL_GetError());
+        return 0;
+    }
+
+    if(mFullScreen)
+    mFlags = SDL_OPENGL | SDL_FULLSCREEN;
+    
+    mInfo = SDL_GetVideoInfo();
+
+    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
+    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
+    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
+    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
+    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+    if(SDL_SetVideoMode(mWidth, mHeight, mBpp, mFlags) == 0)
+    {
+        fprintf(stderr, "[ Fail ] - Video mode set failed: %s\n", SDL_GetError());
+        return 0;
+    }
+    
+    SDL_WM_SetCaption("GLMark 08", NULL);
+    
+    GLenum err = glewInit();
+    if(GLEW_OK != err)
+    {
+        fprintf(stderr, "[ Fail ] - Error: %s\n", glewGetErrorString(err));
+        return 0;
+    }
+
+    if(!GLEW_ARB_vertex_buffer_object)
+    {
+        fprintf(stderr, "[ Fail ] - VBO objects are not supported\n");
+        return 0;
+    }
+
+    glShadeModel(GL_SMOOTH);
+    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
+    glClearDepth(1.0f);
+    glEnable(GL_DEPTH_TEST);
+    glDepthFunc(GL_LEQUAL);
+    glEnable(GL_CULL_FACE);
+    glCullFace(GL_BACK);
+
+    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+    glViewport(0, 0, mWidth, mHeight);
+
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    gluPerspective(60.0, mWidth / (float)mHeight, 1.0, 1024.0);
+    glMatrixMode(GL_MODELVIEW);
+    
+    clear();
+
+#ifdef _DEBUG
+    printf("[ Success ]\n");
+#endif
+    print_info();
+    return 1;
+}
+
+void Screen::clear()
+{
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    glLoadIdentity();
+}
+
+void Screen::update()
+{
+    SDL_GL_SwapBuffers();
+}
+
+void Screen::print_info()
+{
+    printf("    OpenGL Information\n");
+    printf("    GL_VENDOR:     %s\n", glGetString(GL_VENDOR));
+    printf("    GL_RENDERER:   %s\n", glGetString(GL_RENDERER));
+    printf("    GL_VERSION:    %s\n", glGetString(GL_VERSION));
+//    printf("GL_EXTENSIONS:	%s\n", glGetString(GL_EXTENSIONS));
+}
+

=== added file 'screen.h'
--- screen.h	1970-01-01 00:00:00 +0000
+++ screen.h	2010-07-07 10:32:18 +0000
@@ -0,0 +1,29 @@ 
+#ifndef _SCREEN_H
+#define _SCREEN_H
+
+#include "oglsdl.h"
+
+#include <stdio.h>
+
+class Screen
+{
+public:
+    const SDL_VideoInfo *mInfo;
+    
+    int mWidth;
+    int mHeight;
+    int mBpp;
+    int mFlags;
+    int mFullScreen;
+//    SDL_Surface *mScreen;
+
+    Screen();
+    ~Screen();
+    Screen(int pWidth, int pHeight, int pBpp, int pFlags);
+    int init();
+    void clear();
+    void update();
+    void print_info();
+};
+
+#endif

=== added file 'shader.cpp'
--- shader.cpp	1970-01-01 00:00:00 +0000
+++ shader.cpp	2010-07-07 10:32:18 +0000
@@ -0,0 +1,74 @@ 
+#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()
+{
+    remove();
+}
+
+void Shader::load(const char *pVertexShaderFileName, const char *pFragmentShaderFileName)
+{
+    char *vertex_shader_source, *fragment_shader_source;
+    
+	mVertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER);
+	mFragmentShader = glCreateShaderObjectARB(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;
+
+	glShaderSourceARB(mVertexShader, 1, &vs, NULL);
+	glShaderSourceARB(mFragmentShader, 1, &fs, NULL);
+
+	free(vertex_shader_source);
+	free(fragment_shader_source);
+
+	glCompileShaderARB(mVertexShader);
+	glCompileShaderARB(mFragmentShader);
+
+	mShaderProgram = glCreateProgramObjectARB();
+	glAttachObjectARB(mShaderProgram, mFragmentShader);
+	glAttachObjectARB(mShaderProgram, mVertexShader);
+
+	glLinkProgram(mShaderProgram);
+}
+
+void Shader::use()
+{
+    glUseProgramObjectARB(mShaderProgram);
+}
+
+void Shader::remove()
+{
+    glDetachObjectARB(mShaderProgram, mVertexShader);
+    glDetachObjectARB(mShaderProgram, mFragmentShader);
+
+    glDeleteObjectARB(mShaderProgram);
+}

=== added file 'shader.h'
--- shader.h	1970-01-01 00:00:00 +0000
+++ shader.h	2010-07-07 10:32:18 +0000
@@ -0,0 +1,22 @@ 
+#ifndef _SHADER_H
+#define _SHADER_H
+
+#include "oglsdl.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+class Shader
+{
+public:
+    ~Shader();
+    void load(const char *pVertexShaderFileName, const char *pFragmentShaderFileName);
+    void remove();
+    void use();
+    
+    GLuint mVertexShader;
+    GLuint mFragmentShader;
+    int mShaderProgram;
+};
+
+#endif

=== added file 'texture.cpp'
--- texture.cpp	1970-01-01 00:00:00 +0000
+++ texture.cpp	2010-07-07 10:32:18 +0000
@@ -0,0 +1,94 @@ 
+#include "texture.h"
+
+int load_texture(const char pFilename[], GLuint *pTexture)
+{
+    SDL_Surface *surface;
+    GLenum texture_format;
+    GLint  nOfColors;
+
+    if ((surface = SDL_LoadBMP(pFilename)))
+    {
+        if ((surface->w & (surface->w - 1)) != 0)
+            printf("warning: image.bmp's width is not a power of 2\n");
+
+        if ((surface->h & (surface->h - 1)) != 0)
+            printf("warning: image.bmp's height is not a power of 2\n");
+
+        nOfColors = surface->format->BytesPerPixel;
+        if (nOfColors == 4)
+        {
+            if (surface->format->Rmask == 0x000000ff)
+                texture_format = GL_RGBA;
+            else
+                texture_format = GL_BGRA;
+        }
+        else
+        {
+            if (nOfColors == 3)
+            {
+                if (surface->format->Rmask == 0x000000ff)
+                    texture_format = GL_RGB;
+                else
+                    texture_format = GL_BGR;
+            }
+            else
+            {
+                printf("warning: the image is not truecolor..  this will probably break\n");
+            }
+        }
+
+        glGenTextures(3, pTexture);
+
+        // Create Nearest Filtered Texture
+		glBindTexture(GL_TEXTURE_2D, pTexture[0]);
+		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+		glTexImage2D(GL_TEXTURE_2D, 0, nOfColors, surface->w, surface->h, 0, texture_format, GL_UNSIGNED_BYTE, surface->pixels);
+		
+		// Create Linear Filtered Texture
+		glBindTexture(GL_TEXTURE_2D, pTexture[1]);
+		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+		glTexImage2D(GL_TEXTURE_2D, 0, nOfColors, surface->w, surface->h, 0, texture_format, GL_UNSIGNED_BYTE, surface->pixels);
+
+        // Create MipMapped Texture
+		glBindTexture(GL_TEXTURE_2D, pTexture[2]);
+		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
+		
+		gluBuild2DMipmaps(GL_TEXTURE_2D, 3, surface->w, surface->h, texture_format, GL_UNSIGNED_BYTE, surface->pixels);
+
+/*
+        switch (filter)
+        {
+        case 0:
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+            glTexImage2D(GL_TEXTURE_2D, 0, nOfColors, surface->w, surface->h, 0, texture_format, GL_UNSIGNED_BYTE, surface->pixels);
+            break;
+
+        case 1:
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+            glTexImage2D(GL_TEXTURE_2D, 0, nOfColors, surface->w, surface->h, 0, texture_format, GL_UNSIGNED_BYTE, surface->pixels);
+            break;
+
+        case 2:
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+            gluBuild2DMipmaps(GL_TEXTURE_2D, 3, surface->w, surface->h, GL_RGB, GL_UNSIGNED_BYTE, surface->pixels);
+            break;
+        }
+*/
+    }
+    else
+    {
+        fprintf(stderr, "SDL could not load image.bmp: %s\n", SDL_GetError());
+        return 0;
+    }
+
+    if (surface)
+        SDL_FreeSurface(surface);
+
+    return 1;
+}

=== added file 'texture.h'
--- texture.h	1970-01-01 00:00:00 +0000
+++ texture.h	2010-07-07 10:32:18 +0000
@@ -0,0 +1,10 @@ 
+#ifndef _TEXTURE_H
+#define _TEXTURE_H
+
+#include "oglsdl.h"
+
+#include <stdio.h>
+
+int load_texture(const char pFilename[], GLuint *pTexture);
+
+#endif

=== added file 'vector.cpp'
--- vector.cpp	1970-01-01 00:00:00 +0000
+++ vector.cpp	2010-07-07 10:32:18 +0000
@@ -0,0 +1,125 @@ 
+#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;
+}
+

=== added file 'vector.h'
--- vector.h	1970-01-01 00:00:00 +0000
+++ vector.h	2010-07-07 10:32:18 +0000
@@ -0,0 +1,45 @@ 
+#ifndef _VECTOR_H
+#define _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