Here’s the whole thing…you will porb have to playaround with it a bit tho.
//render.cpp
//
#include <windows.h>
#include <process.h>
#include <math.h>
#include <winuser.h>
#include <fstream.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glut.h>
#include “common.h”
//#include “resource.h”
// Variables shared between files (initialized in Tankx.c)
extern HDC hDC; // Private GDI Device context
extern HWND hMainWindow; // Main Application window
extern CRITICAL_SECTION csThreadSafe; // Critical section
extern struct RENDER_STATE rsRenderData; // Communication between threads
extern LARGE_INTEGER timerFrequency; // Timer Frequency
// Locally global variables
static HGLRC hRC = NULL; // Permenant Rendering context
GLUquadricObj *quadric; // Quadric object
static LARGE_INTEGER lastTime; // Time of last movement
GLfloat x,y,z;
GLfloat normal[3];
BOOLEAN launch = FALSE;
int triangle_count, vert_count, norm_count, array_count;
float vertx_array[30000][3];
float triangle_array[80000][3];
float norm_array[40000][3];
float temp_array[3][3];
float elevation_array[128];
int v, w;
struct CAMERA
{
float position[3];
float orientation[3];
} cameraData;
// Light values and coordinates
GLfloat LightSpecular[]={1.0f, 1.0f, 1.0f, 1.0f}; // white
GLfloat LightAmbient[]={0.4f, 0.4f, 0.45f, 0.4f};
GLfloat LightDiffuse[]={0.5f, 0.5f, 0.5f, 1.0f};
// light 0
//GLfloat LightSpecular0[]={1.0f, 0.0f, 0.0f, 1.0f}; // red
//GLfloat LightDiffuse0[]={1.0f, 0.0f, 0.0f, 1.0f}; //red
//GLfloat LightPosition0[]={20.0f, 10.0f, -5.0f, 1.0f};
// light 1
GLfloat LightSpecular2[]={1.0f, 1.0f, 1.0f, 1.0f}; //white
GLfloat LightDiffuse2[]={1.0f, 1.0f, 1.0f, 1.0f}; //white
GLfloat LightPosition2[]={20.0f, 10.0f, -60.0f, 1.0f};
// light 3
GLuint grid, lights, light_setup, mesh, floor_and_lights;
// Convert degrees to radians
#define DEGTORAD(x) ((x)*0.017453292519943296)
// Set Pixel Format function - forward declaration
void SetDCPixelFormat(HDC hDC);
// forward declaration for BuildLists function
void BuildLists(void);
void Load_Vertex_Array(void);
void Load_Normals_Array(void);
//*********************************************************************
// Reduces a normal vector specified as a set of three coordinates,
// to a unit normal vector of length one.
void ReduceToUnit(float vector[3])
{
float length;
// Calculate the length of the vector
length = (float)sqrt((vector[0]*vector[0]) +
(vector[1]*vector[1]) +
(vector[2]*vector[2]));
// Keep the program from blowing up by providing an exceptable
// value for vectors that may calculated too close to zero.
if(length == 0.0f)
length = 1.0f;
// Dividing each element by the length will result in a
// unit normal vector.
vector[0] /= length;
vector[1] /= length;
vector[2] /= length;
}
//**************************************************************************
// Points p1, p2, & p3 specified in counter clock-wise order
void calcNormal(float v[3][3], float out[3])
{
float v1[3],v2[3];
static const int x = 0;
static const int y = 1;
static const int z = 2;
// Calculate two vectors from the three points
v1[x] = v[0][x] - v[1][x];
v1[y] = v[0][y] - v[1][y];
v1[z] = v[0][z] - v[1][z];
v2[x] = v[1][x] - v[2][x];
v2[y] = v[1][y] - v[2][y];
v2[z] = v[1][z] - v[2][z];
// Take the cross product of the two vectors to get
// the normal vector which will be stored in out
out[x] = v1[y]*v2[z] - v1[z]*v2[y];
out[y] = v1[z]*v2[x] - v1[x]*v2[z];
out[z] = v1[x]*v2[y] - v1[y]*v2[x];
// Normalize the vector (shorten length to one)
ReduceToUnit(out);
}
//****************************************************************************
void Load_Vertex_Array()
{
// load an array of vertices
y=0.0f;
z=0.0f;
// float r;
// int x_int;
int index=0;
for (int i=0;i<=200;i++)
{
for(x=0; x<=36;x=x+0.5f)
{
vertx_array[index][0]=(x);
vertx_array[index][1]=(y);
vertx_array[index][2]=(z);
index++;
}
z=z-0.5f;
}
vert_count=index;
// now use the array of vertices to create an array of “triangles”;
int first_offset = 0;
int second_offset = 73;
index=0;
for (int q = 0; q<=200; q++)
{
for (i=1;i<=64;i++)
{
// first triangle
//row-1 2
triangle_array[index][0]=vertx_array[i + first_offset][0];
triangle_array[index][1]=vertx_array[i + first_offset][1];
triangle_array[index][2]=vertx_array[i + first_offset][2];
index++;
//row-2 2
triangle_array[index][0]=vertx_array[i + second_offset + 1][0];
triangle_array[index][1]=vertx_array[i + second_offset + 1][1];
triangle_array[index][2]=vertx_array[i + second_offset + 1][2];
index++;
//row-2 1
triangle_array[index][0]=vertx_array[i + second_offset][0];
triangle_array[index][1]=vertx_array[i + second_offset][1];
triangle_array[index][2]=vertx_array[i + second_offset][2];
index++;
triangle_count++;
// second triangle
// row-1 2
triangle_array[index][0]=vertx_array[i + first_offset][0];
triangle_array[index][1]=vertx_array[i + first_offset][1];
triangle_array[index][2]=vertx_array[i + first_offset][2];
index++;
//row-1 3
triangle_array[index][0]=vertx_array[i + first_offset + 1][0];
triangle_array[index][1]=vertx_array[i + first_offset + 1][1];
triangle_array[index][2]=vertx_array[i + first_offset + 1][2];
index++;
//row-2 2
triangle_array[index][0]=vertx_array[i + second_offset + 1][0];
triangle_array[index][1]=vertx_array[i + second_offset + 1][1];
triangle_array[index][2]=vertx_array[i + second_offset + 1][2];
index++;
triangle_count++;
}
first_offset = second_offset;
second_offset = second_offset + 73;
array_count=index;
}
}
//**************************************************************************
void Load_Normals_Array()
{
int sub=0;
norm_count=0;
for (int i = 0; i <=triangle_count;i++) //(i+3))
{
temp_array[0][0]=triangle_array[sub][0];
temp_array[0][1]=triangle_array[sub][1];
temp_array[0][2]=triangle_array[sub][2];
sub++;
temp_array[1][0]=triangle_array[sub][0];
temp_array[1][1]=triangle_array[sub][1];
temp_array[1][3]=triangle_array[sub][2];
sub++;
temp_array[2][0]=triangle_array[sub][0];
temp_array[2][1]=triangle_array[sub][1];
temp_array[2][2]=triangle_array[sub][2];
sub++;
calcNormal(temp_array, normal);
// if (normal[0]<0)
// normal[0]=normal[0]*-1;
if (normal[1]<0)
normal[1]=normal[1]*-1;
// if (normal[2]<0)
// normal[2]=normal[2]*-1;
norm_array[norm_count][0]=normal[0];
norm_array[norm_count][1]=normal[1];
norm_array[norm_count][2]=normal[2];
norm_count++;
}
}
//**************************************************************************
// Update the position of the camera.This function can vary wildly depending
// on how motion is acheived. For a flight sim, motion will always be along the
// viewer’s Z axis. For a first person walking around, motion will always be in
// the XY plane. Even if the camera tilts down (to look at the ground), or up
// (to look at the sky), the player still only moves along the XY plane.
// This function must be called continuously, or the timed motion will not work.
// If this function is called only when a key press is made, then the time between
// calls will be huge and the camera will ‘rocket’ to the new location with each key
// press
void UpdatePosition(struct CAMERA *pCamera)
{
float fLinearVelocity = 0.0f;
float fAngularVelocityY = 0.0f;
float fAngularVelocityX = 0.0f;
float fAngularVelocityZ = 0.0f;
float fTime,fXDelta,fAngle, fZDelta;
float elevation = 0.0f;
LARGE_INTEGER currentTime;
// Keyboard Input
// Check for forward or backwards Motion
if(GetAsyncKeyState(VK_UP))
fLinearVelocity = 2.0f;
if(GetAsyncKeyState(VK_DOWN))
fLinearVelocity = -2.0f;
// check for elevation
if(GetAsyncKeyState(VK_NEXT))
elevation = 0.25f;
if(GetAsyncKeyState(VK_PRIOR))
elevation = -0.25f;
// Check for spin left/right (Y Axis rotation)
if(GetAsyncKeyState(VK_LEFT))
fAngularVelocityY = -25.0f;
if(GetAsyncKeyState(VK_RIGHT))
fAngularVelocityY = 25.0f;
if(GetAsyncKeyState(VK_SPACE))
fAngularVelocityY = fAngularVelocityY * -1;
// Check for looking up and down
if(GetAsyncKeyState(0x41)) // A key
fAngularVelocityX = -5.0f;
if(GetAsyncKeyState(0x5a)) // Z key
fAngularVelocityX = 5.0f;
// Adjust position and orientation. Get the time since the last
// check. If the velocity = 0 (no keypress or mouse movement)
// then the motion will be nil...
// D = vt
QueryPerformanceCounter(¤tTime);
fTime = (float)(currentTime.QuadPart - lastTime.QuadPart)/
(float)timerFrequency.QuadPart;
lastTime = currentTime;
// Update Rotation angles (clamp the X rotation)
fAngle = fTime * fAngularVelocityX;
fAngle += pCamera->orientation[0];
if((fAngle < 90.0f) && (fAngle > -90.0f))
pCamera->orientation[0] = fAngle;
pCamera->orientation[1] += fTime * fAngularVelocityY;
// Update linear position
fTime = fTime * fLinearVelocity;
fXDelta = fTime * (float)(sin(DEGTORAD(pCamera->orientation[1])));
fXDelta += pCamera->position[0];
fZDelta = fTime * (float)(cos(DEGTORAD(pCamera->orientation[1])));
fZDelta += pCamera->position[2];
pCamera->position[1] += elevation;
pCamera->position[0] = fXDelta;
pCamera->position[2] = fZDelta;
// Halt the camera at the boundaries of the Virtual World.
if(pCamera->position[0] > 200.0f)
pCamera->position[0] = 200.0f;
if(pCamera->position[0] < -200.0f)
pCamera->position[0] = -200.0f;
if(pCamera->position[2] > 200.0f)
pCamera->position[2] = 200.0f;
if(pCamera->position[2] < -200.0f)
pCamera->position[2] = -200.0f;
}
//***********************************************************************
// Reset Viewport and viewing volume transormation
void ChangeSize(GLsizei w, GLsizei h)
{
GLfloat fAspect;
// Prevent a divide by zero
if(h == 0)
h = 1;
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
// Reset coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
fAspect = (float)w/(float)h;
gluPerspective(45.0, fAspect, 0.1, 650.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
//*************************************************************************
// Resets the viewport. This function is called when the window is resized
void ResetViewport()
{
// Get the Window dimensions
RECT rect;
GetClientRect(hMainWindow, &rect);
ChangeSize(rect.right, rect.bottom);
}
//****************************************************************
void SetupRC(void)
{
SetDCPixelFormat(hDC);
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glDepthRange(0.0f, 1.0f);
glPointSize(1.0);
glLineWidth(1.0);
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glPolygonMode(GL_FRONT, GL_LINE);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_POLYGON_SMOOTH);
glShadeModel(GL_SMOOTH);
glFrontFace(GL_CCW);
glEnable(GL_CULL_FACE);
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
// lighting
glEnable(GL_LIGHTING);
// glLightfv(GL_LIGHT0, GL_SPECULAR, LightSpecular0);
// glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse0);
glLightfv(GL_LIGHT2, GL_SPECULAR, LightSpecular2);
glLightfv(GL_LIGHT2, GL_DIFFUSE, LightDiffuse2);
// material
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glColorMaterial(GL_FRONT, GL_SPECULAR);
glEnable(GL_COLOR_MATERIAL);
// glMaterialfv(GL_FRONT, GL_DIFFUSE, LightDiffuse);
// glMaterialfv(GL_FRONT, GL_SPECULAR, LightSpecular);
glMateriali(GL_FRONT,GL_SHININESS, 128);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, LightAmbient);
glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, TRUE);
// glEnable(GL_NORMALIZE);
// display lists
grid =glGenLists(1);
lights =glGenLists(2);
light_setup =glGenLists(3);
mesh =glGenLists(4);
//Load_Elevation_Array();
Load_Vertex_Array();
Load_Normals_Array();
ofstream outfile(“statistics.txt”);
outfile <<" vertices count = “<<vert_count<<’
’
<<” triangle count = “<<triangle_count<<’
’
<<” array count = "<<array_count<<’
’
<<" normal count = "<<norm_count<<'
’
<<"norm 0 “<<norm_array[0][0]<<” “<<norm_array[0][1]<<” "<<norm_array[0][2] <<’
’
<<"norm 1000 “<<norm_array[1000][0]<<” “<<norm_array[1000][1]<<” "<<norm_array[1000][2] <<’
’
<<"norm 1001 “<<norm_array[1001][0]<<” “<<norm_array[1001][1]<<” "<<norm_array[1001][2] <<’
’
<<"norm 1002 “<<norm_array[1002][0]<<” “<<norm_array[1002][1]<<” "<<norm_array[1002][2] <<’
’
<<"norm 1003 “<<norm_array[1003][0]<<” “<<norm_array[1003][1]<<” "<<norm_array[1003][2] <<’
’
<<"norm 2000 “<<norm_array[2000][0]<<” “<<norm_array[2000][1]<<” “<<norm_array[2000][2] <<’
’
<<triangle_array[0][0]<<” “<<triangle_array[0][1]<<” “<<triangle_array[0][2] <<’
’
<<” "<<triangle_array[1][0]<< " “<< triangle_array[1][1]<<” “<<triangle_array[1][2]<<’
’
<<” “<<triangle_array[2][0]<<” “<<triangle_array[2][1] <<” "<<triangle_array[2][2]<<’
’
<< " “<< triangle_array[3][0]<<” “<<triangle_array[3][1]<<” “<<triangle_array[3][2]<<’
’
<<” “<<triangle_array[4][0] <<” "<<triangle_array[4][1]<< " “<< triangle_array[4][2]<<’
’
<<” “<<triangle_array[5][0] <<” "<<triangle_array[5][1]<< " “<< triangle_array[5][2]<<’
’
<<” “<<triangle_array[6][0] <<” "<<triangle_array[6][1]<< " “<< triangle_array[6][2]<<’
’
<<” “<<triangle_array[7][0] <<” "<<triangle_array[7][1]<< " “<< triangle_array[7][2]<<’
’
<<” “<<triangle_array[8][0] <<” "<<triangle_array[8][1]<< " “<< triangle_array[8][2]<<’
’
<<” “<<triangle_array[9][0] <<” "<<triangle_array[9][1]<< " "<< triangle_array[9][2]<<’
’
;
BuildLists();
// quads
quadric=gluNewQuadric();
gluQuadricNormals(quadric, GLU_SMOOTH);
cameraData.position[0] = 0.0f;
cameraData.position[1] = -1.0f;
cameraData.position[2] = -3.0f;
cameraData.orientation[0] = 0.0f;
cameraData.orientation[1] = 0.0f;
cameraData.orientation[2] = 0.0f;
}
//**************************************************************************
void BuildLists()
{
//
grid=1;
glNewList(grid,GL_COMPILE);
glBegin(GL_LINES);
for (z=0.0f; z<=150.0f; z+=5.0f)
{
// x axis
glColor3f(0.0f, 1.0f, 0.0f); // green
glVertex3f(-150.0f, 0.0f, z); glVertex3f(0.0f, 0.0f, z); // x axis
glColor3f(1.0f, 1.0f, 1.0f); // white
glVertex3f(0.0f, 0.0f, z); glVertex3f(150.0f, 0.0f, z); // x axis
}
for (z=0.0f; z<=150.0f; z+=5.0f)
{
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.0f, -150.0f, z); glVertex3f(0.0f, 0.0f, z); // y axis
glColor3f(1.0f, 1.0f, 1.0f); // white
glVertex3f(0.0f, 0.0f, z); glVertex3f(0.0f, 150.0f, z); // y axis
}
for (z=0.0f; z>=-150.0f; z-=5.0f)
{
glColor3f(1.0f, 0.6f, 0.1f); // orange
glVertex3f(0.0f, -150.0f, z); glVertex3f(0.0f, 0.0f, z); // y axis
glColor3f(1.0f, 0.0f, 0.5f); // pink
glVertex3f(0.0f, 0.0f, z); glVertex3f(0.0f, 150.0f, z); // y axis
}
glEnd();
// 3 major axis centered on 0,0,0
glBegin(GL_LINES);
glColor3f(1.0f, 1.0f, 1.0f); // white
glVertex3f(-150.0f, 0.0f, 0.0f); glVertex3f(150.0f, 0.0f, 0.0f); // x axis
glVertex3f(0.0f, -150.0f, 0.0f); glVertex3f(0.0f, 150.0f, 0.0f); // y axis
glVertex3f(0.0f, 0.0f, 150.0f); glVertex3f(0.0f, 0.0f, -150.0f); // z axis
glEnd();
glEndList();
glNewList(lights,GL_COMPILE);
quadric=gluNewQuadric();
gluQuadricNormals(quadric, GLU_SMOOTH);
/*
//red light
glColorMaterial(GL_FRONT, GL_EMISSION);
glColor3f(1.0f, 0.0f, 0.0f);
glPushMatrix();
glTranslatef(LightPosition0[0], LightPosition0[1], LightPosition0[2]);
gluSphere(quadric, 1.0, 30, 30);
glPopMatrix();
*/
//white light
glColorMaterial(GL_FRONT, GL_EMISSION);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glPushMatrix();
glTranslatef(LightPosition2[0], LightPosition2[1], LightPosition2[2]);
gluSphere(quadric, 1.0, 20, 20);
glPopMatrix();
glEndList();
glNewList(light_setup,GL_COMPILE);
glPushMatrix();
// glLightfv(GL_LIGHT0, GL_POSITION, LightPosition0); // red
glLightfv(GL_LIGHT2, GL_POSITION, LightPosition2); // white
// glEnable(GL_LIGHT0);
glEnable(GL_LIGHT2);
glPopMatrix();
glEndList();
glNewList(mesh,GL_COMPILE);
glBegin(GL_TRIANGLES);
glColorMaterial(GL_FRONT, GL_DIFFUSE);
int w = 0;
for (int i=0;i<=25000;i=i+3)
{
glColor4f(0.32f, 0.126f, 0.03f, 0.1f);
glNormal3fv(norm_array[w]);
glVertex3fv(triangle_array[i]);
glVertex3fv(triangle_array[i+1]);
glVertex3fv(triangle_array[i+2]);
w++;
}
glEnd();
glEndList();
}
//************************************************************************
//
void RenderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
glMatrixMode(GL_MODELVIEW);
glCallList(grid); // grid
glCallList(light_setup); // enable lights
glCallList(lights); // light spheres
glCallList(mesh); // mesh
glFlush();
}
//********************************************************************
// Check rendering states and make appropriate adjustements. Returns true on
// termination flag.
BOOL CheckStates()
{
BOOL bRet = FALSE;
// Is it time to leave or anything else
EnterCriticalSection(&csThreadSafe);
if( rsRenderData.bModifyFlag)
{
// Flag set to terminate
if(rsRenderData.bTerminate)
bRet = TRUE;
// Window resized
if(rsRenderData.bResize)
ResetViewport();
// Reset the modify flag and exit
rsRenderData.bModifyFlag = FALSE;
}
// Increment frame count
rsRenderData.uiFrames++;
LeaveCriticalSection(&csThreadSafe);
return bRet;
}
//******************************************************************
// Rendering Thread Entry Point
void RenderingThreadEntryPoint(void *pVoid)
{
// Setup the rendering context
SetupRC();
// QueryPerformanceCounter(&lastTime);
// Main loop for rendering
while(1)
{
// Check rendering state info, terminate if flagged
if(CheckStates())
break;
UpdatePosition(&cameraData);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(cameraData.orientation[0], 1.0f, 0.0f, 0.0f); // look up, down
glRotatef(cameraData.orientation[1], 0.0f, 1.0f, 0.0f); // turn
glRotatef(cameraData.orientation[2], 0.0f, 0.0f, 1.0f); // advance/retreat
glTranslatef(-cameraData.position[0],cameraData.position[1], cameraData.position[2]);
RenderScene();
// Swap buffers
SwapBuffers(hDC);
}
// Do any necessary cleanup and terminate
glDeleteLists(1, 4);
gluDeleteQuadric(quadric);
// Finally, shut down OpenGL Rendering context
wglMakeCurrent(hDC, NULL);
wglDeleteContext(hRC);
_endthread(); // Terminate the thread nicely
}