home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OpenGL Superbible
/
OpenGL_Superbible_Waite_Group_Press_1996.iso
/
book
/
chapt10
/
tank
/
microsoft
/
renderworld.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-07-07
|
18KB
|
699 lines
// RenderWorld.c
// This file actually renders the world
#include <windows.h> // Normal Windows stuff
#include <math.h>
#include <gl/gl.h> // Core OpenGL functions
#include <gl/glu.h> // OpenGL Utility functions
#include <gl/glaux.h>
#include "externs.h" // Data shared between files
#include "glutils.h" // Utilities for this application
// Prevent anoying compiler warnings - only used locally
#define fsin(x) (float)sin(x)
#define fcos(x) (float)cos(x)
// Useful structure for storing coordinates of objects. We declare
// an array of these to hold the positions of the various types of objects
struct COORD
{
float x;
float z;
};
// Maximum number of each type of object
#define MAX_EACH 15
// Arrays of objects
struct COORD Pyramids[MAX_EACH];
struct COORD Slabs[MAX_EACH];
struct COORD Pillers[MAX_EACH];
void RandomizePositions(void);
float RandomPos(void);
void PlacePyramids(void);
void PlaceSlabs(void);
void PlacePillers(void);
void DrawGround(void);
void DrawTank(void);
void DrawRobot(void);
///////////////////////////////////////////////////////////////////////////////
// Pick a random value between -1000.0 and 1000.0
float RandomPos(void)
{
double dRet = 0.0f;
dRet = (double)rand(); // between 0 and RAND_MAX
dRet = dRet/(double)RAND_MAX; // between 0 and 1.0
dRet *= 2000.0f; // between 0 and 2000
dRet -= 1000.0f; // between -1000 and 1000
return (float)dRet;
}
///////////////////////////////////////////////////////////////////////////////
// Position the objects in the scene
void RandomizePositions()
{
int i;
// Pick two random values for x and z coordinates
for(i = 0; i < MAX_EACH; i++)
{
Pyramids[i].x = RandomPos();
Pyramids[i].z = RandomPos();
Slabs[i].x = RandomPos();
Slabs[i].z = RandomPos();
Pillers[i].x = RandomPos();
Pillers[i].z = RandomPos();
}
}
////////////////////////////////////////////////////////////////////////////////
// Put the Pyramids in place Draws each one individually
void PlacePyramids(void)
{
int i;
for(i = 0; i < MAX_EACH; i++)
{
glPushMatrix();
glTranslatef(Pyramids[i].x, 0.0f, Pyramids[i].z);
DrawPyramid();
glPopMatrix();
}
}
///////////////////////////////////////////////////////////////////////////////
// Put the slabs in place
void PlaceSlabs(void)
{
int i;
// Loop through, and place each one
for(i = 0; i < MAX_EACH; i++)
{
glPushMatrix();
glTranslatef(Slabs[i].x, 21.0f, Slabs[i].z);
DrawSlab();
glPopMatrix();
}
}
////////////////////////////////////////////////////////////////////////////////
// Put the Pillers in place
void PlacePillers(void)
{
int i;
// Place each Piller
for(i = 0; i < MAX_EACH; i++)
{
glPushMatrix();
glTranslatef(Pillers[i].x, 23.5f, Pillers[i].z);
DrawPiller();
glPopMatrix();
}
}
////////////////////////////////////////////////////////////////////////////////
// Render the entire scene
void RenderWorld(void)
{
glCallList(nWorldList);
// Pillers not place in display list because of auxSolidBox problems
PlacePillers();
// Draw the robot or the tank. If we draw both, our view will be from
// the inside of whichever one we are.
if(bTank)
DrawRobot();
else
DrawTank();
}
/////////////////////////////////////////////////////////////////////////////
/// Objects contained in the scene
/////////////////////////////////////////////////////////////////////////////////
// Draw the ground just as a grid of lines. No transformation to take place
void DrawGround(void)
{
int r,c;
int nStep = 30;
// Draw Ground in Green
glRGB(0,255,0);
// The ground has a normal too
glNormal3f(0.0f, 1.0f, 0.0f);
// Just draw a bunch of horizontal and vertical lines
glBegin(GL_LINES);
for(r = -1000; r <= 1000; r += nStep)
{
glVertex3f((float)r, 0.0f, -1000.0f);
glVertex3f((float)r, 0.0f, 1000.0f);
}
for(c = -1000; c <= 1000; c += nStep)
{
glVertex3f(1000.0f, 0.0f, (float)c);
glVertex3f(-1000.0f, 0.0f, (float)c);
}
glEnd();
}
////////////////////////////////////////////////////////////////////////////
// A Piller or column
void DrawPiller()
{
GLfloat vNormal[3];
GLfloat x,z,angle; // Storage for coordinates and angles
GLfloat fStep = (float)PI/4.0f;
GLfloat fHeight = 20.0f;
GLfloat fRadius = 7.0f;
// Grey
glRGB(128,128,128);
// Normals are easy for cylinders
glBegin(GL_QUAD_STRIP);
vNormal[0] = fRadius;
vNormal[1] = fHeight;
vNormal[2] = 0.0f;
ReduceToUnit(vNormal);
glNormal3fv(vNormal);
glVertex3f(fRadius, fHeight, 0.0f);
glVertex3f(fRadius, -fHeight, 0.0f);
for(angle = fStep; angle < 3.0f*PI; angle += fStep)
{
x = fRadius*fsin(angle);
z = fRadius*fcos(angle);
vNormal[0] = x;
vNormal[1] = fHeight;
vNormal[2] = z;
ReduceToUnit(vNormal);
glNormal3fv(vNormal);
glVertex3f(x, fHeight, z );
glVertex3f(x, -fHeight, z);
}
glEnd();
// Draw the box at both ends
glPushMatrix();
glTranslatef(0.0f, -fHeight-(fRadius/4), 0.0f);
auxSolidBox(fRadius*2.5, fRadius/2, fRadius*2.5);
glTranslatef(0.0f, (fHeight+(fRadius/4))*2, 0.0f);
auxSolidBox(fRadius*2.5, fRadius/2, fRadius*2.5);
glPopMatrix();
}
///////////////////////////////////////////////////////////////////////////////
// Draw a pyramid
void DrawPyramid(void)
{
GLfloat vNormal[3];
GLfloat vvVertices[3][3];
GLfloat fWidth = 15.0f;
GLfloat fHeight = 30.0f;
// Red Pyramids
glRGB(255,0,0);
// Simple, build with four triangles.
glBegin(GL_TRIANGLES);
vvVertices[0][0] = fWidth;
vvVertices[0][1] = 0.0f;
vvVertices[0][2] = fWidth;
vvVertices[1][0] = fWidth;
vvVertices[1][1] = 0.0f;
vvVertices[1][2] = -fWidth;
vvVertices[0][0] = 0.0f;
vvVertices[0][1] = fHeight;
vvVertices[0][2] = 0.0f;
calcNormal(vvVertices, vNormal);
glNormal3fv(vNormal);
glVertex3f(fWidth, 0.0f, fWidth);
glVertex3f(fWidth, 0.0f, -fWidth);
glVertex3f(0.0f, fHeight, 0.0f);
vvVertices[0][0] = fWidth;
vvVertices[0][1] = 0.0f;
vvVertices[0][2] = fWidth;
vvVertices[1][0] = 0.0f;
vvVertices[1][1] = fHeight;
vvVertices[1][2] = 0.0f;
vvVertices[0][0] = -fWidth;
vvVertices[0][1] = 0.0f;
vvVertices[0][2] = fWidth;
calcNormal(vvVertices, vNormal);
glNormal3fv(vNormal);
glVertex3f(fWidth, 0.0f, fWidth);
glVertex3f(0.0f, fHeight, 0.0f);
glVertex3f(-fWidth, 0.0f, fWidth);
vvVertices[0][0] = -fWidth;
vvVertices[0][1] = 0.0f;
vvVertices[0][2] = fWidth;
vvVertices[1][0] = 0.0f;
vvVertices[1][1] = fHeight;
vvVertices[1][2] = 0.0f;
vvVertices[0][0] = -fWidth;
vvVertices[0][1] = 0.0f;
vvVertices[0][2] = -fWidth;
calcNormal(vvVertices, vNormal);
glNormal3fv(vNormal);
glVertex3f(-fWidth, 0.0f, fWidth);
glVertex3f(0.0f, fHeight, 0.0f);
glVertex3f(-fWidth, 0.0f, -fWidth);
vvVertices[0][0] = -fWidth;
vvVertices[0][1] = 0.0f;
vvVertices[0][2] = -fWidth;
vvVertices[1][0] = 0.0f;
vvVertices[1][1] = fHeight;
vvVertices[1][2] = 0.0f;
vvVertices[0][0] = fWidth;
vvVertices[0][1] = 0.0f;
vvVertices[0][2] = -fWidth;
calcNormal(vvVertices, vNormal);
glNormal3fv(vNormal);
glVertex3f(-fWidth, 0.0f, -fWidth);
glVertex3f(0.0f, fHeight, 0.0f);
glVertex3f(fWidth, 0.0f, -fWidth);
glEnd();
}
///////////////////////////////////////////////////////////////////////////////
// Draw the Slabs
void DrawSlab()
{
GLfloat fWidth = 12.0f;
GLfloat fHeight = 20.0f;
GLfloat fDepth = 7.0f;
GLfloat fEdge = 1.0f;
GLfloat vNormal[3];
GLfloat vvVertices[3][3];
// Blue Slabs
glRGB(0,0, 255);
// Simple, build with four triangles.
glBegin(GL_QUADS);
// Front
glNormal3f(0.0f, 0.0f, -1.0f);
glVertex3f(fWidth, fHeight, -fDepth);
glVertex3f(fWidth, -fHeight, -fDepth);
glVertex3f(-fWidth, -fHeight, -fDepth);
glVertex3f(-fWidth, fHeight, -fDepth);
// Back
glNormal3f(0.0f, 0.0f, 1.0f);
glVertex3f(-fWidth, fHeight, fDepth);
glVertex3f(-fWidth, -fHeight, fDepth);
glVertex3f(fWidth, -fHeight, fDepth);
glVertex3f(fWidth, fHeight, fDepth);
// Top
glNormal3f(0.0f, 1.0f, 0.0f);
glVertex3f(fWidth-fEdge, fHeight+fEdge, fDepth-fEdge);
glVertex3f(fWidth-fEdge, fHeight+fEdge, -(fDepth-fEdge));
glVertex3f(-(fWidth-fEdge), fHeight+fEdge, -(fDepth-fEdge));
glVertex3f(-(fWidth-fEdge), fHeight+fEdge, fDepth-fEdge);
// Bottom
glNormal3f(0.0f, -1.0f, 0.0f);
glVertex3f(-(fWidth-fEdge), -(fHeight+fEdge), fDepth-fEdge);
glVertex3f(-(fWidth-fEdge), -(fHeight+fEdge), -(fDepth-fEdge));
glVertex3f(fWidth-fEdge, -(fHeight+fEdge), -(fDepth-fEdge));
glVertex3f(fWidth-fEdge, -(fHeight+fEdge), fDepth-fEdge);
// Left
glNormal3f(1.0f, 0.0f, 0.0f);
glVertex3f(fWidth, fHeight, fDepth);
glVertex3f(fWidth, -fHeight, fDepth);
glVertex3f(fWidth, -fHeight, -fDepth);
glVertex3f(fWidth, fHeight, -fDepth);
// Right
glNormal3f(-1.0f, 0.0f, 0.0f);
glVertex3f(-fWidth, fHeight, fDepth);
glVertex3f(-fWidth, fHeight, -fDepth);
glVertex3f(-fWidth, -fHeight, -fDepth);
glVertex3f(-fWidth, -fHeight, fDepth);
// Top Bevels
vvVertices[0][0] = fWidth-fEdge;
vvVertices[0][1] = fHeight+fEdge;
vvVertices[0][2] = fDepth-fEdge;
vvVertices[1][0] = -(fWidth-fEdge);
vvVertices[1][1] = fHeight+fEdge;
vvVertices[1][2] = fDepth-fEdge;
vvVertices[2][0] = -fWidth;
vvVertices[2][1] = fHeight;
vvVertices[2][2] = fDepth;
calcNormal(vvVertices,vNormal);
glNormal3fv(vNormal);
glVertex3f(fWidth-fEdge, fHeight+fEdge, fDepth-fEdge);
glVertex3f(-(fWidth-fEdge), fHeight+fEdge, fDepth-fEdge);
glVertex3f(-fWidth, fHeight, fDepth);
glVertex3f(fWidth, fHeight, fDepth);
vvVertices[0][0] = fWidth;
vvVertices[0][1] = fHeight;
vvVertices[0][2] = -fDepth;
vvVertices[1][0] = fWidth-fEdge;
vvVertices[1][1] = fHeight+fEdge;
vvVertices[1][2] = -(fDepth-fEdge);
vvVertices[2][0] = fWidth-fEdge;
vvVertices[2][1] = fHeight+fEdge;
vvVertices[2][2] = fDepth-fEdge;
calcNormal(vvVertices,vNormal);
glNormal3fv(vNormal);
glVertex3f(fWidth, fHeight, -fDepth);
glVertex3f(fWidth-fEdge, fHeight+fEdge, -(fDepth-fEdge));
glVertex3f(fWidth-fEdge, fHeight+fEdge, fDepth-fEdge);
glVertex3f(fWidth, fHeight, fDepth);
vvVertices[0][0] = fWidth;
vvVertices[0][1] = fHeight;
vvVertices[0][2] = -fDepth;
vvVertices[1][0] = -fWidth;
vvVertices[1][1] = fHeight;
vvVertices[1][2] = -fDepth;
vvVertices[2][0] = -(fWidth-fEdge);
vvVertices[2][1] = fHeight+fEdge;
vvVertices[2][2] = -(fDepth-fEdge);
calcNormal(vvVertices,vNormal);
glNormal3fv(vNormal);
glVertex3f(fWidth, fHeight, -fDepth);
glVertex3f(-fWidth, fHeight, -fDepth);
glVertex3f(-(fWidth-fEdge), fHeight+fEdge, -(fDepth-fEdge));
glVertex3f(fWidth-fEdge, fHeight+fEdge, -(fDepth-fEdge));
vvVertices[0][0] = -fWidth;
vvVertices[0][1] = fHeight;
vvVertices[0][2] = fDepth;
vvVertices[1][0] = -(fWidth-fEdge);
vvVertices[1][1] = fHeight+fEdge;
vvVertices[1][2] = fDepth-fEdge;
vvVertices[2][0] = -(fWidth-fEdge);
vvVertices[2][1] = fHeight+fEdge;
vvVertices[2][2] = -(fDepth-fEdge);
calcNormal(vvVertices,vNormal);
glNormal3fv(vNormal);
glVertex3f(-fWidth, fHeight, fDepth);
glVertex3f(-(fWidth-fEdge), fHeight+fEdge, fDepth-fEdge);
glVertex3f(-(fWidth-fEdge), fHeight+fEdge, -(fDepth-fEdge));
glVertex3f(-fWidth, fHeight, -fDepth);
// Bottom Bevels
vvVertices[0][0] = fWidth;
vvVertices[0][1] = -fHeight;
vvVertices[0][2] = fDepth;
vvVertices[1][0] = -fWidth;
vvVertices[1][1] = -fHeight;
vvVertices[1][2] = fDepth;
vvVertices[2][0] = -(fWidth-fEdge);
vvVertices[2][1] = -(fHeight+fEdge);
vvVertices[2][2] = fDepth-fEdge;
calcNormal(vvVertices,vNormal);
glNormal3fv(vNormal);
glVertex3f(fWidth, -fHeight, fDepth);
glVertex3f(-fWidth, -fHeight, fDepth);
glVertex3f(-(fWidth-fEdge), -(fHeight+fEdge), fDepth-fEdge);
glVertex3f(fWidth-fEdge, -(fHeight+fEdge), fDepth-fEdge);
vvVertices[0][0] = fWidth;
vvVertices[0][1] = -fHeight;
vvVertices[0][2] = fDepth;
vvVertices[1][0] = fWidth-fEdge;
vvVertices[1][1] = -(fHeight+fEdge);
vvVertices[1][2] = fDepth-fEdge;
vvVertices[2][0] = fWidth-fEdge;
vvVertices[2][1] = -(fHeight+fEdge);
vvVertices[2][2] = -(fDepth-fEdge);
calcNormal(vvVertices,vNormal);
glNormal3fv(vNormal);
glVertex3f(fWidth, -fHeight, fDepth);
glVertex3f(fWidth-fEdge, -(fHeight+fEdge), fDepth-fEdge);
glVertex3f(fWidth-fEdge, -(fHeight+fEdge), -(fDepth-fEdge));
glVertex3f(fWidth, -fHeight, -fDepth);
vvVertices[0][0] = fWidth-fEdge;
vvVertices[0][1] = -(fHeight+fEdge);
vvVertices[0][2] = -(fDepth-fEdge);
vvVertices[1][0] = -(fWidth-fEdge);
vvVertices[1][1] = -(fHeight+fEdge);
vvVertices[1][2] = -(fDepth-fEdge);
vvVertices[2][0] = -fWidth;
vvVertices[2][1] = -fHeight;
vvVertices[2][2] = -fDepth;
calcNormal(vvVertices,vNormal);
glNormal3fv(vNormal);
glVertex3f(fWidth-fEdge, -(fHeight+fEdge), -(fDepth-fEdge));
glVertex3f(-(fWidth-fEdge), -(fHeight+fEdge), -(fDepth-fEdge));
glVertex3f(-fWidth, -fHeight, -fDepth);
glVertex3f(fWidth, -fHeight, -fDepth);
vvVertices[0][0] = -fWidth;
vvVertices[0][1] = -fHeight;
vvVertices[0][2] = -fDepth;
vvVertices[1][0] = -(fWidth-fEdge);
vvVertices[1][1] = -(fHeight+fEdge);
vvVertices[1][2] = -(fDepth-fEdge);
vvVertices[2][0] = -(fWidth-fEdge);
vvVertices[2][1] = -(fHeight+fEdge);
vvVertices[2][2] = fDepth-fEdge;
calcNormal(vvVertices,vNormal);
glNormal3fv(vNormal);
glVertex3f(-fWidth, -fHeight, -fDepth);
glVertex3f(-(fWidth-fEdge), -(fHeight+fEdge), -(fDepth-fEdge));
glVertex3f(-(fWidth-fEdge), -(fHeight+fEdge), fDepth-fEdge);
glVertex3f(-fWidth, -fHeight, fDepth);
glEnd();
}
///////////////////////////////////////////////////////////////////////////////
// Draw the Wheel (actually just a disk)
void DrawWheel()
{
GLfloat x,y,z,angle; // Storage for coordinates and angles
GLfloat fStep = (float)PI/4.0f;
GLfloat fWidth = 3.0f;
GLfloat fSize = 10.0f;
GLfloat vNormal[3];
// Dark Grey Wheels
glRGB(198, 198, 198);
// Center of fan is at the origin
for(z = 0.0f; z <= fWidth; z+= fWidth)
{
if(z > 0.0)
{
glFrontFace(GL_CW); // Switch to clock wise for back
glNormal3f(0.0f, 0.0f, 1.0f);
}
else
glNormal3f(0.0f, 0.0f, -1.0f);
// Begin a new triangle fan to cover the bottom
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0f, 0.0f, z);
for(angle = 0.0f; angle < (2.0f*(float)PI); angle += fStep)
{
// Calculate x and y position of the next vertex
x = fSize*fsin(angle);
y = fSize*fcos(angle);
// Specify the next vertex for the triangle fan
glVertex3f(x, y, z);
}
// Done drawing the fan that covers the bottom
glEnd();
}
glFrontFace(GL_CCW); // Switch back to counter clock wise
for(angle = 0.0f; angle < 3.0f*(float)PI; angle += fStep)
{
x = fSize*fsin(angle);
y = fSize*fcos(angle);
glBegin(GL_QUADS);
vNormal[0] = x;
vNormal[1] = y;
vNormal[2] = 0.0f;
ReduceToUnit(vNormal);
glNormal3fv(vNormal);
glVertex3f(x, y, 0.0f);
glVertex3f(x, y, fWidth);
x = fSize*fsin(angle+fStep);
y = fSize*fcos(angle+fStep);
vNormal[0] = x;
vNormal[1] = y;
vNormal[2] = fWidth;
ReduceToUnit(vNormal);
glNormal3fv(vNormal);
glVertex3f(x, y, fWidth);
glVertex3f(x, y, 0.0f);
glEnd();
}
}
///////////////////////////////////////////////////////////////////////////////
// Draw the Tank. This consists of just a box and four "wheels"
void DrawTank(void)
{
// Position the tank
glPushMatrix();
// Place and orient tank
glTranslatef(tankPos.xPos, 10.0f, tankPos.zPos);
glRotatef(dRadToDeg(tankPos.radsFromEast+((float)PI/2.0f)), 0.0f, 1.0f, 0.0f);
// Draw body of tank
glRGB(255,255,0);
glPushMatrix();
auxSolidBox(25.0f, 11.0f, 40.0f);
glPopMatrix();
// Draw the wheels
glPushMatrix();
// Orient them in the correct direction
glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
glTranslatef(15.0f, 0.0f, 12.0f);
DrawWheel();
glTranslatef(-30.0f, 0.0f, 0.0f);
DrawWheel();
glTranslatef(0.0f, 0.0f, -25.0f);
DrawWheel();
glTranslatef(30.0f, 0.0f, 0.0f);
DrawWheel();
glPopMatrix();
glPopMatrix();
}
//////////////////////////////////////////////////////////////////////////////
// Draw the Robot. A Box with cone legs and Sphere eyes
void DrawRobot(void)
{
// Position the robot
glPushMatrix();
// Center is 30 above the ground
glTranslatef(robotPos.xPos, 30.0f, robotPos.zPos);
glRotatef(dRadToDeg(robotPos.radsFromEast+((float)PI/2.0f)), 0.0f, 1.0f, 0.0f);
// Body Color
glRGB(255,255,0);
auxSolidBox(20.0f, 30.0f, 10.0f);
// Eye Color
glRGB(0,255,255);
glTranslatef(5.0f, 10.0f, 5.0f);
auxSolidSphere(3.0f);
glTranslatef(-10.0f, 0.0f, 0.0f);
auxSolidSphere(3.0f);
// Leg color
glRGB(255,0,255);
glTranslatef(0.0f, -26.0f, -5.0f);
auxSolidCylinder(3.0f, 15.0f);
glTranslatef(10.0f, 0.0f, 0.0f);
auxSolidCylinder(3.0f, 15.0f);
glPopMatrix();
}