//***************************************************************************
#include <math.h>
#include <ctype.h>
#include <iostream.h>
#include <fstream.h>
#include <GL/glut.h>
#include <stdlib.h>
#include "color.h"
#include "query.h"
#include "readrgb.h"
#include "table.h"
#include <stdio.h>
//***************************************************************************
#define TOLERANCE (1.0e-6)
#define IS_EQUAL(x,y) (fabs((x)-(y)) < TOLERANCE)
#define MAX_EDGES 300
//***************************************************************************
typedef struct _myEdge {
double x1, x2, y1, y2;
} myEdge;
//***************************************************************************
// Global variables:
static int winIdMain;
static int winIdSub;
myColor colorDB; // Color Database
GLfloat yAngle, xPosition, yPosition, zPosition, tempAngle;
GLfloat yAnglePopup, tempAnglePopup;
GLfloat xBegin, zBegin, xEnd, zEnd, xCheck, zCheck;
GLint xStart, yStart, zStart;
GLint finished = 0;
GLfloat strip[MAX_EDGES][10][3];
GLfloat doorstrip[MAX_EDGES][10][3];
int numDoorStrips;
GLfloat stripColor[MAX_EDGES][10][4];
GLfloat doorstripColor[MAX_EDGES][10][4];
GLfloat mat_diffuse[] = { 0.6, 0.6, 0.6, 1.0 };
GLfloat mat_specular[] = { 1.0, 0.5, 0.5, 1.0 };
GLfloat mat_shininess[] = { 30.0 };
GLfloat spinningSpherePos[] = { 1.0, 1.0, 4.0 };
GLfloat bouncingSpherePos[] = { 3.0, 0.0, 6.0 };
GLfloat ball_color[] = { 0.0, 0.0, 0.0, 0.0 };
GLfloat floorColor[4];
double deg2rad = 3.141592654 / 180.0;
double rad2deg = 180.0 / 3.141592654;
float safe = 0.1;
int numEdges, numObjects;
int tick = 0, tock = 0, tack = 0;
int noWalls = 0;
float edgelist[MAX_EDGES][2][2];
float dooredge[MAX_EDGES][2][2];
myEdge myEdges[MAX_EDGES];
float objects[MAX_EDGES][2];
int objectType[MAX_EDGES];
float Xmin, Zmin, Xmax, Zmax;
int popView = 0;
float zoom = 25.0;
int initialMovement = 0;
long startTime, endTime, totalTime, score;
int popCount;
int whichMaze = 1;
int numBoundingEdges;
float xVec, zVec;
char inpFile[30];
int inpFlag = 0;
int helpflag = 0;
int textureflag = 1;
double x_scaling_factor = +3.0;
double z_scaling_factor = -3.0;
int tableOrientation = 0; // 0 -> North, 1 -> South
GLfloat lightZeroPosition[] = { 27.0*x_scaling_factor, 3.2, 2.7*z_scaling_factor, 1.0 };
GLfloat lightZeroColor[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat lightOnePosition[] = { 0.0, 3.2, 2.7*z_scaling_factor, 1.0 };
GLfloat lightOneColor[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat lightTwoPosition[] = { 13.0*x_scaling_factor, 4.0, 2.7*z_scaling_factor, 1.0 };
GLfloat lightTwoColor[] = { 1.0, 1.0, 1.0, 1.0 };
float xGlobal, yGlobal;
char filename[][30] = {"plan.dat"};
double wallheight = 4.0;
int numfiles = sizeof(filename)/sizeof(filename[30]);
int WIDTH = 700, HEIGHT = 500;
void drawString(char *s);
char infoString[200];
//***************************************************************************
static int compareEdge(const void *e1, const void *e2);
void addColors();
float OrientPointer(float xVec, float zVec);
void print_help();
void readMazeFromFile();
int addTextureFromFile(char *filename);
void printRoom(Room *ptr);
void printhelpScreen(void);
void reshape(int width, int height);
void initMazeColor(void);
void setBoundingBox(float x, float z);
void facecube(float tx, float tz, int texnum);
void subDisplay(void);
void subreshape(int w, int h);
void renderRoom(Room *room);
//***************************************************************************
// idle routine that updates clock for spinning sphere
void idle(void)
{
tick = (tick+1)%120;
tack++;
if (tack < 10 && tack > 4)
{
if (tack > 8)
tack = 0;
tock = (tock > 0) ? -1 : tock - 1;
}
else
tock = (tock < 0) ? 1 : tock + 1;
glutPostRedisplay();
}
//***************************************************************************
// Convert maze description to quadralaterals
void initMaze()
{
int i, k;
float dx, dy, nx, ny, norm;
float r, g, b;
char name[30];
finished = 0;
readMazeFromFile();
xPosition = xBegin;
zPosition = zBegin;
yPosition = 1.0;
if (whichMaze == 2)
yAngle = 180.0;
else
yAngle = 0.0;
yAnglePopup = yAngle;
// We take each edge and extend it into a wall of thickness 0.1
// We also extend the edges a bit extra in the "long" direction
// so that we don't get faces of adjoining walls right on top of
// other. Note that we have made no effort to get the surface
// normals correct.
double wallextension = 1.0;
double wallwidth = 0.10;
for (i = 0; i < numEdges; i++)
{
dx = edgelist[i][1][0] - edgelist[i][0][0];
dy = edgelist[i][1][1] - edgelist[i][0][1];
norm = sqrt(dx*dx + dy*dy);
dx = wallwidth * dx / norm;
dy = wallwidth * dy / norm;
nx = -dy;
ny = dx;
// convert each edge to quad strip
strip[i][0][0] = edgelist[i][0][0] - wallextension * dx - nx;
strip[i][0][1] = 0.0;
strip[i][0][2] = edgelist[i][0][1] - wallextension * dy - ny;
strip[i][1][0] = strip[i][0][0];
strip[i][1][1] = wallheight;
strip[i][1][2] = strip[i][0][2];
strip[i][2][0] = edgelist[i][1][0] + wallextension * dx - nx;
strip[i][2][1] = 0.0;
strip[i][2][2] = edgelist[i][1][1] + wallextension * dy - ny;
strip[i][3][0] = strip[i][2][0];
strip[i][3][1] = wallheight;
strip[i][3][2] = strip[i][2][2];
strip[i][4][0] = edgelist[i][1][0] + wallextension * dx + nx;
strip[i][4][1] = 0.0;
strip[i][4][2] = edgelist[i][1][1] + wallextension * dy + ny;
strip[i][5][0] = strip[i][4][0];
strip[i][5][1] = wallheight;
strip[i][5][2] = strip[i][4][2];
strip[i][6][0] = edgelist[i][0][0] - wallextension * dx + nx;
strip[i][6][1] = 0.0;
strip[i][6][2] = edgelist[i][0][1] - wallextension * dy + ny;
strip[i][7][0] = strip[i][6][0];
strip[i][7][1] = wallheight;
strip[i][7][2] = strip[i][6][2];
strip[i][8][0] = strip[i][0][0];
strip[i][8][1] = strip[i][0][1];
strip[i][8][2] = strip[i][0][2];
strip[i][9][0] = strip[i][1][0];
strip[i][9][1] = strip[i][1][1];
strip[i][9][2] = strip[i][1][2];
// generate some different colors for the vertices
for (k = 0; k < 10; k++)
{
colorDB.setColor4f("Blue",1.0,stripColor[i][k]);
}
}
for (i = 0; i < numDoorStrips; i++)
{
dx = dooredge[i][1][0] - dooredge[i][0][0];
dy = dooredge[i][1][1] - dooredge[i][0][1];
norm = sqrt(dx*dx + dy*dy);
dx = wallwidth * dx / norm;
dy = wallwidth * dy / norm;
nx = -dy;
ny = dx;
// convert each edge to quad doorstrip
doorstrip[i][0][0] = dooredge[i][0][0] - wallextension * dx - nx;
doorstrip[i][0][1] = 0.67*wallheight;
doorstrip[i][0][2] = dooredge[i][0][1] - wallextension * dy - ny;
doorstrip[i][1][0] = doorstrip[i][0][0];
doorstrip[i][1][1] = wallheight;
doorstrip[i][1][2] = doorstrip[i][0][2];
doorstrip[i][2][0] = dooredge[i][1][0] + wallextension * dx - nx;
doorstrip[i][2][1] = 0.67*wallheight;
doorstrip[i][2][2] = dooredge[i][1][1] + wallextension * dy - ny;
doorstrip[i][3][0] = doorstrip[i][2][0];
doorstrip[i][3][1] = wallheight;
doorstrip[i][3][2] = doorstrip[i][2][2];
doorstrip[i][4][0] = dooredge[i][1][0] + wallextension * dx + nx;
doorstrip[i][4][1] = 0.67*wallheight;
doorstrip[i][4][2] = dooredge[i][1][1] + wallextension * dy + ny;
doorstrip[i][5][0] = doorstrip[i][4][0];
doorstrip[i][5][1] = wallheight;
doorstrip[i][5][2] = doorstrip[i][4][2];
doorstrip[i][6][0] = dooredge[i][0][0] - wallextension * dx + nx;
doorstrip[i][6][1] = 0.67*wallheight;
doorstrip[i][6][2] = dooredge[i][0][1] - wallextension * dy + ny;
doorstrip[i][7][0] = doorstrip[i][6][0];
doorstrip[i][7][1] = wallheight;
doorstrip[i][7][2] = doorstrip[i][6][2];
doorstrip[i][8][0] = doorstrip[i][0][0];
doorstrip[i][8][1] = doorstrip[i][0][1];
doorstrip[i][8][2] = doorstrip[i][0][2];
doorstrip[i][9][0] = doorstrip[i][1][0];
doorstrip[i][9][1] = doorstrip[i][1][1];
doorstrip[i][9][2] = doorstrip[i][1][2];
// generate some different colors for the vertices
for (k = 0; k < 10; k++)
{
colorDB.setColor4f("Blue",1.0,doorstripColor[i][k]);
}
}
}
//***************************************************************************
// draw the maze and floor
void drawMaze()
{
int i, j;
float x, z;
if (helpflag)
{
printhelpScreen();
return;
}
initMazeColor();
if (textureflag)
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 4);
}
for (i = 0; i < numEdges; i++)
{
glBegin(GL_QUAD_STRIP);
for (j = 0; j < 10; j++)
{
if (textureflag)
{
if ((strip[i][j][0] == strip[i][j+1][0]) && (strip[i][j][0] == strip[i][j+2][0]))
glTexCoord2f(strip[i][j][2], strip[i][j][1]);
else
glTexCoord2f(strip[i][j][0], strip[i][j][1]);
}
else
{
glMaterialfv(GL_FRONT, GL_DIFFUSE, stripColor[i][j]);
glColor3fv(stripColor[i][j]);
}
glVertex3fv(strip[i][j]);
}
glEnd();
}
for (i = 0; i < numDoorStrips; i++)
{
glBegin(GL_QUAD_STRIP);
for (j = 0; j < 10; j++)
{
if (textureflag)
{
if ((doorstrip[i][j][0] == doorstrip[i][j+1][0]) && (doorstrip[i][j][0] == doorstrip[i][j+2][0]))
glTexCoord2f(doorstrip[i][j][2], doorstrip[i][j][1]);
else
glTexCoord2f(doorstrip[i][j][0], doorstrip[i][j][1]);
}
else
{
glMaterialfv(GL_FRONT, GL_DIFFUSE, doorstripColor[i][j]);
glColor3fv(doorstripColor[i][j]);
}
glVertex3fv(doorstrip[i][j]);
}
glEnd();
glBegin(GL_QUADS);
glVertex3fv(doorstrip[i][0]);
glVertex3fv(doorstrip[i][2]);
glVertex3fv(doorstrip[i][4]);
glVertex3fv(doorstrip[i][6]);
glEnd();
}
if (textureflag)
glDisable(GL_TEXTURE_2D);
// Draw the Floor
colorDB.setColor4f("White",1.0,floorColor);
glBegin(GL_POLYGON);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, floorColor);
glVertex3f(Xmin, 0.0, Zmin);
glVertex3f(Xmax, 0.0, Zmin);
glVertex3f(Xmax, 0.0, Zmax);
glVertex3f(Xmin, 0.0, Zmax);
glVertex3f(Xmin, 0.0, Zmin);
glEnd();
if (!popView) // Draw the Ceiling
{
glBegin(GL_POLYGON);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, floorColor);
glVertex3f(Xmin, wallheight, Zmin);
glVertex3f(Xmax, wallheight, Zmin);
glVertex3f(Xmax, wallheight, Zmax);
glVertex3f(Xmin, wallheight, Zmax);
glVertex3f(Xmin, wallheight, Zmin);
glEnd();
for (i = 0; i < numObjects; i++)
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, i+1);
if (tableOrientation == 0) // North
drawTableAndChair(objects[i][0], objects[i][1], 0.0);
else // South
drawTableAndChair(objects[i][0], objects[i][1], 180.0);
glDisable(GL_TEXTURE_2D);
}
facecube(17.6,4.6, 5); // Dr. Sharma's face
facecube(24.5, 1.5, 6); // Dr. Plassmann's face
}
}
//***************************************************************************
// display function resets MODELVIEW matrix and draws everything
void display(void)
{
GLfloat angle, ybounce;
glutSetWindow(winIdMain);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if (!popView) // Normal view
{
gluLookAt(0.0, 0.0, 0.0, /// eye is at (0,0,0)
0.0, 0.0, -100.0, //center is at (0,0,-100)
0.0, 1.0, 0.); // up is in positive Y direction
glPushMatrix();
glRotatef(yAngle, 0.0, 1.0, 0.0);
glTranslatef(-xPosition, -yPosition, -zPosition);
}
else // Pop-up view
{
gluLookAt(Xmax / 2, zoom, Zmax / 2, // eye is at (0,0,0)
0.0, 0.0, 0.0, // center is at (0,0,-100)
0.0, 1.0, 0.); // up is in positive Y direction
glRotatef(yAnglePopup, 0.0, 1.0, 0.0);
glTranslatef(-Xmax / 2, 0.0, -Zmax / 2);
}
// draws objects in popup mode, start, finish, your position, and direction
if (popView)
facecube(xGlobal+0.1, yGlobal+0.1, 7);
glLightfv(GL_LIGHT1, GL_AMBIENT, lightOneColor);
glLightfv(GL_LIGHT1, GL_POSITION, lightOnePosition);
glEnable(GL_LIGHT1);
glLightfv(GL_LIGHT2, GL_DIFFUSE, lightTwoColor);
glLightfv(GL_LIGHT2, GL_POSITION, lightTwoPosition);
glEnable(GL_LIGHT2);
drawMaze();
glPopMatrix();
glutSwapBuffers();
subDisplay();
}
//***************************************************************************
// mouse click initiates movement
void mouse(int button, int state, int x, int y)
{
if (state == GLUT_DOWN)
{
if (button == GLUT_LEFT_BUTTON)
{
xStart = x;
yStart = y;
}
}
}
//***************************************************************************
// Make sure that we don't run into walls
// Note that we aren't doing the wall in the middle!
void checkIntersections(GLfloat xVec, GLfloat zVec)
{
int i;
GLfloat xCollision = -1.0, zCollision = -1.0;
for (i = 0; i < numEdges + numBoundingEdges; i++)
{
if (edgelist[i][0][0] == edgelist[i][1][0]) // vertical Z wall
{
if (edgelist[i][0][1] - safe < zPosition
&& zPosition < edgelist[i][1][1] + safe
|| edgelist[i][0][1] + safe > zPosition
&& zPosition > edgelist[i][1][1] - safe)
{
if ((xPosition < edgelist[i][0][0]
&& xPosition - xVec > edgelist[i][0][0] - safe)
|| (xPosition > edgelist[i][0][0]
&& xPosition - xVec < edgelist[i][0][0] + safe))
{
xCollision = edgelist[i][0][0];
break;
}
}
}
}
for (i = 0; i < numEdges + numBoundingEdges; i++)
{
if (edgelist[i][0][1] == edgelist[i][1][1]) // horizontal X wall
{
if (edgelist[i][0][0] - safe < xPosition
&& xPosition < edgelist[i][1][0] + safe
|| edgelist[i][0][0] + safe > xPosition
&& xPosition > edgelist[i][1][0] - safe)
{
if ((zPosition < edgelist[i][0][1]
&& zPosition + zVec > edgelist[i][0][1] - safe)
|| (zPosition > edgelist[i][0][1]
&& zPosition + zVec < edgelist[i][0][1] + safe))
{
zCollision = edgelist[i][0][1];
break;
}
}
}
}
if (IS_EQUAL(xCollision,-1.0))
xPosition -= xVec;
else
xPosition = (xVec < 0) ? xCollision - .25 : xCollision + .25;
if (IS_EQUAL(zCollision,-1.0))
zPosition += zVec;
else
zPosition = (zVec < 0) ? zCollision + .25 : zCollision - .25;
xCheck = fabs(xPosition - xEnd);
zCheck = fabs(zPosition - zEnd);
}
//***************************************************************************
// motion function -- we "pan" with an x motion, and we move forward/backward
// based on y motion
void motion(int x, int y)
{
double dx, dy, c, s;
static int motioncounter = 0;
++motioncounter;
if (initialMovement == 0)
{
initialMovement = 1;
startTime = glutGet((GLenum) GLUT_ELAPSED_TIME);
}
dx = (double) (x - xStart);
dy = (double) (y - yStart);
yAngle += 0.3 * dx;
yAnglePopup += 0.3 * dx;
if (!popView)
{
xVec = 0.04 * sin(deg2rad * yAngle) * dy;
zVec = 0.04 * cos(deg2rad * yAngle) * dy;
if (!noWalls)
checkIntersections(xVec, zVec);
else
{
xPosition -= xVec;
zPosition += zVec;
}
}
/*
cout.setf(ios::fixed,ios::floatfield);
cout.precision(2);
cout << "\r(" << xPosition/x_scaling_factor << "," << zPosition/z_scaling_factor << ")";
cout.flush();
*/
int typeRequest = 0;
char keyWords[10] = "302";
Room *roomResult;
xGlobal = xPosition/x_scaling_factor;
yGlobal = zPosition/z_scaling_factor;
roomResult = (Room *) queryXML(typeRequest,keyWords, xGlobal, yGlobal);
if (roomResult->inRoom)
{
sprintf(infoString, "Room %d (%s)", roomResult->roomNumber, roomResult->introText);
renderRoom(roomResult);
}
else
{
sprintf(infoString, "You are in the corridor");
}
xStart = x;
yStart = y;
glutPostRedisplay();
}
//***************************************************************************
// Initialize background, lights, materials, some global variables.
void init(void)
{
sprintf(infoString, "You are in the corridor");
glClearColor(0.0, 0.05, 0.0, 0.0);
//glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
// Enable a red OpenGL light.
glLightfv(GL_LIGHT0, GL_AMBIENT, lightZeroColor);
glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition);
glEnable(GL_LIGHT0);
// Enable lighting
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
glEnable(GL_LIGHTING);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
// initial angles and positions
yAngle = 0.0;
yAnglePopup = 0.0;
xPosition = 1.0;
yPosition = 1.0;
zPosition = 8.0;
// Enable a green OpenGL light.
addTextureFromFile("texture2.rgb"); // Texture #2
addTextureFromFile("tabletexture.rgb"); // Texture #1
addTextureFromFile("walltexture.rgb"); // Texture #3
addTextureFromFile("walltexture2.rgb"); // Texture #4
addTextureFromFile("sharma.rgb"); // Texture #5
addTextureFromFile("plassmann.rgb"); // Texture #6
addTextureFromFile("person.rgb"); // Texture #7
initMaze();
}
//***************************************************************************
// Window reshape function
void reshape(int width, int height)
{
WIDTH = width; HEIGHT = height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (float) width / (float) height, 0.05, 100.0);
glMatrixMode(GL_MODELVIEW);
glutSetWindow(winIdSub);
glutReshapeWindow(width-10, height/10);
glutPositionWindow(5, 5);
glutSetWindow(winIdMain);
glutPostRedisplay();
}
//***************************************************************************
// Exit on escape from keyboard
void keyboard(unsigned char c, int x, int y)
{
switch (tolower(c))
{
case 27: // ESC character
case 'q':
cout << endl;
exit(0);
break;
case '1':
whichMaze = 1;
init();
glutPostRedisplay();
break;
case '2':
whichMaze = 2;
init();
glutPostRedisplay();
break;
case '3':
whichMaze = 3;
init();
glutPostRedisplay();
break;
case 'v': // To change to popup or back
glutSetWindow(winIdSub);
if (!popView)
{
popCount++;
tempAngle = yAngle;
yAnglePopup = tempAnglePopup;
glutHideWindow();
}
else
{
yAngle = tempAngle;
tempAnglePopup = yAnglePopup;
glutShowWindow();
glutSetWindow(winIdMain);
reshape(WIDTH, HEIGHT);
}
popView = (!popView);
break;
case 'w':
noWalls = (noWalls + 1) % 2;
break;
case 't':
textureflag = (!textureflag);
break;
default:
break;
}
}
//***************************************************************************
void key(int key, int x, int y)
{
switch(key)
{
case GLUT_KEY_F1:
helpflag = (!helpflag);
glutSetWindow(winIdSub);
if (helpflag)
{
glutHideWindow();
}
else
{
glutShowWindow();
glutSetWindow(winIdMain);
reshape(WIDTH, HEIGHT);
}
break;
case GLUT_KEY_LEFT:
xStart = 0;
yStart = 0;
motion(-20, 0);
break;
case GLUT_KEY_RIGHT:
xStart = 0;
yStart = 0;
motion(20, 0);
break;
case GLUT_KEY_UP:
if (!popView)
{
xStart = 0;
yStart = 0;
motion(0, -10);
}
else
{
if (zoom <= 5.0)
zoom = 5.0;
else
zoom -= 5.0;
}
break;
case GLUT_KEY_DOWN:
if (!popView)
{
xStart = 0;
yStart = 0;
motion(0, 10);
}
else
{
if (zoom >= 100.0)
zoom = 100.0;
else
zoom += 5.0;
}
break;
}
}
//***************************************************************************
int main(int argc, char **argv)
{
addColors();
glutInitWindowSize(WIDTH, HEIGHT);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glEnable(GL_DEPTH_TEST);
winIdMain = glutCreateWindow("Kiosk");
if (argc == 2)
{
inpFlag = 1;
strcpy(inpFile, argv[1]);
}
// print some directions to screen
//print_help();
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutSpecialFunc(key);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutIdleFunc(idle);
winIdSub = glutCreateSubWindow(winIdMain, 5, 5, WIDTH-10, HEIGHT/10);
glutDisplayFunc(subDisplay);
glutReshapeFunc(subreshape);
glutSetWindow(winIdSub);
glutShowWindow();
//glutSetWindow(winIdMain);
glutMainLoop();
return 0;
}
//***************************************************************************
float OrientPointer(float xVec, float zVec)
{
return rad2deg * atan2(-zVec, -xVec);
}
//***************************************************************************
void addColors()
{
colorDB.init(20);
colorDB.addColor("Background", 255, 255, 255);
colorDB.addColor("White", 255, 255, 255);
colorDB.addColor("Black", 0, 0, 0);
colorDB.addColor("Red", 255, 0, 0);
colorDB.addColor("Green", 0, 255, 0);
colorDB.addColor("Blue", 0, 0, 255);
colorDB.addColor("Yellow", 255, 255, 0);
colorDB.addColor("Orange", 255, 128, 0);
colorDB.addColor("Brown", 165, 42, 42);
colorDB.addColor("RedTinted", 255, 77, 51);
}
//***************************************************************************
void print_help()
{
cout << "====================Keyboard Help===========================" << endl;
cout << " F1: help" << endl;
cout << " 1: Switch to maze 1 (maze1.dat)" << endl;
cout << " 2: Switch to maze 2 (maze2.dat)" << endl;
cout << " 3: Switch to maze 3 (maze3.dat)" << endl;
cout << " V: Toggle between POP-UP view of maze" << endl;
cout << " W: Allows to go through the walls" << endl;
cout << " arrow keys: Move around the maze" << endl;
cout << " Esc/Q: Quit" << endl;
cout << "============================================================" << endl;
cout << "Using the LEFT MOUSE BUTTON: maneuvers you through the maze." << endl;
cout << "============================================================" << endl;
}
//***************************************************************************
void readMazeFromFile()
{
int i;
char name[30];
if (inpFlag) // Filename specified as argument to program
{
ifstream inp(inpFile);
if (!inp)
{
cout << "Cannot read maze from file \"" << inpFile
<< "\"....exiting!" << endl;
exit(-1);
}
strcpy(name,inpFile);
inpFlag = 0;
}
else
strcpy(name,filename[whichMaze-1]);
ifstream inp(name);
if (!inp)
{
cerr << "Couldn't open file \"" << name << "\"!!!"
<< endl;
return;
}
cout << "Reading plan from file \"" << name << "\".....";
cout.flush();
inp >> Xmin;
inp >> Zmin;
inp >> Xmax;
inp >> Zmax;
inp >> numEdges;
Xmin *= x_scaling_factor;
Zmin *= z_scaling_factor;
Xmax *= x_scaling_factor;
Zmax *= z_scaling_factor;
for (i = 0; i < numEdges; i++)
{
inp >> edgelist[i][0][0];
inp >> edgelist[i][0][1];
inp >> edgelist[i][1][0];
inp >> edgelist[i][1][1];
edgelist[i][0][0] *= x_scaling_factor;
edgelist[i][0][1] *= z_scaling_factor;
edgelist[i][1][0] *= x_scaling_factor;
edgelist[i][1][1] *= z_scaling_factor;
}
// Remove duplicate edges
int edgecount = 0;
for (i = 0; i < numEdges; i++)
{
myEdges[i].x1 = edgelist[i][0][0];
myEdges[i].x2 = edgelist[i][1][0];
myEdges[i].y1 = edgelist[i][0][1];
myEdges[i].y2 = edgelist[i][1][1];
}
qsort(myEdges,numEdges,sizeof(myEdge), compareEdge);
for (i = 1; i < numEdges; i++)
{
edgelist[edgecount][0][0] = myEdges[i-1].x1;
edgelist[edgecount][1][0] = myEdges[i-1].x2;
edgelist[edgecount][0][1] = myEdges[i-1].y1;
edgelist[edgecount][1][1] = myEdges[i-1].y2;
++edgecount;
if ((myEdges[i].x1 == myEdges[i-1].x1) &&
(myEdges[i].x2 == myEdges[i-1].x2) &&
(myEdges[i].y1 == myEdges[i-1].y1) &&
(myEdges[i].y2 == myEdges[i-1].y2))
--edgecount;
}
/*
cout << "Number of given edges = " << numEdges;
cout << " (Number of unique edges = " << edgecount << ")" << endl;
cout.flush();
*/
numEdges = edgecount;
inp >> numDoorStrips;
for (i = 0; i < numDoorStrips; i++)
{
inp >> dooredge[i][0][0];
inp >> dooredge[i][0][1];
inp >> dooredge[i][1][0];
inp >> dooredge[i][1][1];
dooredge[i][0][0] *= x_scaling_factor;
dooredge[i][0][1] *= z_scaling_factor;
dooredge[i][1][0] *= x_scaling_factor;
dooredge[i][1][1] *= z_scaling_factor;
}
inp >> numObjects;
numBoundingEdges = 0;
for (i = 0; i < numObjects; i++)
{
inp >> objects[i][0];
inp >> objects[i][1];
inp >> objectType[i];
objects[i][0] *= x_scaling_factor;
objects[i][1] *= z_scaling_factor;
if (objectType[i] == 2) // table and chair
setBoundingBox(objects[i][0], objects[i][1]);
}
inp >> xBegin;
inp >> zBegin;
inp >> xEnd;
inp >> zEnd;
xBegin *= x_scaling_factor;
zBegin *= z_scaling_factor;
xEnd *= x_scaling_factor;
zEnd *= z_scaling_factor;
inp.close();
cout << "done!" << endl;
}
//***************************************************************************
void printRoom(Room *ptr)
{
// printf("\n Room in = %d ", ptr->inRoom);
printf("\n Room number = %d ", ptr->roomNumber);
printf("\n Professor = %s",ptr->professorName);
printf("\n introText = %s ", ptr->introText);
printf("\n research = %s ", ptr->research);
printf("\n publications = %s",ptr->publications);
printf("\n texture = %s",ptr->texture);
printf("\n image = %s",ptr->image);
printf("\n");
/*
printf("\n numWalls = %d ", ptr->numWalls);
printf("\n roomX1 = %.2f",ptr->roomX1);
printf("\n roomX2 = %.2f ", ptr->roomX2);
printf("\n roomX3 = %.2f",ptr->roomX3);
printf("\n roomX4 = %.2f ", ptr->roomX4);
printf("\n roomX5 = %.2f",ptr->roomX5);
printf("\n roomX6 = %.2f ", ptr->roomX6);
printf("\n roomX7 = %.2f",ptr->roomX7);
printf("\n roomX8 = %.2f ", ptr->roomX8);
printf("\n roomX9 = %.2f",ptr->roomX9);
printf("\n roomX10= %.2f ",ptr->roomX10);
printf("\n roomY1 = %.2f",ptr->roomY1);
printf("\n roomY2 = %.2f ", ptr->roomY2);
printf("\n roomY3 = %.2f",ptr->roomY3);
printf("\n roomY4 = %.2f ", ptr->roomY4);
printf("\n roomY5 = %.2f",ptr->roomY5);
printf("\n roomY6 = %.2f ", ptr->roomY6);
printf("\n roomY7 = %.2f",ptr->roomY7);
printf("\n roomY8 = %.2f ",ptr->roomY8);
printf("\n roomY9 = %.2f",ptr->roomY9);
printf("\n roomY10= %.2f ", ptr->roomY10);
printf("\n centerX= %.2f",ptr->centerX);
printf("\n centerY= %.2f ", ptr->centerY);
printf("\n tableX= %.2f",ptr->tableX);
printf("\n tableY= %.2f ", ptr->tableY);
printf("\n normalTable= %s",ptr->normalTable);
printf("\n lightX= %f ", ptr->lightX);
printf("\n lightY= %f",ptr->lightY);
*/
}
//***************************************************************************
int addTextureFromFile(char *filename)
{
int width, height, n_comp;
static int numTex = 0;
ifstream inp(filename);
if (!inp)
{
cout << "Cannot read texture file \"" << filename
<< "\"....skipping!" << endl;
return -1;
}
inp.close();
GLubyte *imageData = (GLubyte *) read_texture(filename, &width, &height,
&n_comp);
cout << "Reading texture from file \"" << filename << "\" (" << width
<< "x" << height << "x" << n_comp << ")" << endl;
#define WIDTH 256
#define HEIGHT 256
GLubyte newimg[WIDTH][HEIGHT][4];
gluScaleImage(GL_RGBA, width, height, GL_UNSIGNED_BYTE, imageData,
WIDTH, HEIGHT, GL_UNSIGNED_BYTE, newimg);
++numTex;
glBindTexture(GL_TEXTURE_2D, numTex);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D,0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA,
GL_UNSIGNED_BYTE, newimg);
#undef WIDTH
#undef HEIGHT
}
/****************************************************************************/
static int compareEdge(const void *e1, const void *e2)
{
myEdge *E1, *E2;
E1 = (myEdge *) e1;
E2 = (myEdge *) e2;
double cmp = 1000*(E1->x1 - E2->x1) + 100*(E1->x2 - E2->x2) +
10*(E1->y1 - E2->y1) + (E1->y2 - E2->y2);
if ((E1->x1 == E2->x1) && (E1->x2 == E2->x2) && (E1->y1 == E2->y1)
&& (E1->y2 == E2->y2))
return 0;
else if (cmp > 0.0)
return +1;
else if (cmp < 0.0)
return -1;
}
/****************************************************************************/
void printstring(void *font, char *string)
{
int len,i;
len=(int)strlen(string);
for(i=0;i<len;i++)
glutBitmapCharacter(font,string[i]);
}
/****************************************************************************/
void printhelpScreen(void)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-0.5,639.5,-0.5,479.5,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//glColor4f(255,255,255,1.0);
//glClearColor(255,255,255,1.0);
glRasterPos2i(60,420);
printstring(GLUT_BITMAP_TIMES_ROMAN_24,"F1 -Help");
glRasterPos2i(60,370);
printstring(GLUT_BITMAP_TIMES_ROMAN_24,"V - Toggle Between POP-UP view of maze");
glRasterPos2i(60,320);
printstring(GLUT_BITMAP_TIMES_ROMAN_24,"T - To Toggle Texture");
glRasterPos2i(60,270);
printstring(GLUT_BITMAP_TIMES_ROMAN_24,"W - Allows to go through the walls ");
glRasterPos2i(60,220);
printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Arrow Keys - Move Around the Maze");
glRasterPos2i(60,70);
printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Esc/Q : QUIT");
glRasterPos2i(60,170);
printstring(GLUT_BITMAP_TIMES_ROMAN_24," Optional {Use The Left Mouse Button :");
glRasterPos2i(100,120);
printstring(GLUT_BITMAP_TIMES_ROMAN_24," To Maneuver through the maze}");
}
//***************************************************************************
void initMazeColor(void)
{
glClearColor(0.0, 0.05, 0.0, 0.0);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
// Enable a red OpenGL light.
glLightfv(GL_LIGHT0, GL_AMBIENT, lightZeroColor);
glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition);
glEnable(GL_LIGHT0);
// Enable lighting
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
glEnable(GL_LIGHTING);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
}
//***************************************************************************
void setBoundingBox(float x, float z)
{
numBoundingEdges++;
edgelist[numEdges + numBoundingEdges - 1][0][0] = x;
edgelist[numEdges + numBoundingEdges - 1][0][1] = z;
edgelist[numEdges + numBoundingEdges - 1][1][0] = x + 1.1;
edgelist[numEdges + numBoundingEdges - 1][1][1] = z;
numBoundingEdges++;
edgelist[numEdges + numBoundingEdges - 1][0][0] = x;
edgelist[numEdges + numBoundingEdges - 1][0][1] = z + 1.0;
edgelist[numEdges + numBoundingEdges - 1][1][0] = x + 1.1;
edgelist[numEdges + numBoundingEdges - 1][1][1] = z + 1.0;
numBoundingEdges++;
edgelist[numEdges + numBoundingEdges - 1][0][0] = x + 1.0;
edgelist[numEdges + numBoundingEdges - 1][0][1] = z + 1.0;
edgelist[numEdges + numBoundingEdges - 1][1][0] = x + 1.0;
edgelist[numEdges + numBoundingEdges - 1][1][1] = z;
numBoundingEdges++;
edgelist[numEdges + numBoundingEdges - 1][0][0] = x + 1.1;
edgelist[numEdges + numBoundingEdges - 1][0][1] = z;
edgelist[numEdges + numBoundingEdges - 1][1][0] = x;
edgelist[numEdges + numBoundingEdges - 1][1][1] = z;
}
//***************************************************************************
void facecube(float tx, float tz, int texnum)
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texnum);
glPushMatrix();
glTranslatef(tx*x_scaling_factor,0.4,tz*z_scaling_factor);
cube(1.0,1.0,1.0,1.0,0.0,0.0,0.0);
glPopMatrix();
glDisable(GL_TEXTURE_2D);
}
//***************************************************************************
void subDisplay(void)
{
char label[100];
glutSetWindow(winIdSub);
glClearColor(0.25, 0.25, 0.25, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(0.0, 1.0, 0.0);
// Draw Box
glBegin(GL_LINE_LOOP);
glVertex2f(-0.999F, -0.99F);
glVertex2f(-0.999F, +0.99F);
glVertex2f(+0.999F, +0.99F);
glVertex2f(+0.999F, -0.99F);
glEnd();
// Draw Text info
colorDB.setglColor3f("White");
float xf = (WIDTH-450)*1.0/WIDTH-1.0;
float yf = 0.1*WIDTH/HEIGHT;
if (xf < -0.97)
xf = -0.97;
xf = -0.5-strlen(infoString)*4.3/WIDTH + 0.2;
glRasterPos2f(xf, yf);
drawString(infoString);
glutSwapBuffers();
}
//***************************************************************************
// SubWindow reshape function
void subreshape(int w, int h)
{
glViewport(0, 0, w, h);
}
//***************************************************************************
void drawString(char *s)
{
double curpos[4];
colorDB.setglColor3f("White");
glGetDoublev(GL_CURRENT_RASTER_POSITION, curpos);
glRasterPos2f(2*curpos[0]/(WIDTH-10)-1.0, 2*curpos[1]/(HEIGHT/10)-1.0);
unsigned int i;
for (i = 0; i < strlen(s); i++)
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, s[i]);
}
//***************************************************************************
void renderRoom(Room *room)
{
static int callonce = 0;
if (room->tableX == 0.0 && room->tableY == 0.0) // Compute table co-ordinates
// automatically
{
room->tableX = (room->roomX1+room->roomX2+room->roomX3+room->roomX4+room->roomX5+room->roomX6)/6.0;
room->tableY = (room->roomY1+room->roomY2+room->roomY3+room->roomY4+room->roomY5+room->roomY6)/6.0;
}
else if (room->tableX == -1.0 && room->tableY == -1.0) // No table
return;
if (room->tableY > 2.7)
tableOrientation = 1; // South
else
tableOrientation = 0; // North
int i = 0;
numObjects = 1;
/*
if (strcmp(room->normalTable,"North") == 0)
tableOrientation = 0; // North
else
tableOrientation = 1; // South
*/
objects[i][0] = room->tableX;
objects[i][1] = room->tableY;
objectType[i] = 2;
objects[i][0] *= x_scaling_factor;
objects[i][1] *= z_scaling_factor;
if (objectType[i] == 2) // table and chair
setBoundingBox(objects[i][0], objects[i][1]);
char command[200];
if (callonce == 0)
{
sprintf(command,"netscape-remote %s &",room->publications);
// sprintf(command,"c:\\Progra~1\\Intern~1\\iexplore.exe %s &",room->publications);
system(command);
}
++callonce;
}
//***************************************************************************