OpenGL Objects Finalised
Debugging Tip For Debugging your applications remember: glGetError(); gluErrorString(); Don’t use these in release code (the render loop), as fetching the error from the card is slow!!!
Packing Your Objects
My Stupid Tetrahedron glBegin( GL_TRIANGLE_FAN ); glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.0f, 1.0f, 0.0f ); glColor3f(0.0f,1.0f,0.0f); glVertex3f( 0.5f, 0.0f, 0.0f ); glColor3f(0.0f,0.0f,1.0f); glVertex3f( -0.5f, 0.0f, 0.0f ); glColor3f(0.0f,1.0f,1.0f); glVertex3f( 0.0f, 0.0f, -1.0f ); glColor3f(1.0f,0.0f,1.0f); glVertex3f( 0.5f, 0.0f, 0.0f ); glEnd(); glBegin( GL_TRIANGLES ); glColor3f(0.5f,1.0f,0.5f); glVertex3f( 0.5f, 0.0f, 0.0f ); glVertex3f( -0.5f, 0.0f, 0.0f ); glVertex3f( 0.0f, 0.0f, -1.0f ); glEnd();
The Basic Packing Code GLuInt Beef = glGenLists( 1); glNewList( Beef) ……\\ Object List glEndList(); content/uploads/2007/04/heres-the-beef.jpg
Lists can work in a hierarchy glNewList(Cow); glTranslatef(…) glCallList(Beef); glTranslatef(…) glCallList(Beef); glTranslatef(…) glCallList(Beef); glEndList(); content/uploads/2007/04/heres-the-beef.jpg
Old Old way of drawing the Tetrahedron glBegin( GL_TRIANGLE_FAN ); glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.0f, 1.0f, 0.0f ); glColor3f(0.0f,1.0f,0.0f); glVertex3f( 0.5f, 0.0f, 0.0f ); glColor3f(0.0f,0.0f,1.0f); glVertex3f( -0.5f, 0.0f, 0.0f ); glColor3f(0.0f,1.0f,1.0f); glVertex3f( 0.0f, 0.0f, -1.0f ); glColor3f(1.0f,0.0f,1.0f); glVertex3f( 0.5f, 0.0f, 0.0f ); glEnd(); glBegin( GL_TRIANGLES ); glColor3f(0.5f,1.0f,0.5f); glVertex3f( 0.5f, 0.0f, 0.0f ); glVertex3f( -0.5f, 0.0f, 0.0f ); glVertex3f( 0.0f, 0.0f, -1.0f ); glEnd();
New Way glCallList(Tetrahedron); om/Geometry/Tetrahedr on_files/image004.jpg
Our Objects are now in nice packages – glCallList(Cow) Rendering code looks very nice But it still requires a lot of calls to OpenGL
glNewList(Tetrahedron); glBegin( GL_TRIANGLE_FAN ); glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.0f, 1.0f, 0.0f ); glColor3f(0.0f,1.0f,0.0f); glVertex3f( 0.5f, 0.0f, 0.0f ); glColor3f(0.0f,0.0f,1.0f); glVertex3f( -0.5f, 0.0f, 0.0f ); glColor3f(0.0f,1.0f,1.0f); glVertex3f( 0.0f, 0.0f, -1.0f ); glColor3f(1.0f,0.0f,1.0f); glVertex3f( 0.5f, 0.0f, 0.0f ); glEnd(); glBegin( GL_TRIANGLES ); glColor3f(0.5f,1.0f,0.5f); glVertex3f( 0.5f, 0.0f, 0.0f ); glVertex3f( -0.5f, 0.0f, 0.0f ); glVertex3f( 0.0f, 0.0f, -1.0f ); glEnd(); glEndList(); What Really Happens glCallList(Tetrahedron);
Say Hello to Vertex Arrays Array Types: Vertex Normal Colour Index Texture Coordinate Array Edge Flag Array
Declaring an Array GLfloat vertices[8] = { (0.0,1.0,0.0), (0.5,0.0,0.0), (-0.5,0.0,0.0), (0.0,0.0,-1.0), (0.5,0.0,0.0), (0.0,0.0,-1.0), (-0.5,0.0,-0.0.0), (0.0,0.0,-1.0), };
Enabling and Disabling your Arrays glEnableClientState(array); glDisableClientState(array); Client state refers to system memory!! GL_COLOR_ARRAY – Array for Vertex Colours GL_EDGE_FLAG_ARRAY – Array for Wireframe (Line Drawing) GL_INDEX_ARRAY – Array of Arrays GL_NORMAL_ARRAY – Normals (typically Per Vertex) GL_TEXTURE_COORD_ARRAY – Duh! GL_VERTEX_ARRAY – Duh!
Accessing Your Array glVertexPointer(): specify pointer to vertex coordinates array glNormalPointer(): specify pointer to normal array glColorPointer(): specify pointer to RGB colour array glIndexPointer(): specify pointer to indexed colour array glTexCoordPointer(): specify pointer to texture cordinates array glEdgeFlagPointer(): specify pointer to edge flag array
Drawing From an Array Set The Vertex Pointer – glVertexPointer(…); Use the array in the Draw Function – glDrawArrays();
Old Way of Drawing the Tetrahedron glBegin( GL_TRIANGLE_FAN ); glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.0f, 1.0f, 0.0f ); glColor3f(0.0f,1.0f,0.0f); glVertex3f( 0.5f, 0.0f, 0.0f ); glColor3f(0.0f,0.0f,1.0f); glVertex3f( -0.5f, 0.0f, 0.0f ); glColor3f(0.0f,1.0f,1.0f); glVertex3f( 0.0f, 0.0f, -1.0f ); glColor3f(1.0f,0.0f,1.0f); glVertex3f( 0.5f, 0.0f, 0.0f ); glEnd(); glBegin( GL_TRIANGLES ); glColor3f(0.5f,1.0f,0.5f); glVertex3f( 0.5f, 0.0f, 0.0f ); glVertex3f( -0.5f, 0.0f, 0.0f ); glVertex3f( 0.0f, 0.0f, -1.0f ); glEnd();
Drawing the Tetrahedron With an Array GLfloat vertices[8] = { (0.0,1.0,0.0), (0.5,0.0,0.0), (-0.5,0.0,0.0), (0.0,0.0,-1.0), (0.5,0.0,0.0), (0.0,0.0,-1.0), (-0.5,0.0,-0.0.0), (0.0,0.0,-1.0), }; // Enable the vertex Array glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, vertices); // draw a tetrahedron glDrawArray(GL_TRIANGLE_FAN, 0, 4); glDrawArray(GL_TRIANGLES, 3, 3; // deactivate vertex array glDisableClientState(GL_VERTEX_ARRAY);
Even Faster Ways of Drawing We have used glDrawArrays(mode, first, count); The other options we have are: – glDrawElements(mode, count, type, indices); – glDrawRangeElements(mode, start, end, count, type, indicies); // An optimised version of glDrawElements
Declaring a Better Array GLfloat vertices[4] = { (0.0,1.0,0.0), (0.5,0.0,0.0), (-0.5,0.0,0.0), (0.0,0.0,-1.0)}; Glfloat indicies[12] = {0,1,2, 0,2,3, 0,3,1, 1,2,3};
Drawing the Tetrahedron Faster GLfloat vertices[4] = {...} Glflaot indicies[12] = {…} // Enable the vertex Array glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, vertices); // draw a tetrahedron glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_BYTE, indices); // deactivate vertex array glDisableClientState(GL_VERTEX_ARRAY);
You can’t always share your normals!
Partitioning your world ClearCut.jpg
Binary Spacial Partitioning (BSP) In today's gaming world, there are two important reasons for dividing the world – Rendering without the Z-Buffer – Rendering Translucent (Alpha Blend) Polygons
Why? Modern games have so many polygons that stretching the z buffer to cover the entire object range would result in many visual glitches, as many polygons start falling into the same depth levels of the buffer. Translucent Polygons are created using a blend function which requires back-to-front rendering (Painters algorithm)
How? There are many differing ways and methods to create maps of polygons, especially static collections One of the most common and a very efficient way is utilising BSP trees. – The first use of a BSP tree was Doom in 1993 It was only used in a 2D implementation!
A BSP is a specialised implementation of a Binary Data Tree Binary Trees are used because: the ability to be efficiently traversed in both directions The ability to add data randomly during the building of the tree The speed in which a random location can be found
Binary Data Trees gif/CompleteBinaryTree_1000.gif /features/trees2/BuildTree1.gif
The Principal to creating a BSP Tree Each polygon (3D) / line (2D) creates a dividing line / plane in the tree where every other Polygon/line is either in front or behind.
Cutting your Polygons The offending Polygon / Line must be cut into two parts It then becomes two separate polygons / lines One infront of the division, the other behind
Reordering the split If we split using the red/green line first, our tree would require no splitting
Problems Creating BSP Lists Minimising Polygon Cuts Balancing the Tree
A short 2D Example
Creating a BSP Tree for Lines (Doom Style)