gluSphere(q, 0.2f, 16, 8); // Draw A Little Yellow Sphere (Represents Light)
glEnable(GL_LIGHTING); // Enable Lighting
glDepthMask(GL_TRUE); // Enable Depth Mask
The last part updates the object's position and returns.
xrot += xspeed; // Increase xrot By xspeed
yrot += yspeed; // Increase yrot By yspeed
glFlush(); // Flush The OpenGL Pipeline
return TRUE; // Everything Went OK
}
We did specify a DrawGLRoom function, and here it is — a bunch of rectangles to cast shadows against:
void DrawGLRoom() // Draw The Room (Box)
{
glBegin(GL_QUADS); // Begin Drawing Quads
// Floor
glNormal3f(0.0f, 1.0f, 0.0f); // Normal Pointing Up
glVertex3f(-10.0f,-10.0f,-20.0f); // Back Left
glVertex3f(-10.0f,-10.0f, 20.0f); // Front Left
glVertex3f( 10.0f,-10.0f, 20.0f); // Front Right
glVertex3f( 10.0f,-10.0f,-20.0f); // Back Right
// Ceiling
glNormal3f(0.0f,-1.0f, 0.0f); // Normal Point Down
glVertex3f(-10.0f, 10.0f, 20.0f); // Front Left
glVertex3f(-10.0f, 10.0f,-20.0f); // Back Left
glVertex3f( 10.0f, 10.0f,-20.0f); // Back Right
glVertex3f( 10.0f, 10.0f, 20.0f); // Front Right
// Front Wall
glNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Away From Viewer
glVertex3f(-10.0f, 10.0f,-20.0f); // Top Left
glVertex3f(-10.0f,-10.0f,-20.0f); // Bottom Left
glVertex3f( 10.0f,-10.0f,-20.0f); // Bottom Right
glVertex3f( 10.0f, 10.0f,-20.0f); // Top Right
// Back Wall
glNormal3f(0.0f, 0.0f,-1.0f); // Normal Pointing Towards Viewer
glVertex3f( 10.0f, 10.0f, 20.0f); // Top Right
glVertex3f( 10.0f,-10.0f, 20.0f); // Bottom Right
glVertex3f(-10.0f,-10.0f, 20.0f); // Bottom Left
glVertex3f(-10.0f, 10.0f, 20.0f); // Top Left
// Left Wall
glNormal3f(1.0f, 0.0f, 0.0f); // Normal Pointing Right
glVertex3f(-10.0f, 10.0f, 20.0f); // Top Front
glVertex3f(-10.0f,-10.0f, 20.0f); // Bottom Front
glVertex3f(-10.0f,-10.0f,-20.0f); // Bottom Back
glVertex3f(-10.0f, 10.0f,-20.0f); // Top Back
// Right Wall
glNormal3f(-1.0f, 0.0f, 0.0f); // Normal Pointing Left
glVertex3f( 10.0f, 10.0f,-20.0f); // Top Back
glVertex3f( 10.0f,-10.0f,-20.0f); // Bottom Back
glVertex3f( 10.0f,-10.0f, 20.0f); // Bottom Front
glVertex3f( 10.0f, 10.0f, 20.0f); // Top Front
glEnd(); // Done Drawing Quads
}
And before I forget, here is the VMatMult function which multiplies a vector by a matrix (get that Math textbook out again!):
void VMatMult(GLmatrix16f M, GLvector4f v) {
GLfloat res[4]; // Hold Calculated Results
res[0]=M[ 0]*v[0]+M[ 4]*v[1]+M[ 8]*v[2]+M[12]*v[3];
res[1]=M[ 1]*v[0]+M[ 5]*v[1]+M[ 9]*v[2]+M[13]*v[3];
res[2]=M[ 2]*v[0]+M[ 6]*v[1]+M[10]*v[2]+M[14]*v[3];
res[3]=M[ 3]*v[0]+M[ 7]*v[1]+M[11]*v[2]+M[15]*v[3];
v[0]=res[0]; // Results Are Stored Back In v[]
v[1]=res[1];
v[2]=res[2];
v[3]=res[3]; // Homogenous Coordinate
}
The function to load the object is simple, just calling readObject, and then setting up the connectivity and the plane equations for each face.
int InitGLObjects() // Initialize Objects
{
if (!readObject("Data/Object2.txt", obj)) // Read Object2 Into obj
{
return FALSE; // If Failed Return False
}
setConnectivity(obj); // Set Face To Face Connectivity
for (int i=0; i < obj.nFaces; i++) // Loop Through All Object Faces
calculatePlane(obj, obj.pFaces[i]); // Compute Plane Equations For All Faces
return TRUE; // Return True
}
Finally, KillGLObjects is a convenience function so that if you add more objects, you can add them in a central place.
void KillGLObjects() {
killObject( obj );
}
All of the other functions don't require any further explanantion. I have left out the standard NeHe tutorial code, as well as all of the variable definitions and the keyboard processing function. The commenting alone explains these sufficiently.
Some things to note about the tutoriaclass="underline"
• The sphere doesn't stop shadows being projected on the wall. In reality, the sphere should also be casting a shadow, so seeing the one on the wall won't matter, it's hidden. It's just there to see what happens on curved surfaces :)
• If you are noticing extremely slow frame rates, try switching to fullscreen mode, or setting your desktop colour depth to 32bpp.
• Arseny L. writes: If you are having problems with a TNT2 in Windowed mode, make sure your desktop color depth is not set to 16bit. In 16bit color mode, the stencil buffer is emulated, resulting in sluggish performance. There are no problems in 32bit mode (I have a TNT2 Ultra and I checked it). I've got to admit this was a lengthy task to write out this tutorial. It gives you full appreciation for the work that Jeff puts in! I hope you enjoy it, and give a huge thanks to Banu who wrote the original code! IF there is anything that needs further explaining in here, you are welcome to contact me (Brett), at brettporter@yahoo.com.
* DOWNLOAD Visual C++ Code For This Lesson.
* DOWNLOAD Linux Code For This Lesson. (Conversion by Jay Groven)
Lesson 28
This tutorial is intended to introduce you to Bezier Surfaces in the hopes that someone more artistic than myself will do something really cool with them and show all of us. This is not intended as a complete Bezier patch library, but more as proof of concept code to get you familiar with how these curved surfaces actually work. Also, as this is a very informal piece, I may have occasional lapses in correct terminology in favor of comprehensability; I hope this sits well with everyone. Finally, to those of you already familiar with Beziers who are just reading this to see if I screw up, shame on you ;-), but if you find anything wrong by all means let me or NeHe know, after all no one's perfect, eh? Oh, and one more thing, none of this code is optimised beyond my normal programming technique, this is by design. I want everyone to be able to see exactly what is going on. Well, I guess that's enough of an intro. On with the show!