#include <Body.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <iostream.h>
#include <unistd.h>
#include <userInterface.h>
#include <sys/time.h>
#define TEXTURE_DIR "textures/"
#define LINE_LENGTH 255
#define MAX_TREE_DEPTH 10
#define COMMENT_CHAR '#'
#define BODY_DELIM "."
#define AU 149597870
int checkArgs (int myargc, char **myargv);
void display ();
void init ();
Body* makeScene ();
void printUsage (char *progname);
int parseNames (char *fullname, char *names[MAX_TREE_DEPTH]);
void reshape (int w, int h);
int update ();
char planet_file[LINE_LENGTH];
int fileset = 0;
double disExp = 1.0, radExp = 0.1, masExp = 1.0,
orbExp = 1.0, rotExp = 1.0;
Body* root;
long int ltime = 0, timestep = 100000;
int main (int argc, char **argv) {
if (!checkArgs(argc, argv))
printUsage(argv[0]);
srand48(getpid());
glutInitWindowSize(900, 600);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutCreateWindow(argv[0]);
init();
glutReshapeFunc(reshape);
userInterfaceInit();
glutKeyboardFunc(keyboard);
root = makeScene();
root->setExp(disExp, radExp, masExp, orbExp, rotExp);
root->dump();
glutDisplayFunc(display);
glutMainLoop();
delete root;
return 0;
}
/* initialize state */
void init (void) {
GLfloat mat_diffuse[] = { 0.5, 0.5, 0.5, 1.0 };
GLfloat mat_specular[] = { 0.2, 0.2, 0.2, 1.0 }; /* white highlight */
GLfloat mat_shininess[] = { 50.0 };
GLfloat light_position[] = { 0.0, 0.0, 50.0, 0.0 };
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_SMOOTH);
glDepthFunc (GL_LESS);
glMaterialfv (GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv (GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv (GL_FRONT, GL_SHININESS, mat_shininess);
glLightfv (GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_NORMALIZE); /* Make my normals unit length for me. */
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
}
int update () {
struct timeval ctime;
gettimeofday(&ctime, NULL);
if (labs(ctime.tv_usec - ltime) > timestep) {
ltime = ctime.tv_usec;
return 1;
} else
return 0;
}
/* Clear window and draw surface. */
void display (void) {
GLfloat matrix[16];
static int curtime = 0;
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
glPushMatrix();
glLoadIdentity();
gluLookAt(0, 0, 65, 0, 0, 0, 0, 1, 0);
glRotatef(45.0, 1.0, 0.0, 0.0);
glMultMatrixf(matrix);
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
if (update()) {
curtime += 1.0;
root->draw((curtime + 1.0) / 5.0);
} else
root->draw((curtime + 1.0) / 5.0);
//cout << curtime << endl;
glDisable(GL_TEXTURE_2D);
glPopMatrix();
glutSwapBuffers();
}
/* Handle window resize. */
void reshape (int w, int h) {
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, 0, 0, 0, -1, 0, 1, 0);
}
Body* makeScene () {
char line[LINE_LENGTH], *names[MAX_TREE_DEPTH], fullname[50],
texture[25], texpath[50];
float dis, rad, mass, orb, rot;
Body *root = NULL, *parent = NULL, *child = NULL;
int cur_par = 0, name_cnt = 0;
FILE *fptr;
if (fileset)
fptr = fopen(planet_file, "r");
else
fptr = stdin;
while (fgets(line, LINE_LENGTH, fptr) != NULL) {
if (line[0] == COMMENT_CHAR || isspace(line[0])) {
while (fgets(line, LINE_LENGTH, fptr) != NULL) {
if (line[0] != COMMENT_CHAR && !isspace(line[0]))
break;
}
if (line[0] == COMMENT_CHAR || isspace(line[0]))
break;
}
sscanf(line, "%s %f %f %f %f %f %s\n", fullname,
&dis, &rad, &mass, &orb, &rot, texture);
parseNames(fullname, names);
strcpy(texpath, TEXTURE_DIR);
strcat(texpath, texture);
dis *= AU;
parent = root;
if (names[0] == NULL) {
cerr << "Invalid File Format: No Name" << endl;
exit(-1);
}
else if (root == NULL) {
root = new Body(names[0], dis, rad, mass, orb, rot, texpath);
parent = root;
}
else if (!strcmp(root->getName(), names[0])) {
name_cnt = 1;
while (names[name_cnt] != NULL) {
cur_par = parent->getChildByName(names[name_cnt]);
if (cur_par >= 0)
parent = parent->getChild(cur_par);
else if (names[name_cnt + 1] == NULL) {
child = new Body(names[name_cnt], dis, rad, mass, orb, rot, texpath);
parent->addChild(child);
child->setParent(parent);
} else {
cout << endl << line << endl;
cerr << "Invalid File Format: Bad Name Sequence" << endl;
exit(-1);
}
name_cnt++;
}
}
else {
cerr << "Invalid File Format: Bad Root" << endl;
exit(-1);
}
}
return root;
}
int parseNames (char *fullname, char *names[MAX_TREE_DEPTH]) {
char *ptr;
int len = 0, num = 0;
ptr = strtok(fullname, BODY_DELIM);
do {
len = strlen(ptr);
names[num] = new char[len + 1];
strncpy(names[num], ptr, len);
names[num][len] = 0;
ptr = strtok(NULL, BODY_DELIM);
num++;
} while (ptr != NULL);
names[num] = NULL;
return num;
}
// checkArgs() checks the command line arguments and assigns all variables
// not listed on command to zero.
int checkArgs(int myargc, char **myargv) {
int i;
for (i = 1; i < myargc; i += 2) {
if (i + 1 == myargc) return 0;
if (!strcmp(myargv[i], "-file")) {
strcpy(planet_file, myargv[i+1]);
fileset = 1;
}
else if (!strcmp(myargv[i], "-dis"))
disExp = atof(myargv[i+1]);
else if (!strcmp(myargv[i], "-rad"))
radExp = atof(myargv[i+1]);
else if (!strcmp(myargv[i], "-orb"))
orbExp = atof(myargv[i+1]);
else if (!strcmp(myargv[i], "-mass"))
masExp = atof(myargv[i+1]);
else if (!strcmp(myargv[i], "-rot"))
rotExp = atof(myargv[i+1]);
else if (!strcmp(myargv[i], "-help"))
return 0;
else if (!strcmp(myargv[i], "-h"))
return 0;
else
return 0;
}
return 1;
}
void printUsage(char *progname) {
cout << "Usage - " << endl;
exit(1);
}