saving pulsar from school project (reformatting machine)
This commit is contained in:
845
graphics.c
Normal file
845
graphics.c
Normal file
@@ -0,0 +1,845 @@
|
||||
|
||||
/* Derived from scene.c in the The OpenGL Programming Guide */
|
||||
/* Keyboard and mouse rotation taken from Swiftless Tutorials #23 Part 2 */
|
||||
/* http://www.swiftless.com/tutorials/opengl/camera2.html */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "graphics.h"
|
||||
|
||||
extern void update();
|
||||
extern void collisionResponse();
|
||||
extern void buildDisplayList();
|
||||
extern void mouse(int, int, int, int);
|
||||
extern void draw2D();
|
||||
extern void quit();
|
||||
|
||||
|
||||
/* flags used to control the appearance of the image */
|
||||
int lineDrawing = 0; // draw polygons as solid or lines
|
||||
int lighting = 1; // use diffuse and specular lighting
|
||||
int smoothShading = 1; // smooth or flat shading
|
||||
int textures = 0;
|
||||
|
||||
/* texture data */
|
||||
GLubyte Image[64][64][4];
|
||||
GLuint textureID[1];
|
||||
|
||||
/* viewpoint coordinates */
|
||||
float vpx = -50.0, vpy = -50.0, vpz = -50.0;
|
||||
float oldvpx, oldvpy, oldvpz;
|
||||
|
||||
/* mouse direction coordiates */
|
||||
float mvx = 0.0, mvy = 45.0, mvz = 0.0;
|
||||
|
||||
/* stores current mouse position value */
|
||||
float oldx, oldy;
|
||||
|
||||
/* location for the light source (the sun), the first three
|
||||
values are the x,y,z coordinates */
|
||||
GLfloat lightPosition[] = {0.0, 49.0, 0.0, 0.0};
|
||||
/* location for light source that is kept at viewpoint location */
|
||||
GLfloat viewpointLight[] = {-50.0, -50.0, -50.0, 1.0};
|
||||
|
||||
/* sky cube size */
|
||||
float skySize;
|
||||
|
||||
/* screen dimensions */
|
||||
int screenWidth = 1024;
|
||||
int screenHeight = 768;
|
||||
|
||||
/* command line flags */
|
||||
int flycontrol = 1; // allow viewpoint to move in y axis when 1
|
||||
int displayAllCubes = 0; // draw all of the cubes in the world when 1
|
||||
int testWorld = 0; // sample world for timing tests
|
||||
int fps = 0; // turn on frame per second output
|
||||
int netClient = 0; // network client flag, is client when = 1
|
||||
int netServer = 0; // network server flag, is server when = 1
|
||||
|
||||
/* list of cubes to display */
|
||||
int displayList[MAX_DISPLAY_LIST][3];
|
||||
int displayCount = 0; // count of cubes in displayList[][]
|
||||
|
||||
/* list of mobs - number of mobs, xyz values and rotation about y */
|
||||
float mobPosition[MOB_COUNT][6];
|
||||
/* visibility of mobs, 0 not drawn, 1 drawn */
|
||||
short mobVisible[MOB_COUNT];
|
||||
|
||||
/* list of players - number of mobs, xyz values and rotation about y */
|
||||
float playerPosition[MOB_COUNT][4];
|
||||
/* visibility of players, 0 not drawn, 1 drawn */
|
||||
short playerVisible[MOB_COUNT];
|
||||
|
||||
/* flag indicating the user wants the cube in front of them removed */
|
||||
int space = 0;
|
||||
/* flag indicates if map is to be printed */
|
||||
int displayMap = 1;
|
||||
|
||||
/* functions draw 2D images */
|
||||
void draw2Dline(int, int, int, int, int);
|
||||
void draw2Dbox(int, int, int, int);
|
||||
void draw2Dtriangle(int, int, int, int, int, int);
|
||||
void set2Dcolour(float []);
|
||||
|
||||
/***************/
|
||||
|
||||
int isMobVisible(int mob) {
|
||||
return mobVisible[mob];
|
||||
}
|
||||
|
||||
int getMapState() {
|
||||
return displayMap;
|
||||
}
|
||||
|
||||
/* player control functions */
|
||||
/* set all player location, rotation, and visibility values to zero */
|
||||
void initPlayerArray() {
|
||||
int i;
|
||||
for (i=0; i<MOB_COUNT; i++) {
|
||||
playerPosition[i][0] = 0.0;
|
||||
playerPosition[i][1] = 0.0;
|
||||
playerPosition[i][2] = 0.0;
|
||||
playerPosition[i][3] = 0.0;
|
||||
playerVisible[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* create player with identifier "number" at x,y,z with */
|
||||
/* heading of rotx, roty, rotz */
|
||||
void createPlayer(int number, float x, float y, float z, float playerroty) {
|
||||
if (number >= PLAYER_COUNT) {
|
||||
printf("ERROR: player number greater than %d\n", PLAYER_COUNT);
|
||||
exit(1);
|
||||
}
|
||||
playerPosition[number][0] = x;
|
||||
playerPosition[number][1] = y;
|
||||
playerPosition[number][2] = z;
|
||||
playerPosition[number][3] = playerroty;
|
||||
playerVisible[number] = 1;
|
||||
}
|
||||
|
||||
/* move player to a new position xyz with rotation rotx,roty,rotz */
|
||||
void setPlayerPosition(int number, float x, float y, float z, float playerroty){
|
||||
if (number >= PLAYER_COUNT) {
|
||||
printf("ERROR: player number greater than %d\n", PLAYER_COUNT);
|
||||
exit(1);
|
||||
}
|
||||
playerPosition[number][0] = x;
|
||||
playerPosition[number][1] = y;
|
||||
playerPosition[number][2] = z;
|
||||
playerPosition[number][3] = playerroty;
|
||||
}
|
||||
|
||||
/* turn off drawing for player number */
|
||||
void hidePlayer(int number) {
|
||||
if (number >= PLAYER_COUNT) {
|
||||
printf("ERROR: player number greater than %d\n", PLAYER_COUNT);
|
||||
exit(1);
|
||||
}
|
||||
playerVisible[number] = 0;
|
||||
}
|
||||
|
||||
/* turn on drawing for player number */
|
||||
void showPlayer(int number) {
|
||||
if (number >= PLAYER_COUNT) {
|
||||
printf("ERROR: player number greater than %d\n", PLAYER_COUNT);
|
||||
exit(1);
|
||||
}
|
||||
playerVisible[number] = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* mob control functions */
|
||||
/* set all mob location, rotation, and visibility values to zero */
|
||||
void initMobArray() {
|
||||
int i;
|
||||
for (i=0; i<MOB_COUNT; i++) {
|
||||
mobPosition[i][0] = 0.0;
|
||||
mobPosition[i][1] = 0.0;
|
||||
mobPosition[i][2] = 0.0;
|
||||
mobPosition[i][3] = 0.0;
|
||||
mobVisible[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* create mob with identifier "number" at x,y,z with */
|
||||
/* heading of rotx, roty, rotz */
|
||||
void createMob(int number, float x, float y, float z, float mobroty) {
|
||||
if (number >= MOB_COUNT) {
|
||||
printf("ERROR: mob number greater than %d\n", MOB_COUNT);
|
||||
exit(1);
|
||||
}
|
||||
mobPosition[number][0] = x;
|
||||
mobPosition[number][1] = y;
|
||||
mobPosition[number][2] = z;
|
||||
mobPosition[number][3] = mobroty;
|
||||
mobVisible[number] = 1;
|
||||
}
|
||||
|
||||
void mobTrajectory(int number, float mobrotx, float mobrotz) {
|
||||
mobPosition[number][4] = mobrotx;
|
||||
mobPosition[number][5] = mobrotz;
|
||||
}
|
||||
|
||||
/* move mob to a new position xyz with rotation rotx,roty,rotz */
|
||||
void setMobPosition(int number, float x, float y, float z, float mobroty){
|
||||
if (number >= MOB_COUNT) {
|
||||
printf("ERROR: mob number greater than %d\n", MOB_COUNT);
|
||||
exit(1);
|
||||
}
|
||||
mobPosition[number][0] = x;
|
||||
mobPosition[number][1] = y;
|
||||
mobPosition[number][2] = z;
|
||||
mobPosition[number][3] = mobroty;
|
||||
}
|
||||
|
||||
void getMobPosition(int number, float* x, float* y, float* z, float* roty, float* rotx, float* rotz) {
|
||||
*x = mobPosition[number][0];
|
||||
*y = mobPosition[number][1];
|
||||
*z = mobPosition[number][2];
|
||||
*roty = mobPosition[number][3];
|
||||
*rotx = mobPosition[number][4];
|
||||
*rotz = mobPosition[number][5];
|
||||
}
|
||||
|
||||
/* turn off drawing for mob number */
|
||||
void hideMob(int number) {
|
||||
if (number >= MOB_COUNT) {
|
||||
printf("ERROR: mob number greater than %d\n", MOB_COUNT);
|
||||
exit(1);
|
||||
}
|
||||
mobVisible[number] = 0;
|
||||
}
|
||||
|
||||
/* turn on drawing for mob number */
|
||||
void showMob(int number) {
|
||||
if (number >= MOB_COUNT) {
|
||||
printf("ERROR: mob number greater than %d\n", MOB_COUNT);
|
||||
exit(1);
|
||||
}
|
||||
mobVisible[number] = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* allows user to set position of the light */
|
||||
void setLightPosition(GLfloat x, GLfloat y, GLfloat z) {
|
||||
lightPosition[0] = x;
|
||||
lightPosition[1] = y;
|
||||
lightPosition[2] = z;
|
||||
glLightfv (GL_LIGHT0, GL_POSITION, lightPosition);
|
||||
}
|
||||
|
||||
/* returns current position of the light */
|
||||
GLfloat* getLightPosition() {
|
||||
return(lightPosition);
|
||||
}
|
||||
|
||||
/* functions store and return the current location of the viewpoint */
|
||||
void getViewPosition(float *x, float *y, float *z) {
|
||||
*x = vpx;
|
||||
*y = vpy;
|
||||
*z = vpz;
|
||||
}
|
||||
|
||||
void setViewPosition(float x, float y, float z) {
|
||||
oldvpx = vpx;
|
||||
oldvpy = vpy;
|
||||
oldvpz = vpz;
|
||||
vpx = x;
|
||||
vpy = y;
|
||||
vpz = z;
|
||||
}
|
||||
|
||||
/* returns the previous location of the viewpoint */
|
||||
void getOldViewPosition(float *x, float *y, float *z) {
|
||||
*x = oldvpx;
|
||||
*y = oldvpy;
|
||||
*z = oldvpz;
|
||||
}
|
||||
|
||||
/* sets the current orientation of the viewpoint */
|
||||
void setViewOrientation(float xaxis, float yaxis, float zaxis) {
|
||||
mvx = xaxis;
|
||||
mvy = yaxis;
|
||||
mvz = zaxis;
|
||||
}
|
||||
|
||||
/* returns the current orientation of the viewpoint */
|
||||
void getViewOrientation(float *xaxis, float *yaxis, float *zaxis) {
|
||||
*xaxis = mvx;
|
||||
*yaxis = mvy;
|
||||
*zaxis = mvz;
|
||||
}
|
||||
|
||||
/* add the cube at world[x][y][z] to the display list and */
|
||||
/* increment displayCount */
|
||||
void addDisplayList(int x, int y, int z) {
|
||||
displayList[displayCount][0] = x;
|
||||
displayList[displayCount][1] = y;
|
||||
displayList[displayCount][2] = z;
|
||||
displayCount++;
|
||||
if (displayCount > MAX_DISPLAY_LIST) {
|
||||
printf("You have put more items in the display list then there are\n");
|
||||
printf("cubes in the world. Set displayCount = 0 at some point.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Initialize material property and light source. */
|
||||
void init (void)
|
||||
{
|
||||
GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
|
||||
GLfloat light_diffuse[] = { 0.8, 0.8, 0.8, 1.0 };
|
||||
GLfloat light_specular[] = { 0.5, 0.5, 0.5, 1.0 };
|
||||
GLfloat light_full_off[] = {0.0, 0.0, 0.0, 1.0};
|
||||
GLfloat light_full_on[] = {1.0, 1.0, 1.0, 1.0};
|
||||
|
||||
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
|
||||
|
||||
/* if lighting is turned on then use ambient, diffuse and specular
|
||||
lights, otherwise use ambient lighting only */
|
||||
if (lighting == 1) {
|
||||
/* sun light */
|
||||
glLightfv (GL_LIGHT0, GL_AMBIENT, light_ambient);
|
||||
glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse);
|
||||
/* no specular reflection from sun, it is too distracting */
|
||||
glLightfv (GL_LIGHT0, GL_SPECULAR, light_full_off);
|
||||
} else {
|
||||
glLightfv (GL_LIGHT0, GL_AMBIENT, light_full_on);
|
||||
glLightfv (GL_LIGHT0, GL_DIFFUSE, light_full_off);
|
||||
glLightfv (GL_LIGHT0, GL_SPECULAR, light_full_off);
|
||||
}
|
||||
glLightfv (GL_LIGHT0, GL_POSITION, lightPosition);
|
||||
|
||||
/* viewpoint light */
|
||||
glLightfv (GL_LIGHT1, GL_POSITION, viewpointLight);
|
||||
glLightfv (GL_LIGHT1, GL_AMBIENT, light_ambient);
|
||||
glLightfv (GL_LIGHT1, GL_DIFFUSE, light_diffuse);
|
||||
glLightfv (GL_LIGHT1, GL_SPECULAR, light_specular);
|
||||
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.5);
|
||||
|
||||
|
||||
glEnable (GL_LIGHTING);
|
||||
glEnable (GL_LIGHT0);
|
||||
glEnable (GL_LIGHT1);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
}
|
||||
|
||||
/* draw cube in world[i][j][k] */
|
||||
void drawCube(int i, int j, int k) {
|
||||
GLfloat blue[] = {0.0, 0.0, 1.0, 1.0};
|
||||
GLfloat red[] = {1.0, 0.0, 0.0, 1.0};
|
||||
GLfloat green[] = {0.0, 1.0, 0.0, 1.0};
|
||||
GLfloat yellow[] = {1.0, 1.0, 0.0, 1.0};
|
||||
GLfloat purple[] = {1.0, 0.0, 1.0, 1.0};
|
||||
GLfloat orange[] = {1.0, 0.64, 0.0, 1.0};
|
||||
GLfloat white[] = {1.0, 1.0, 1.0, 1.0};
|
||||
GLfloat black[] = {0.0, 0.0, 0.0, 1.0};
|
||||
|
||||
GLfloat dblue[] = {0.0, 0.0, 0.5, 1.0};
|
||||
GLfloat dred[] = {0.5, 0.0, 0.0, 1.0};
|
||||
GLfloat dgreen[] = {0.0, 0.5, 0.0, 1.0};
|
||||
GLfloat dyellow[] = {0.5, 0.5, 0.0, 1.0};
|
||||
GLfloat dpurple[] = {0.5, 0.0, 0.5, 1.0};
|
||||
GLfloat dorange[] = {0.5, 0.32, 0.0, 1.0};
|
||||
|
||||
|
||||
/* select colour based on value in the world array */
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, white);
|
||||
|
||||
if (world[i][j][k] == 1) {
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, dgreen);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, green);
|
||||
}
|
||||
else if (world[i][j][k] == 2) {
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, dblue);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, blue);
|
||||
}
|
||||
else if (world[i][j][k] == 3) {
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, dred);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, red);
|
||||
}
|
||||
else if (world[i][j][k] == 4) {
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, black);
|
||||
}
|
||||
else if (world[i][j][k] == 5) {
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, white);
|
||||
}
|
||||
else if (world[i][j][k] == 6) {
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, dpurple);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, purple);
|
||||
}
|
||||
else if (world[i][j][k] == 7) {
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, dorange);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, orange);
|
||||
}
|
||||
else {
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, dyellow);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow);
|
||||
}
|
||||
|
||||
glPushMatrix ();
|
||||
/* offset cubes by 0.5 so the centre of the */
|
||||
/* cube falls in the centre of the world array */
|
||||
glTranslatef(i + 0.5, j + 0.5, k + 0.5);
|
||||
glutSolidCube(1.0);
|
||||
glPopMatrix ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* called each time the world is redrawn */
|
||||
void display (void)
|
||||
{
|
||||
GLfloat skyblue[] = {0.52, 0.74, 0.84, 1.0};
|
||||
GLfloat black[] = {0.0, 0.0, 0.0, 1.0};
|
||||
GLfloat red[] = {1.0, 0.0, 0.0, 1.0};
|
||||
GLfloat gray[] = {0.3, 0.3, 0.3, 1.0};
|
||||
GLfloat white[] = {1.0, 1.0, 1.0, 1.0};
|
||||
int i, j, k;
|
||||
|
||||
buildDisplayList();
|
||||
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
/* position viewpoint based on mouse rotation and keyboard
|
||||
translation */
|
||||
glLoadIdentity();
|
||||
glRotatef(mvx, 1.0, 0.0, 0.0);
|
||||
glRotatef(mvy, 0.0, 1.0, 0.0);
|
||||
glRotatef(mvz, 0.0, 0.0, 1.0);
|
||||
/* Subtract 0.5 to raise viewpoint slightly above objects. */
|
||||
/* Gives the impression of a head on top of a body. */
|
||||
glTranslatef(vpx, vpy - 0.5, vpz);
|
||||
// glTranslatef(vpx, vpy, vpz);
|
||||
|
||||
|
||||
/* set viewpoint light position */
|
||||
viewpointLight[0] = -vpx;
|
||||
viewpointLight[1] = -vpy;
|
||||
viewpointLight[2] = -vpz;
|
||||
glLightfv (GL_LIGHT1, GL_POSITION, viewpointLight);
|
||||
|
||||
/* draw surfaces as either smooth or flat shaded */
|
||||
if (smoothShading == 1)
|
||||
glShadeModel(GL_SMOOTH);
|
||||
else
|
||||
glShadeModel(GL_FLAT);
|
||||
|
||||
/* draw polygons as either solid or outlines */
|
||||
if (lineDrawing == 1)
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
else
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
|
||||
/* give all objects the same shininess value and specular colour */
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, 90.0);
|
||||
|
||||
/* set starting location of objects */
|
||||
glPushMatrix ();
|
||||
|
||||
/* make a blue sky cube */
|
||||
glShadeModel(GL_SMOOTH);
|
||||
/* turn off all reflection from sky so it is a solid colour */
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, black);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, black);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, skyblue);
|
||||
glPushMatrix ();
|
||||
/* move the sky cube center to middle of world space */
|
||||
glTranslatef((float)WORLDX/2.0, (float)WORLDY/2.0, (float)WORLDZ/2.0);
|
||||
//glutSolidCube(150.0);
|
||||
glutSolidCube(skySize);
|
||||
glPopMatrix ();
|
||||
glShadeModel(GL_SMOOTH);
|
||||
/* turn off emision lighting, use only for sky */
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
|
||||
|
||||
/* draw mobs in the world */
|
||||
for(i=0; i<MOB_COUNT; i++) {
|
||||
if (mobVisible[i] == 1) {
|
||||
glPushMatrix();
|
||||
/* black body */
|
||||
glTranslatef(mobPosition[i][0]+0.5, mobPosition[i][1]+0.5,
|
||||
mobPosition[i][2]+0.5);
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, black);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, gray);
|
||||
glutSolidSphere(0.5, 8, 8);
|
||||
/* white eyes */
|
||||
glRotatef(mobPosition[i][3], 0.0, 1.0, 0.0);
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, white);
|
||||
glTranslatef(0.3, 0.1, 0.3);
|
||||
glutSolidSphere(0.1, 4, 4);
|
||||
glTranslatef(-0.6, 0.0, 0.0);
|
||||
glutSolidSphere(0.1, 4, 4);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
/* draw players in the world */
|
||||
for(i=0; i<PLAYER_COUNT; i++) {
|
||||
if (playerVisible[i] == 1) {
|
||||
glPushMatrix();
|
||||
/* black body */
|
||||
glTranslatef(playerPosition[i][0]+0.5, playerPosition[i][1]+0.5,
|
||||
playerPosition[i][2]+0.5);
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, white);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, gray);
|
||||
glutSolidSphere(0.5, 8, 8);
|
||||
/* white eyes */
|
||||
glRotatef(playerPosition[i][3], 0.0, 1.0, 0.0);
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
|
||||
glTranslatef(0.3, 0.1, 0.3);
|
||||
glutSolidSphere(0.1, 4, 4);
|
||||
glTranslatef(-0.6, 0.0, 0.0);
|
||||
glutSolidSphere(0.1, 4, 4);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
/* draw all cubes in the world array */
|
||||
if (displayAllCubes == 1) {
|
||||
/* draw all cubes */
|
||||
for(i=0; i<WORLDX; i++) {
|
||||
for(j=0; j<WORLDY; j++) {
|
||||
for(k=0; k<WORLDZ; k++) {
|
||||
if (world[i][j][k] != 0) {
|
||||
drawCube(i, j, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* draw only the cubes in the displayList */
|
||||
/* these should have been selected in the update function */
|
||||
|
||||
for(i=0; i<displayCount; i++) {
|
||||
drawCube(displayList[i][0],
|
||||
displayList[i][1],
|
||||
displayList[i][2]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 2D drawing section used to create interface components */
|
||||
/* change to orthographic mode to display 2D images */
|
||||
glMatrixMode (GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity ();
|
||||
gluOrtho2D(0, screenWidth, 0, screenHeight);
|
||||
glMatrixMode (GL_MODELVIEW);
|
||||
glLoadIdentity ();
|
||||
|
||||
/* turn on alpha blending for 2D */
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glShadeModel(GL_FLAT);
|
||||
glNormal3f(0.0, 0.0, -1.0);
|
||||
|
||||
/* call user's 2D drawing function */
|
||||
draw2D();
|
||||
|
||||
/* reset graphics for 3D drawing */
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glMatrixMode (GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
|
||||
glMatrixMode (GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
/* end 2d display code */
|
||||
|
||||
glutSwapBuffers();
|
||||
}
|
||||
|
||||
/* sets viewport information */
|
||||
void reshape(int w, int h)
|
||||
{
|
||||
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
|
||||
glMatrixMode (GL_PROJECTION);
|
||||
glLoadIdentity ();
|
||||
/* use skySize for far clipping plane */
|
||||
gluPerspective(45.0, (GLfloat)w/(GLfloat)h, 0.1, skySize);
|
||||
glMatrixMode (GL_MODELVIEW);
|
||||
glLoadIdentity ();
|
||||
/* set global screen width and height */
|
||||
screenWidth = w;
|
||||
screenHeight = h;
|
||||
|
||||
}
|
||||
|
||||
/* respond to keyboard events */
|
||||
void keyboard(unsigned char key, int x, int y)
|
||||
{
|
||||
float rotx, roty;
|
||||
|
||||
switch (key) {
|
||||
case 27:
|
||||
case 'q':
|
||||
quit();
|
||||
break;
|
||||
case '1': // draw polygons as outlines
|
||||
lineDrawing = 1;
|
||||
lighting = 0;
|
||||
smoothShading = 0;
|
||||
textures = 0;
|
||||
init();
|
||||
glutPostRedisplay();
|
||||
break;
|
||||
case '2': // draw polygons as filled
|
||||
lineDrawing = 0;
|
||||
lighting = 0;
|
||||
smoothShading = 0;
|
||||
textures = 0;
|
||||
init();
|
||||
glutPostRedisplay();
|
||||
break;
|
||||
case '3': // diffuse and specular lighting, flat shading
|
||||
lineDrawing = 0;
|
||||
lighting = 1;
|
||||
smoothShading = 0;
|
||||
textures = 0;
|
||||
init();
|
||||
glutPostRedisplay();
|
||||
break;
|
||||
case '4': // diffuse and specular lighting, smooth shading
|
||||
lineDrawing = 0;
|
||||
lighting = 1;
|
||||
smoothShading = 1;
|
||||
textures = 0;
|
||||
init();
|
||||
glutPostRedisplay();
|
||||
break;
|
||||
case '5': // texture with smooth shading
|
||||
lineDrawing = 0;
|
||||
lighting = 1;
|
||||
smoothShading = 1;
|
||||
textures = 1;
|
||||
init();
|
||||
glutPostRedisplay();
|
||||
break;
|
||||
case 'w': // forward motion
|
||||
oldvpx = vpx;
|
||||
oldvpy = vpy;
|
||||
oldvpz = vpz;
|
||||
rotx = (mvx / 180.0 * 3.141592);
|
||||
roty = (mvy / 180.0 * 3.141592);
|
||||
vpx -= sin(roty) * 0.3;
|
||||
// turn off y motion so you can't fly
|
||||
if (flycontrol == 1)
|
||||
vpy += sin(rotx) * 0.3;
|
||||
vpz += cos(roty) * 0.3;
|
||||
collisionResponse();
|
||||
glutPostRedisplay();
|
||||
break;
|
||||
case 's': // backward motion
|
||||
oldvpx = vpx;
|
||||
oldvpy = vpy;
|
||||
oldvpz = vpz;
|
||||
rotx = (mvx / 180.0 * 3.141592);
|
||||
roty = (mvy / 180.0 * 3.141592);
|
||||
vpx += sin(roty) * 0.3;
|
||||
// turn off y motion so you can't fly
|
||||
if (flycontrol == 1)
|
||||
vpy -= sin(rotx) * 0.3;
|
||||
vpz -= cos(roty) * 0.3;
|
||||
collisionResponse();
|
||||
glutPostRedisplay();
|
||||
break;
|
||||
case 'a': // strafe left motion
|
||||
oldvpx = vpx;
|
||||
oldvpy = vpy;
|
||||
oldvpz = vpz;
|
||||
roty = (mvy / 180.0 * 3.141592);
|
||||
vpx += cos(roty) * 0.3;
|
||||
vpz += sin(roty) * 0.3;
|
||||
collisionResponse();
|
||||
glutPostRedisplay();
|
||||
break;
|
||||
case 'd': // strafe right motion
|
||||
oldvpx = vpx;
|
||||
oldvpy = vpy;
|
||||
oldvpz = vpz;
|
||||
roty = (mvy / 180.0 * 3.141592);
|
||||
vpx -= cos(roty) * 0.3;
|
||||
vpz -= sin(roty) * 0.3;
|
||||
collisionResponse();
|
||||
glutPostRedisplay();
|
||||
break;
|
||||
case 'f': // toggle flying controls
|
||||
if (flycontrol == 0) flycontrol = 1;
|
||||
else flycontrol = 0;
|
||||
break;
|
||||
case ' ': // toggle space flag
|
||||
space = 1;
|
||||
break;
|
||||
case 'm': // toggle map display, 0=none, 1=small, 2=large
|
||||
displayMap++;
|
||||
if (displayMap > 2)
|
||||
displayMap = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* load a texture from a file */
|
||||
/* not currently used */
|
||||
void loadTexture() {
|
||||
FILE *fp;
|
||||
int i, j;
|
||||
int red, green, blue;
|
||||
|
||||
if ((fp = fopen("image.txt", "r")) == 0) {
|
||||
printf("Error, failed to find the file named image.txt.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
for(i=0; i<64; i++) {
|
||||
for(j=0; j<64; j++) {
|
||||
fscanf(fp, "%d %d %d", &red, &green, &blue);
|
||||
Image[i][j][0] = red;
|
||||
Image[i][j][1] = green;
|
||||
Image[i][j][2] = blue;
|
||||
Image[i][j][3] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glGenTextures(1,textureID);
|
||||
glBindTexture(GL_TEXTURE_2D, textureID[0]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, Image);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
glEnable(GL_TEXTURE_GEN_S);
|
||||
glEnable(GL_TEXTURE_GEN_T);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
/* responds to mouse movement when a button is pressed */
|
||||
void motion(int x, int y) {
|
||||
/* update current mouse movement but don't use to change the viewpoint*/
|
||||
oldx = x;
|
||||
oldy = y;
|
||||
}
|
||||
|
||||
/* responds to mouse movement when a button is not pressed */
|
||||
void passivemotion(int x, int y) {
|
||||
mvx += (float) y - oldy;
|
||||
mvy += (float) x - oldx;
|
||||
oldx = x;
|
||||
oldy = y;
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* initilize graphics information and mob data structure */
|
||||
void graphicsInit(int *argc, char **argv) {
|
||||
int i, fullscreen;
|
||||
/* set GL window information */
|
||||
glutInit(argc, argv);
|
||||
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
|
||||
|
||||
/* parse command line args */
|
||||
fullscreen = 0;
|
||||
for(i=1; i<*argc; i++) {
|
||||
if (strcmp(argv[i],"-full") == 0)
|
||||
fullscreen = 1;
|
||||
if (strcmp(argv[i],"-drawall") == 0)
|
||||
displayAllCubes = 1;
|
||||
if (strcmp(argv[i],"-testworld") == 0)
|
||||
testWorld = 1;
|
||||
if (strcmp(argv[i],"-fps") == 0)
|
||||
fps = 1;
|
||||
if (strcmp(argv[i],"-client") == 0)
|
||||
netClient = 1;
|
||||
if (strcmp(argv[i],"-server") == 0)
|
||||
netServer = 1;
|
||||
if (strcmp(argv[i],"-help") == 0) {
|
||||
printf("Usage: a4 [-full] [-drawall] [-testworld] [-fps] [-client] [-server]\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (fullscreen == 1) {
|
||||
glutGameModeString("1024x768:32@75");
|
||||
glutEnterGameMode();
|
||||
} else {
|
||||
glutInitWindowSize (screenWidth, screenHeight);
|
||||
glutCreateWindow (argv[0]);
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
/* not used at the moment */
|
||||
// loadTexture();
|
||||
|
||||
/* attach functions to GL events */
|
||||
glutReshapeFunc (reshape);
|
||||
glutDisplayFunc(display);
|
||||
glutKeyboardFunc (keyboard);
|
||||
glutPassiveMotionFunc(passivemotion);
|
||||
glutMotionFunc(motion);
|
||||
glutMouseFunc(mouse);
|
||||
glutIdleFunc(update);
|
||||
|
||||
|
||||
/* initialize mob and player array to empty */
|
||||
initMobArray();
|
||||
initPlayerArray();
|
||||
|
||||
/* set the size of the sky */
|
||||
if (WORLDX > WORLDY)
|
||||
skySize = (float) WORLDX;
|
||||
else
|
||||
skySize = (float) WORLDY;
|
||||
if (WORLDZ > skySize)
|
||||
skySize = (float) WORLDZ;
|
||||
skySize *= 1.5;
|
||||
}
|
||||
|
||||
/* functions to draw 2d images on screen */
|
||||
void draw2Dline(int x1, int y1, int x2, int y2, int lineWidth) {
|
||||
glLineWidth(lineWidth);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2i(x1, y1);
|
||||
glVertex2i(x2, y2);
|
||||
glEnd();
|
||||
glLineWidth(1);
|
||||
}
|
||||
|
||||
void draw2Dbox(int x1, int y1, int x2, int y2) {
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2i(x1, y1);
|
||||
glVertex2i(x1, y2);
|
||||
glVertex2i(x2, y2);
|
||||
glVertex2i(x2, y1);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void draw2Dtriangle(int x1, int y1, int x2, int y2, int x3, int y3) {
|
||||
glBegin(GL_TRIANGLES);
|
||||
glVertex2i(x1, y1);
|
||||
glVertex2i(x2, y2);
|
||||
glVertex2i(x3, y3);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void set2Dcolour(float colourv[]) {
|
||||
glMaterialfv(GL_FRONT, GL_EMISSION, colourv);
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, colourv);
|
||||
}
|
||||
|
||||
21
graphics.h
Normal file
21
graphics.h
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/glu.h>
|
||||
#include <GLUT/glut.h>
|
||||
#elif __linux__
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include <GL/glut.h>
|
||||
#endif
|
||||
|
||||
/* world size and storage array */
|
||||
#define WORLDX 100
|
||||
#define WORLDY 10
|
||||
#define WORLDZ 100
|
||||
GLubyte world[WORLDX][WORLDY][WORLDZ];
|
||||
|
||||
#define MOB_COUNT 10
|
||||
#define PLAYER_COUNT 10
|
||||
|
||||
#define MAX_DISPLAY_LIST 500000
|
||||
10
makefile
Normal file
10
makefile
Normal file
@@ -0,0 +1,10 @@
|
||||
INCLUDES = -F/System/Library/Frameworks -framework OpenGL -framework GLUT -lm
|
||||
LINUXINCLUDES = -g -Wall -F/System/Library/Frameworks -lGL -lGLU -lm -lglut
|
||||
|
||||
a3: a4.c graphics.c visible.c graphics.h
|
||||
gcc a4.c graphics.c visible.c -o a4 $(INCLUDES)
|
||||
|
||||
linux: a4.c graphics.c visible.c graphics.h
|
||||
gcc a4.c graphics.c visible.c -o a4 $(LINUXINCLUDES)
|
||||
clean:
|
||||
rm a4
|
||||
2
readme.txt
Normal file
2
readme.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
If you have trouble finding anything in the maze far any reason, such as walls always being in your way,
|
||||
you can shoot a hole in the wall and walk through. Shoot the 2nd block from the bottom and climb through.
|
||||
426
visible.c
Normal file
426
visible.c
Normal file
@@ -0,0 +1,426 @@
|
||||
|
||||
/* Frustum culling source code from:
|
||||
http://www.crownandcutlass.com/features/technicaldetails/frustum.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "graphics.h"
|
||||
|
||||
#define OCTREE_LEVEL 1
|
||||
|
||||
extern void gradphicsInit(int *, char **);
|
||||
extern void setLightPosition(GLfloat, GLfloat, GLfloat);
|
||||
extern GLfloat* getLightPosition();
|
||||
|
||||
extern void setViewPosition(float, float, float);
|
||||
extern void getViewPosition(float *, float *, float *);
|
||||
extern void getOldViewPosition(float *, float *, float *);
|
||||
extern void getViewOrientation(float *, float *, float *);
|
||||
|
||||
extern int addDisplayList(int, int, int);
|
||||
|
||||
extern void createMob(int, float, float, float, float);
|
||||
extern void setMobPosition(int, float, float, float, float);
|
||||
extern void hideMob(int);
|
||||
extern void showMob(int);
|
||||
|
||||
extern void createPlayer(int, float, float, float, float);
|
||||
extern void setPlayerPosition(int, float, float, float, float);
|
||||
extern void hidePlayer(int);
|
||||
extern void showPlayer(int);
|
||||
|
||||
/* flag which is set to 1 when flying behaviour is desired */
|
||||
extern int flycontrol;
|
||||
/* flag used to indicate that the test world should be used */
|
||||
extern int testWorld;
|
||||
/* list and count of polygons to be displayed, set during culling */
|
||||
extern int displayList[MAX_DISPLAY_LIST][3];
|
||||
extern int displayCount;
|
||||
/* flag to print out frames per second */
|
||||
extern int fps;
|
||||
/* flag indicates the program is a client when set = 1 */
|
||||
extern int netClient;
|
||||
/* flag indicates the program is a server when set = 1 */
|
||||
extern int netServer;
|
||||
|
||||
/* frustum corner coordinates */
|
||||
float corners[4][3];
|
||||
|
||||
/***********************/
|
||||
|
||||
float lengthTwoPoints(float x1, float y1, float z1, float x2, float y2, float z2) {
|
||||
float result;
|
||||
result = sqrtf( powf((x1 - x2), 2.0) + powf((y1 - y2), 2.0)
|
||||
+ powf((z1 - z2), 2.0) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
float lengthVector(float x1, float y1, float z1) {
|
||||
float result;
|
||||
result = sqrtf( powf(x1, 2.0) + powf(y1, 2.0) + powf(z1, 2.0) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
void cross(float x1, float y1, float z1, float x2, float y2, float z2,
|
||||
float *x, float *y, float *z) {
|
||||
*x = (y1*z2) - (z1*y2);
|
||||
*y = (x1*z2) - (z1*x2);
|
||||
*z = (x1*y2) - (y1*x2);
|
||||
}
|
||||
|
||||
/* returns radians */
|
||||
void dot (float x1, float y1, float z1, float x2, float y2, float z2) {
|
||||
float result;
|
||||
result = (x1 * x2) + (y1 * y2) + (z1 * z2);
|
||||
result /= (lengthVector(x1, y1, z1) * lengthVector(x2, y2, z2));
|
||||
result = acosf(result);
|
||||
}
|
||||
|
||||
/* the next two function use Cramer's rule to find the intersection */
|
||||
/* of three planes */
|
||||
/* used to find outer points of frustum */
|
||||
/* http://www.dreamincode.net/code/snippet530.htm */
|
||||
double finddet(double a1,double a2, double a3,double b1, double b2,double b3, double c1, double c2, double c3)
|
||||
{
|
||||
/*expansion of a 3x3 determinant*/
|
||||
return ((a1*b2*c3)-(a1*b3*c2)-(a2*b1*c3)+(a3*b1*c2)+(a2*b3*c1)-(a3*b2*c1));
|
||||
}
|
||||
|
||||
void intersect(float a1, float b1, float c1, float d1,
|
||||
float a2, float b2, float c2, float d2,
|
||||
float a3, float b3, float c3, float d3,
|
||||
float *x, float *y, float *z) {
|
||||
float det, detx, dety, detz;
|
||||
|
||||
det=finddet(a1,a2,a3,b1,b2,b3,c1,c2,c3); /*Find determinants*/
|
||||
detx=finddet(d1,d2,d3,b1,b2,b3,c1,c2,c3);
|
||||
dety=finddet(a1,a2,a3,d1,d2,d3,c1,c2,c3);
|
||||
detz=finddet(a1,a2,a3,b1,b2,b3,d1,d2,d3);
|
||||
|
||||
/*Print Answers depending on various conditions*/
|
||||
if(d1==0 && d2==0 && d3==0 && det==0) {
|
||||
printf("\n Infinite Solutions\n ");
|
||||
} else if(d1==0 && d2==0 && d3==0 && det!=0) {
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
*z = 0;
|
||||
} else if(det!=0) {
|
||||
*x = (detx/det);
|
||||
*y = (dety/det);
|
||||
*z = (detz/det);
|
||||
//printf("x=%lf y=%lf z=%lf\n", (detx/det), (dety/det), (detz/det));
|
||||
} else if(det==0 && detx==0 && dety==0 && detz==0)
|
||||
printf("\n Infinite Solutions\n ");
|
||||
else
|
||||
printf("No Solution\n ");
|
||||
}
|
||||
|
||||
/***********************/
|
||||
|
||||
/* calculate the viewing frustum and test if cubes fall inside it */
|
||||
/* code from */
|
||||
/* http://www.crownandcutlass.com/features/technicaldetails/frustum.html */
|
||||
float frustum[6][4];
|
||||
int true = 1;
|
||||
int false = 0;
|
||||
|
||||
void ExtractFrustum()
|
||||
{
|
||||
float proj[16];
|
||||
float modl[16];
|
||||
float clip[16];
|
||||
float t;
|
||||
|
||||
/* Get the current PROJECTION matrix from OpenGL */
|
||||
glGetFloatv( GL_PROJECTION_MATRIX, proj );
|
||||
|
||||
/* Get the current MODELVIEW matrix from OpenGL */
|
||||
glGetFloatv( GL_MODELVIEW_MATRIX, modl );
|
||||
|
||||
/* Combine the two matrices (multiply projection by modelview) */
|
||||
clip[ 0] = modl[ 0] * proj[ 0] + modl[ 1] * proj[ 4] + modl[ 2] * proj[ 8] + modl[ 3] * proj[12];
|
||||
clip[ 1] = modl[ 0] * proj[ 1] + modl[ 1] * proj[ 5] + modl[ 2] * proj[ 9] + modl[ 3] * proj[13];
|
||||
clip[ 2] = modl[ 0] * proj[ 2] + modl[ 1] * proj[ 6] + modl[ 2] * proj[10] + modl[ 3] * proj[14];
|
||||
clip[ 3] = modl[ 0] * proj[ 3] + modl[ 1] * proj[ 7] + modl[ 2] * proj[11] + modl[ 3] * proj[15];
|
||||
|
||||
clip[ 4] = modl[ 4] * proj[ 0] + modl[ 5] * proj[ 4] + modl[ 6] * proj[ 8] + modl[ 7] * proj[12];
|
||||
clip[ 5] = modl[ 4] * proj[ 1] + modl[ 5] * proj[ 5] + modl[ 6] * proj[ 9] + modl[ 7] * proj[13];
|
||||
clip[ 6] = modl[ 4] * proj[ 2] + modl[ 5] * proj[ 6] + modl[ 6] * proj[10] + modl[ 7] * proj[14];
|
||||
clip[ 7] = modl[ 4] * proj[ 3] + modl[ 5] * proj[ 7] + modl[ 6] * proj[11] + modl[ 7] * proj[15];
|
||||
|
||||
clip[ 8] = modl[ 8] * proj[ 0] + modl[ 9] * proj[ 4] + modl[10] * proj[ 8] + modl[11] * proj[12];
|
||||
clip[ 9] = modl[ 8] * proj[ 1] + modl[ 9] * proj[ 5] + modl[10] * proj[ 9] + modl[11] * proj[13];
|
||||
clip[10] = modl[ 8] * proj[ 2] + modl[ 9] * proj[ 6] + modl[10] * proj[10] + modl[11] * proj[14];
|
||||
clip[11] = modl[ 8] * proj[ 3] + modl[ 9] * proj[ 7] + modl[10] * proj[11] + modl[11] * proj[15];
|
||||
|
||||
clip[12] = modl[12] * proj[ 0] + modl[13] * proj[ 4] + modl[14] * proj[ 8] + modl[15] * proj[12];
|
||||
clip[13] = modl[12] * proj[ 1] + modl[13] * proj[ 5] + modl[14] * proj[ 9] + modl[15] * proj[13];
|
||||
clip[14] = modl[12] * proj[ 2] + modl[13] * proj[ 6] + modl[14] * proj[10] + modl[15] * proj[14];
|
||||
clip[15] = modl[12] * proj[ 3] + modl[13] * proj[ 7] + modl[14] * proj[11] + modl[15] * proj[15];
|
||||
|
||||
/* Extract the numbers for the RIGHT plane */
|
||||
frustum[0][0] = clip[ 3] - clip[ 0];
|
||||
frustum[0][1] = clip[ 7] - clip[ 4];
|
||||
frustum[0][2] = clip[11] - clip[ 8];
|
||||
frustum[0][3] = clip[15] - clip[12];
|
||||
|
||||
/* Normalize the result */
|
||||
t = sqrt( frustum[0][0] * frustum[0][0] + frustum[0][1] * frustum[0][1] + frustum[0][2] * frustum[0][2] );
|
||||
frustum[0][0] /= t;
|
||||
frustum[0][1] /= t;
|
||||
frustum[0][2] /= t;
|
||||
frustum[0][3] /= t;
|
||||
|
||||
/* Extract the numbers for the LEFT plane */
|
||||
frustum[1][0] = clip[ 3] + clip[ 0];
|
||||
frustum[1][1] = clip[ 7] + clip[ 4];
|
||||
frustum[1][2] = clip[11] + clip[ 8];
|
||||
frustum[1][3] = clip[15] + clip[12];
|
||||
|
||||
/* Normalize the result */
|
||||
t = sqrt( frustum[1][0] * frustum[1][0] + frustum[1][1] * frustum[1][1] + frustum[1][2] * frustum[1][2] );
|
||||
frustum[1][0] /= t;
|
||||
frustum[1][1] /= t;
|
||||
frustum[1][2] /= t;
|
||||
frustum[1][3] /= t;
|
||||
|
||||
/* Extract the BOTTOM plane */
|
||||
frustum[2][0] = clip[ 3] + clip[ 1];
|
||||
frustum[2][1] = clip[ 7] + clip[ 5];
|
||||
frustum[2][2] = clip[11] + clip[ 9];
|
||||
frustum[2][3] = clip[15] + clip[13];
|
||||
|
||||
/* Normalize the result */
|
||||
t = sqrt( frustum[2][0] * frustum[2][0] + frustum[2][1] * frustum[2][1] + frustum[2][2] * frustum[2][2] );
|
||||
frustum[2][0] /= t;
|
||||
frustum[2][1] /= t;
|
||||
frustum[2][2] /= t;
|
||||
frustum[2][3] /= t;
|
||||
|
||||
/* Extract the TOP plane */
|
||||
frustum[3][0] = clip[ 3] - clip[ 1];
|
||||
frustum[3][1] = clip[ 7] - clip[ 5];
|
||||
frustum[3][2] = clip[11] - clip[ 9];
|
||||
frustum[3][3] = clip[15] - clip[13];
|
||||
|
||||
/* Normalize the result */
|
||||
t = sqrt( frustum[3][0] * frustum[3][0] + frustum[3][1] * frustum[3][1] + frustum[3][2] * frustum[3][2] );
|
||||
frustum[3][0] /= t;
|
||||
frustum[3][1] /= t;
|
||||
frustum[3][2] /= t;
|
||||
frustum[3][3] /= t;
|
||||
|
||||
/* Extract the FAR plane */
|
||||
frustum[4][0] = clip[ 3] - clip[ 2];
|
||||
frustum[4][1] = clip[ 7] - clip[ 6];
|
||||
frustum[4][2] = clip[11] - clip[10];
|
||||
frustum[4][3] = clip[15] - clip[14];
|
||||
|
||||
/* Normalize the result */
|
||||
t = sqrt( frustum[4][0] * frustum[4][0] + frustum[4][1] * frustum[4][1] + frustum[4][2] * frustum[4][2] );
|
||||
frustum[4][0] /= t;
|
||||
frustum[4][1] /= t;
|
||||
frustum[4][2] /= t;
|
||||
frustum[4][3] /= t;
|
||||
|
||||
/* Extract the NEAR plane */
|
||||
frustum[5][0] = clip[ 3] + clip[ 2];
|
||||
frustum[5][1] = clip[ 7] + clip[ 6];
|
||||
frustum[5][2] = clip[11] + clip[10];
|
||||
frustum[5][3] = clip[15] + clip[14];
|
||||
|
||||
/* Normalize the result */
|
||||
t = sqrt( frustum[5][0] * frustum[5][0] + frustum[5][1] * frustum[5][1] + frustum[5][2] * frustum[5][2] );
|
||||
frustum[5][0] /= t;
|
||||
frustum[5][1] /= t;
|
||||
frustum[5][2] /= t;
|
||||
frustum[5][3] /= t;
|
||||
}
|
||||
|
||||
int PointInFrustum( float x, float y, float z )
|
||||
{
|
||||
int p;
|
||||
|
||||
for( p = 0; p < 6; p++ )
|
||||
if( frustum[p][0] * x + frustum[p][1] * y + frustum[p][2] * z + frustum[p][3] <= 0 )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int CubeInFrustum( float x, float y, float z, float size )
|
||||
{
|
||||
int p;
|
||||
int c;
|
||||
int c2 = 0;
|
||||
|
||||
for( p = 0; p < 6; p++ )
|
||||
{
|
||||
c = 0;
|
||||
if( frustum[p][0] * (x - size) + frustum[p][1] * (y - size) + frustum[p][2] * (z - size) + frustum[p][3] > 0 )
|
||||
c++;
|
||||
if( frustum[p][0] * (x + size) + frustum[p][1] * (y - size) + frustum[p][2] * (z - size) + frustum[p][3] > 0 )
|
||||
c++;
|
||||
if( frustum[p][0] * (x - size) + frustum[p][1] * (y + size) + frustum[p][2] * (z - size) + frustum[p][3] > 0 )
|
||||
c++;
|
||||
if( frustum[p][0] * (x + size) + frustum[p][1] * (y + size) + frustum[p][2] * (z - size) + frustum[p][3] > 0 )
|
||||
c++;
|
||||
if( frustum[p][0] * (x - size) + frustum[p][1] * (y - size) + frustum[p][2] * (z + size) + frustum[p][3] > 0 )
|
||||
c++;
|
||||
if( frustum[p][0] * (x + size) + frustum[p][1] * (y - size) + frustum[p][2] * (z + size) + frustum[p][3] > 0 )
|
||||
c++;
|
||||
if( frustum[p][0] * (x - size) + frustum[p][1] * (y + size) + frustum[p][2] * (z + size) + frustum[p][3] > 0 )
|
||||
c++;
|
||||
if( frustum[p][0] * (x + size) + frustum[p][1] * (y + size) + frustum[p][2] * (z + size) + frustum[p][3] > 0 )
|
||||
c++;
|
||||
if( c == 0 )
|
||||
return 0;
|
||||
if( c == 8 )
|
||||
c2++;
|
||||
}
|
||||
return (c2 == 6) ? 2 : 1;
|
||||
}
|
||||
|
||||
|
||||
int CubeInFrustum2( float x, float y, float z, float size )
|
||||
{
|
||||
int p;
|
||||
|
||||
//ZZZ
|
||||
for( p = 0; p < 6; p++ )
|
||||
{
|
||||
if( frustum[p][0] * (x - size) + frustum[p][1] * (y - size) + frustum[p][2] * (z - size) + frustum[p][3] > 0 )
|
||||
continue;
|
||||
if( frustum[p][0] * (x + size) + frustum[p][1] * (y - size) + frustum[p][2] * (z - size) + frustum[p][3] > 0 )
|
||||
continue;
|
||||
if( frustum[p][0] * (x - size) + frustum[p][1] * (y + size) + frustum[p][2] * (z - size) + frustum[p][3] > 0 )
|
||||
continue;
|
||||
if( frustum[p][0] * (x + size) + frustum[p][1] * (y + size) + frustum[p][2] * (z - size) + frustum[p][3] > 0 )
|
||||
continue;
|
||||
if( frustum[p][0] * (x - size) + frustum[p][1] * (y - size) + frustum[p][2] * (z + size) + frustum[p][3] > 0 )
|
||||
continue;
|
||||
if( frustum[p][0] * (x + size) + frustum[p][1] * (y - size) + frustum[p][2] * (z + size) + frustum[p][3] > 0 )
|
||||
continue;
|
||||
if( frustum[p][0] * (x - size) + frustum[p][1] * (y + size) + frustum[p][2] * (z + size) + frustum[p][3] > 0 )
|
||||
continue;
|
||||
if( frustum[p][0] * (x + size) + frustum[p][1] * (y + size) + frustum[p][2] * (z + size) + frustum[p][3] > 0 )
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****/
|
||||
|
||||
|
||||
|
||||
// if frustum test shows box in view
|
||||
// if level == max level then draw contents of cube
|
||||
// else call 8 subdivisions, increment level
|
||||
// assumes all t[xyz] are larger than b[xyz] respectively
|
||||
|
||||
void tree(float bx, float by, float bz, float tx, float ty, float tz,
|
||||
int level) {
|
||||
float length;
|
||||
float newCentrex, newCentrey, newCentrez;
|
||||
int i, j, k;
|
||||
|
||||
/* find length of cube edge */
|
||||
length = (tx - bx) / 2.0;
|
||||
if (length < 0) length *= -1;
|
||||
|
||||
/* if the octree cube is in the frustum then */
|
||||
/* if the bottom octree level is reached then */
|
||||
/* if the visible cube is not empty and is not surrounded then */
|
||||
/* add to the display list */
|
||||
if (CubeInFrustum(bx + ((tx-bx)/2), by + ((ty-by)/2), bz + ((tz-bz)/2), length )) {
|
||||
if (level == OCTREE_LEVEL) {
|
||||
/* draw cubes */
|
||||
for(i=bx; i<tx+1; i++)
|
||||
for(j=by; j<ty+1; j++)
|
||||
for(k=bz; k<tz+1; k++) {
|
||||
if ((i<WORLDX) && (j<WORLDY) && (k<WORLDZ) && (i>-1) && (j>-1) && (k>-1))
|
||||
if ( (world[i][j][k] != 0) &&
|
||||
(CubeInFrustum(i+0.5, j+0.5, k+0.5, 0.5)) ) {
|
||||
/* check for six neighbours */
|
||||
/* if cube is not on the outer edge and is not*/
|
||||
/* surrounded by 6 neighbours then draw it */
|
||||
/* else if the cube is an outside cube then */
|
||||
/* always draw it */
|
||||
if ( (i > 0) && (i < WORLDX-1) &&
|
||||
(j > 0) && (j < WORLDY-1) &&
|
||||
(k > 0) && (k < WORLDZ-1) &&
|
||||
((world[i+1][j][k] == 0) || (world[i-1][j][k] == 0)
|
||||
|| (world[i][j+1][k] == 0) || (world[i][j-1][k] == 0)
|
||||
|| (world[i][j][k+1] == 0) || (world[i][j][k-1] == 0)))
|
||||
addDisplayList(i, j, k);
|
||||
else if ( (i == 0) || (i == WORLDX-1) ||
|
||||
(j == 0) || (j == WORLDY-1) ||
|
||||
(k == 0) || (k == WORLDZ-1) )
|
||||
addDisplayList(i, j, k);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* calculate centre of new cube */
|
||||
newCentrex = bx + ((tx - bx) / 2.0);
|
||||
newCentrey = by + ((ty - by) / 2.0);
|
||||
newCentrez = bz + ((tz - bz) / 2.0);
|
||||
/* call recursive tree functions, increment level */
|
||||
level++;
|
||||
tree(bx, by, bz, newCentrex, newCentrey, newCentrez, level);
|
||||
tree(newCentrex, by, bz, tx, newCentrey, newCentrez, level);
|
||||
tree(bx, by, newCentrez, newCentrex, newCentrey, tz, level);
|
||||
tree(newCentrex, by, newCentrez, tx, newCentrey, tz, level);
|
||||
tree(bx, newCentrey, bz, newCentrex, ty, newCentrez, level);
|
||||
tree(newCentrex, newCentrey, bz, tx, ty, newCentrez, level);
|
||||
tree(bx, newCentrey, newCentrez, newCentrex, ty, tz, level);
|
||||
tree(newCentrex, newCentrey, newCentrez, tx, ty, tz, level);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* determines which cubes are to be drawn and puts them into */
|
||||
/* the displayList */
|
||||
/* write your cube culling code here */
|
||||
void buildDisplayList() {
|
||||
float newx, newy, newz;
|
||||
/* used to calculate frames per second */
|
||||
static int frame=0, time, timebase=0;
|
||||
|
||||
getViewPosition(&newx, &newy, &newz);
|
||||
|
||||
|
||||
/* calculate frustum for current viewpoint, store in frustum[][] */
|
||||
ExtractFrustum();
|
||||
|
||||
/* octree, used to determine if regions are visible */
|
||||
/* stores visible cubes in a display list */
|
||||
displayCount = 0;
|
||||
tree(0.0, 0.0, 0.0, (float) WORLDX, (float) WORLDY, (float) WORLDZ, 0);
|
||||
|
||||
|
||||
/* frame per second calculation */
|
||||
/* don't change the following routine */
|
||||
/* Code taken from : */
|
||||
/* http://www.lighthouse3d.com/opengl/glut/index.php?fps */
|
||||
if (fps == 1) {
|
||||
frame++;
|
||||
time=glutGet(GLUT_ELAPSED_TIME);
|
||||
if (time - timebase > 1000) {
|
||||
printf("FPS:%4.2f\n", frame*1000.0/(time-timebase));
|
||||
timebase = time;
|
||||
frame = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* redraw the screen at the end of the update */
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user