Well greetings all. For those of you that want to see what we are doing here, you can check it out at the end of my demo/hack Worthless! I am bosco and I will do my best to teach you guys how to do the animated, sine-wave picture. This tutorial is based on NeHe's tutorial #6 and you should have at least that much knowledge. You should download the source package and place the bitmap I've included in a directory called data where your source code is. Or use your own texture if it's an appropriate size to be used as a texture with OpenGL.

First things first. Open Tutorial #6 in the applicable source editor. And add the following somewhere near the top next to their respective counterparts.
#include <math.h>		// For the sin() function


float points[ 45 ][ 45 ][3]; // The array for the points on the grid of our "wave"

We'll use this array, "points" to store the individual x, y, z coordinates of our grid. The grid is 45 points by 45 points, which in turn makes 44 quads x 44 quads. Also add the following line toward the top next to the array.
int wiggle_count = 0;

We'll use this variable to decide when to "cycle" our sine values and animate our wave. Every three frames looks really good on my box.

Change the filename in the LoadGLTextures() function to the appropriate file. I personally like my bitmap in the same directory as my executable, but that's just me, so my line looks like this.
texture1 = auxDIBImageLoad("tim.bmp");

Now add the following code to the bottom of the InitGL() function before the closing "}".
	for(float  float_x = 0.0f; float_x < 9.0f; float_x +=  0.2f )
	{
		for( float float_y = 0.0f; float_y < 9.0f; float_y += 0.2f)
		{
			points[ int(float_x*5) ][ int(float_y*5) ][0] = float_x - 4.4f;
			points[ int(float_x*5) ][ int(float_y*5) ][1] = float_y - 4.4f;
			points[ int(float_x*5) ][ int(float_y*5) ][2] = float(sin( ( (float_x*5*8)/360 ) * 3.14159 * 2 ));
		}
	}

Ok, before I said our grid is 45 points by 45 points. Well to accomplish this without having to push our scene back too far, we merely use a world coordinate of 9x9 and space the points 0.2 units apart.

These two loops initialize the points on our grid. I initialize variables in my loop to localize them in my mind as merely loop variables. Not sure it's kosher. To come up with the array reference we have to multiply our loop variable by 5 ( i.e. 45 / 9 = 5 ). I subtract 4.4 from each of the coordinates to put the "wave" centered on the origin. The same effect could be accomplished with a translate, but I prefer this method.

The final value points[x][y][2] statement is our sine value. The sin() function requires radians. We take our degree value, which is our float_x multiplied by 5 to get a whole number and then by 8 ( i.e. 360/8 is 45 ). Once we have that, to convert to radians we take the degree, divide by 360, multiply by pi, or an approximation and then multiply by 2.

