/* Nicholas Dunn * Robot arm program */ #include #include #include #include #ifdef __APPLE__ #include #else #include #endif #define PI 3.14159265 GLfloat red[3] = {1.0, 0.0, 0.0}; GLfloat green[3] = {0.0, 1.0, 0.0}; GLfloat blue[3] = {0.0, 0.0, 1.0}; GLfloat black[3] = {0.0, 0.0, 0.0}; GLfloat white[3] = {1.0, 1.0, 1.0}; GLfloat gray[3] = {0.5, 0.5, 0.5}; GLfloat yellow[3] = {1.0, 1.0, 0.0}; GLfloat magenta[3] = {1.0, 0.0, 1.0}; GLfloat cyan[3] = {0.0, 1.0, 1.0}; GLint fillmode = 0; // Used for rotating to see surface GLfloat x_angle = 0.0, y_angle = 0.0, z_angle = 0.0; GLint shapeMode = 0; GLint numSegments = 10; GLfloat shoulderTheta = 0.0, elbowTheta = 0.0, wristTheta = 0.0, clawTheta = 0; GLfloat shoulderMin = -90.0, shoulderMax = 90.0; GLfloat elbowMin = -30.0, elbowMax = 95.0; GLfloat wristMin = -65.0, wristMax = 80.0; GLfloat clawMin = 0.0, clawMax = 60.0; GLfloat clawRadius = .5; GLint numClaws = 3; GLint jointRestrictions = 1; /* forward declarations of functions */ void display(void); void keypress(unsigned char key, int x, int y); void main_menu(int value); int main(int argc, char** argv) { /* open a window */ glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 500); glutInitWindowPosition(100,100); glutCreateWindow("Mechanical death machine"); /* OpenGL init */ glClearColor(0, 0, 0, 0); /* set background color black*/ glShadeModel(GL_FLAT); glEnable(GL_DEPTH_TEST); glMatrixMode(GL_PROJECTION); glLoadIdentity(); // glFrustum (-1.0, 2.0, -1.0, 2.0, //.5, 10.0); gluPerspective(60,1,1,15); glMatrixMode(GL_MODELVIEW); /* callback functions */ glutDisplayFunc(display); glutKeyboardFunc(keypress); glutCreateMenu(main_menu); glutAddMenuEntry("Fill/Outline", 1); glutAddMenuEntry("Quit", 3); glutAttachMenu(GLUT_LEFT_BUTTON); /* event handler */ glutMainLoop(); return 0; } void draw_cube(double length) { glutSolidCube(length); } void draw_triangle_covering(double sideLength, double offset, double elbowWidth) { glBegin(GL_POLYGON); glVertex3f(sideLength/2, sideLength/2, sideLength/2); glVertex3f(sideLength/2 + offset, 0, elbowWidth/2); glVertex3f(sideLength/2, -sideLength/2, sideLength/2); glEnd(); } void draw_robot_shoulder(double sideLength, double offset, double elbowWidth) { glColor3fv(blue); glPushMatrix(); glScalef(1.5,1,1); draw_cube(sideLength); glPopMatrix(); // draw a triangle covering up the joint on side close to camera glColor3fv(magenta); glTranslatef(.5,0,0); draw_triangle_covering(sideLength, offset, elbowWidth); glPushMatrix(); glRotatef(180,1,0,0); //glTranslatef(0,0,sideLength/2); draw_triangle_covering(sideLength, offset, elbowWidth); glPopMatrix(); } void draw_elbow(double elbowLength) { // draw the elbow box glColor3fv(green); draw_cube(elbowLength); } // Draws a semicircular pincer void draw_pincer(double angle, double r) { glPushMatrix(); glTranslatef(-r,0,0); glRotatef(angle,0,0,1); glTranslatef(r,0,0); glBegin(GL_LINE_STRIP); int i; for (i = 0; i < numSegments; i++) { double angle = PI * i / numSegments; // Shift over by the radius so that we rotate about an end point instead // of the circle's center glVertex2f(r*cos(angle), r*sin(angle)); } //glVertex2f(0,0); glEnd(); glPopMatrix(); } // Draw a 3 claw pincer void draw_claw(double angle, double radius) { glPushMatrix(); int i; for (i = 0; i < numClaws; i++) { glPushMatrix(); glColor3f(.2+(double)i/numClaws, 2*(double)i/numClaws, 3 * (double)i/numClaws); glRotatef(i*360.0/numClaws,1,0,0); draw_pincer(angle,radius); glPopMatrix(); } } void draw_cylinder(double r, double length) { glPushMatrix(); glRotatef(90,0,1,0); int i; for (i = 0; i < numSegments; i++) { double angle1 = 2 * PI * i / numSegments; double x1 = r*cos(angle1); double y1 = r*sin(angle1); double angle2 = 2 * PI * (i + 1) / numSegments; double x2 = r*cos(angle2); double y2 = r*sin(angle2); glBegin(GL_POLYGON); glColor3f((double)i/numSegments,(double)i/numSegments,(double)i/numSegments); glVertex3f(x1, y1, 0); glVertex3f(x1, y1, length); glVertex3f(x2, y2, length); glVertex3f(x2, y2, 0); glEnd(); } glPopMatrix(); } void draw_wrist(double length, double cylinderRadius, double cylinderLength) { glTranslatef(length/2,0,0); draw_cylinder(cylinderRadius, cylinderLength); // put the origin at the end of the cylinder glTranslatef(cylinderLength+.5,0,0); //draw_cube(length); draw_claw(clawTheta,clawRadius); } void draw_polygon(){ glLoadIdentity(); glClear(GL_DEPTH_BUFFER_BIT); glTranslatef (0.0, 0.0, -9.0); if (fillmode) { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } else { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } glRotatef(y_angle,0,1,0); // Draw main arm glRotatef(shoulderTheta,0,0,1); draw_robot_shoulder(2.0, 1.5, 1.0); // draw elbow glTranslatef(2.4,0,0); glRotatef(elbowTheta,0,0,1); draw_elbow(1.0); // draw wrist glRotatef(wristTheta,1,0,0); draw_wrist(1.0,.2,2.0); } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); draw_polygon(); /*glViewport(0,0,250,500); draw_polygon(); */ glViewport(0,0,500,500); /* execute the drawing commands */ glFlush(); } void keypress(unsigned char key, int a, int b) { switch(key) { case '9': exit(0); break; case 'w': shoulderTheta += 5; if (jointRestrictions && shoulderTheta > shoulderMax) {shoulderTheta = shoulderMax;} glutPostRedisplay(); break; case 's': shoulderTheta -= 5; if (jointRestrictions && shoulderTheta < shoulderMin) {shoulderTheta = shoulderMin;} glutPostRedisplay(); break; case 'a': elbowTheta -= 5; if (jointRestrictions && elbowTheta < elbowMin) {elbowTheta = elbowMin;} glutPostRedisplay(); break; case 'd': elbowTheta += 5; if (jointRestrictions && elbowTheta > elbowMax) {elbowTheta = elbowMax;} glutPostRedisplay(); break; case 'q': wristTheta -= 5; if (jointRestrictions && wristTheta < wristMin) {wristTheta = wristMin;} glutPostRedisplay(); break; case 'e': wristTheta += 5; if (jointRestrictions && wristTheta > wristMax) {wristTheta = wristMax;} glutPostRedisplay(); break; case 'o': clawTheta += 5; if (jointRestrictions && clawTheta > clawMax) {clawTheta = clawMax;} glutPostRedisplay(); break; case 'c': clawTheta -= 5; if (jointRestrictions && clawTheta < clawMin) {clawTheta = clawMin;} glutPostRedisplay(); break; case 'j': y_angle += 5; glutPostRedisplay(); break; case 'k': y_angle -= 5; glutPostRedisplay(); break; case '+': numSegments += 5; numClaws += 1; glutPostRedisplay(); break; case '-': numSegments -= 5; numClaws -=1; if (numClaws < 0) { numClaws = 0; } glutPostRedisplay(); break; } } void main_menu(int value) { switch (value){ case 1: /* toggle outline/fill */ fillmode = !fillmode; break; case 3: exit(0); } glutPostRedisplay(); }