/* robot.c + file.c -> robot By: Andrew Wiles SSN: 215-15-5027 3/31/97 This is the main file for the robot assignment. It does all of the translations and everything else Please note: The Makefile uses the Mesa routines in Dr. Kumar's directory - because they work. Making destination 'a' will use the dynamic librires stored on hops, but they cause seg-faults. */ #include #include #include #include #include #include #include #include "robot.h" robotptr obj; static int shoulder = 0, elbow = 0, istate, ix, iy; static int camera = 0, ibutton; robotptr selpiece; void agvMakeAxesList(); void init(void) { /* Initialize function called from main() */ glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); } void display(void) { /* Display function */ int i; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); render(&i, obj); /* This function actually draws the robot */ renderbot(obj, GL_RENDER); glPopMatrix(); glutSwapBuffers(); } void renderbot(robotptr pres, GLenum mode) { int i; glPushMatrix(); /* Translate to the attachment position */ glTranslatef(pres->attach.x, pres->attach.y, pres->attach.z); /* Apply any rotations */ glRotatef(pres->rotate.x, 1.0, 0.0, 0.0); glRotatef(pres->rotate.y, 0.0, 1.0, 0.0); glRotatef(pres->rotate.z, 0.0, 0.0, 1.0); /* Translate from the hotspot (the attachment) to the center to create the box */ glTranslatef(-pres->hotspot.x, -pres->hotspot.y, -pres->hotspot.z); glPushMatrix(); glScalef(pres->geom.vert[0].x, pres->geom.vert[0].y, pres->geom.vert[0].z); glColor3f(pres->color.x, pres->color.y, pres->color.z); /* Used for mouse handling */ if(mode == GL_SELECT) glLoadName((GLint) pres); glutSolidCube(1.0); glPopMatrix(); /* Recurse through all children */ for(i = 0; i < pres->attachm; i++) renderbot(pres->children[i], mode); glPopMatrix(); } void reshape(int w, int h) { /* Called if the window is resized - doesn't seem to work though */ /*float m[16]; int i;*/ glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(80.0, (GLfloat) w/ (GLfloat) h, 1.0, 200.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -5.0); glutPostRedisplay(); } void clearrot(robotptr pres) { /* Clear the rotation matricies - used to return to normal */ int i; pres->rotate.x = 0.0; pres->rotate.y = 0.0; pres->rotate.z = 0.0; for(i = 0; i < pres->attachm; i++) clearrot(pres->children[i]); } void keyboard(unsigned char key, int x, int y) { /* Keyboard handler - most functions here are archaic - the only ones that still do anything are t and T */ switch(key) { case 's': shoulder = (shoulder + 5) % 360; glutPostRedisplay(); break; case 'S': shoulder = (shoulder - 5) % 360; glutPostRedisplay(); break; case 'e': elbow = (elbow + 5) % 360; glutPostRedisplay(); break; case 'E': elbow = (elbow - 5) % 360; glutPostRedisplay(); break; case 'c': camera += 2; glutPostRedisplay(); break; case 'C': gluLookAt(0.0, 0.0, (GLfloat) -2, 0.0, 0.0, -100.0, 0.0, 1.0, 0.0); camera -= 2; glutPostRedisplay(); break; case 'T': clearrot(obj); case 't': glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(80.0, 1.0, 1.0, 200.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -5.0); glutPostRedisplay(); break; default: break; } } robotptr processHits(GLint hits, GLuint buffer[]) { /* Processes the mouse stuff - finds the active object using labeling */ unsigned int i, j; GLuint names, *ptr; int lowest = INT_MAX; int lowass = 0; int lowname; /* Process the hits */ if(hits == 0) return 0; ptr = (GLuint *) buffer; for(i = 0; i < hits; i++) { names = *ptr; ptr++; if(*ptr < lowest) { lowest = *ptr; lowass = i; } ptr++; if(*ptr < lowest) { lowest = *ptr; lowass = i; } ptr++; for(j = 0; j < names; j++) { if(i == lowass) lowname = *ptr; ptr++; } } /* The name is actually a pointer to the correct structure for the give piece */ return (robotptr) lowname; } void mouse(int button, int state, int x, int y) { /* The mouse handling function - sets up a labeled set of objects and finds when the mouse is inside a particular object */ GLint viewport[4]; /*GLdouble mvmatrix[16], projmatrix[16]; GLint realy; GLdouble wx, wy, wz; GLdouble nx, ny, nz; robotptr tmp;*/ static GLuint selectBuf[512]; GLint hits; if(state == GLUT_DOWN) { istate = TRUE; ibutton = button; ix = x; iy = y; if(button == GLUT_RIGHT_BUTTON) return; /* Set up the labeling */ glGetIntegerv(GL_VIEWPORT, viewport); glSelectBuffer(512, selectBuf); glRenderMode(GL_SELECT); glInitNames(); glPushName(0); glLoadName(0); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluPickMatrix((GLdouble) x, (GLdouble) (viewport[3] - y), 5.0, 5.0, viewport); gluPerspective(80.0, (GLfloat) viewport[2]/ (GLfloat) viewport[3], 1.0, 200.0); glMatrixMode(GL_MODELVIEW); /* Render the bot in select mode */ renderbot(obj, GL_SELECT); glMatrixMode(GL_PROJECTION); glPopMatrix(); glFlush(); glMatrixMode(GL_MODELVIEW); hits = glRenderMode(GL_RENDER); selpiece = processHits(hits, selectBuf); return; } else if(state == GLUT_UP) { istate = FALSE; } } void mousemove(int x, int y) { /* Handles mouse motion */ if(!istate) return; if(ibutton == GLUT_LEFT_BUTTON) { /* Left button - rotation around the pivot point and the x and y axes */ if(!selpiece) return; glPushMatrix(); glLoadIdentity(); rotaterec((GLfloat) ix - x, 0.0, 1.0, 0.0, selpiece); rotaterec((GLfloat) iy - y, 1.0, 0.0, 0.0, selpiece); glPopMatrix(); ix = x; iy = y; glutPostRedisplay(); } if(ibutton == GLUT_MIDDLE_BUTTON) { /* Middle button - rotatin around the pivot point and the y and z axes */ if(!selpiece) return; glPushMatrix(); glLoadIdentity(); rotaterec((GLfloat) ix - x, 0.0, 1.0, 0.0, selpiece); rotaterec((GLfloat) iy - y, 0.0, 0.0, 1.0, selpiece); glPopMatrix(); ix = x; iy = y; glutPostRedisplay(); } if(ibutton == GLUT_RIGHT_BUTTON) { /* Right button - scaling and x translation */ gluLookAt((GLdouble) ix - x, 0.0, (GLdouble) iy - y, (GLdouble) -(ix - x), 0.0, -100.0, 0.0, 1.0, 0.0); iy = y; ix = x; glutPostRedisplay(); } return; } void rotaterec(float theta, float x, float y, float z, robotptr pres) { /*GLdouble m[16];*/ static float itheta, ix, iy, iz; /*int i;*/ /* Rotate the object in pres by (theta, x, y, z) */ if(!itheta) { itheta = theta; ix = x; iy = y; iz = z; } /* Store the values for furture reference */ if(x > 0.0) pres->rotate.x = ((float)(((int)(pres->rotate.x + theta)) % 360)); if(y > 0.0) pres->rotate.y = ((float)(((int)(pres->rotate.y + theta)) % 360)); if(z > 0.0) pres->rotate.z = ((float)(((int)(pres->rotate.z + theta)) % 360)); } int main(int argc, char **argv) { /* Main function - sets up and calls appropriate functions */ /*float m[16];*/ int i=0; glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(500, 500); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMouseFunc(mouse); glutMotionFunc(mousemove); glMatrixMode(GL_MODELVIEW); /* If there's a command line or not */ if(argc <= 1) parse_robot("robot.disc"); else parse_robot(argv[1]); render(&i, obj); glutMainLoop(); return 0; }