I'm going to re-write the DrawGLScene function from scratch so clean it out and it replace with the following code.
GLvoid DrawGLScene(GLvoid)
{
	int x, y;
	float float_x, float_y, float_xb, float_yb;

Different variables used for controlling the loops. See the code below but most of these serve no "specific" purpose other than controlling loops and storing temporary values.
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	
	glLoadIdentity();							
	glTranslatef(0.0f,0.0f,-12.0f);

	glRotatef(xrot,1.0f,0.0f,0.0f);
	glRotatef(yrot,0.0f,1.0f,0.0f);  
	glRotatef(zrot,0.0f,0.0f,1.0f);

	glBindTexture(GL_TEXTURE_2D, texture[0]);

You've seen all of this before as well. Same as in tutorial #6 except I merely push my scene back away from the camera a bit more.
	glPolygonMode( GL_BACK, GL_FILL );
	glPolygonMode( GL_FRONT, GL_LINE );

These simple specify that we want back facing polygons to be filled completely and that we want front facing polygons to be outlined only. Mostly personal preference at this point. Has to do with the orientation of the polygon or the direction of the vertices. See the Red Book for more information on this. Incidentally, while I'm at it, let me plug that as it's one of the driving forces behind me learning OpenGL, not to mention NeHe's site! Thanks NeHe. Buy The Programmer's Guide to OpenGL from Addison-Wesley. It's an invaluable resource as far as I'm concerned. Ok, back to the tutorial.
	glBegin( GL_QUADS );

	for( x = 0; x < 44; x++ )
	{
		for( y = 0; y < 44; y++ )
		{

Merely starts the loop to draw our polygons. I use integers here to keep from having to use the int() function as I did earlier to get the array reference returned as an integer.
			float_x = float(x)/44;
			float_y = float(y)/44;
			float_xb = float(x+1)/44;
			float_yb = float(y+1)/44;

We use these four variables for the texture coordinates. Each of our polygons(quads), square in the grid, has a 1/44 x 1/44 section of the texture mapped on it. The loops will specify the lower left vertex and then we just add to it accordingly to get the other three ( i.e. x+1 or y+1 ).
			glTexCoord2f( float_x, float_y);
			glVertex3f( points[x][y][0], points[x][y][1], points[x][y][2] );
			
			glTexCoord2f( float_x, float_yb );
			glVertex3f( points[x][y+1][0], points[x][y+1][1], points[x][y+1][2] );
			
			glTexCoord2f( float_xb, float_yb );
			glVertex3f( points[x+1][y+1][0], points[x+1][y+1][1], points[x+1][y+1][2] );
			
			glTexCoord2f( float_xb, float_y );
			glVertex3f( points[x+1][y][0], points[x+1][y][1], points[x+1][y][2] );
		}
	}
	glEnd();

These lines merely make the OpenGL calls to pass all the data we talked about. Four separate calls to each glTexCoord2f() and glVertex3f(). Continue with the following.
	if( wiggle_count == 2 )
	{

If we've drawn two scenes, then we want to cycle our sine values giving us "motion".
		for( y = 0; y < 45; y++)
		{
			points[44][y][2] = points[0][y][2];
		}

This sets all of the last column of our grid's values to be equal to our grid's first values. If you have trouble seeing this, think of a conveyor belt. When the item gets pushed off the end the conveyor belt returns to the beginning to get another item. Same concept here. The point is being pushed off the end so we send it back to the beginning.
		for( x = 0; x < 44; x++ )
		{
			for( y = 0; y < 45; y++)
			{
				points[x][y][2] = points[x+1][y][2];
			}
		}
		wiggle_count = 0;
	}
	wiggle_count++;

What we do here is cycle the rest of the values. Pushing everything one position toward the end. And so if we did do this, then we want to set our "frame" counter back to zero. If we didn't, in fact, move our values, then we need to increment our counter. I'll admit this isn't a real "scalable" way of doing things, but hey what can I say, it looks great on mine and most everyone else's machine and I'm not perfect.. ( gasp! ) Tweak at will.
	xrot+=0.3f;
	yrot+=0.2f;
	zrot+=0.4f;
}

Standard NeHe rotation values. :) And that's it folks. Compile and you should have a nice rotating bitmapped "wave". I'm not sure what else to say except, whew.. This was LONG! But I hope you guys can follow it/get something out of it. If you have any questions, want me to clear something up or tell me how god awful, lol, I code, then send me a note. Also there is a slight visual glitch in this effect. If you notice it and/or can fix it send me some mail as well. I played with it a bit and decided it wasn't worth the trouble.. Other than that, this was a blast, but very energy/time consuming and makes me appreciate the likes of NeHe ALOT more now. Thanks all.

Bosco (bosco4@home.com)

* DOWNLOAD Visual C++ Code For This Lesson.
* DOWNLOAD Visual Fortran Code For This Lesson. ( Conversion by Jean-Philippe Perois )
* DOWNLOAD Delphi Code For This Lesson. ( Conversion by Marc Aarts )
* DOWNLOAD Mac OS Code For This Lesson. ( Conversion by Anthony Parker )
* DOWNLOAD Power Basic Code For This Lesson. ( Conversion by Angus Law )
* DOWNLOAD Java Code For This Lesson. ( Conversion by Darren Hodges )