//********************************************************************************/ // OpenGL program illustartes: hierarchical modeling, animation. // // OpenGL program that models the robot given in the handouts (cs453A). // The robot components are modeled by display lists, and positioned // using the modeling transformation. // // We can model hierarchically the robot as: // BODY // / \ // /T2.R2 \T3 // hand NECK // // where the hand is modeled hierarchicaly as: // hand // / // / arm_motion rotation // ARM // / // /T1 // wrist // where // // BODY, ARM, WHEEL are defined in display lists. // T2.R2 denotes the composition of a rotation, R2, followed by a // transpation T2 // // wrist flipping back and forth is modeled by // wrist // / wrist_motion rotation // WRIST // hand and robot are modeled by functions draw_robot() and draw_hand() // // wrist swings back and fort at R1_th angle // File: robot2D.cpp // Date: 2/17/2001 /*********************************************************************************/ #include #include #include #include // display lists identifiers #define BODY 1 #define ARM 2 #define WRIST 3 #define NECK 4 // model dimensions #define PI 3.141592 #define HALF_BODY_W 1.5 #define BODY_H 4.0 #define HALF_ARM_W 0.5 #define ARM_H 2.5 #define HALF_WRIST_BASE 0.75 #define HALF_MAX_WRIST_W 1.2 #define MIN_WRIST_H 0.5 #define WRIST_H 2.0 #define HALF_NECK_W 0.5 #define NECK_H 1.2 // globals: //translation parameters positioning NECK to BODY GLdouble T3_x = 0.0; GLdouble T3_y = BODY_H; //translation parameters positioning ARM to BODY GLdouble T2_x = 0.75*HALF_BODY_W; GLdouble T2_y = 0.85*BODY_H; // rotation angle for positioning arm GLdouble R2_th = -45.0; //rotation angle for arm motion GLdouble arm_motion = -20.0; // hand flips + and - this angle GLdouble arm_incr = 1; // arm incremet angle //translation parameters positionin WRIST to ARM GLdouble T1_x = 0.0; GLdouble T1_y = 0.85*ARM_H; //rotation angle for wrist motion GLdouble wrist_motion = 45.0; // wrist flips + and - this angle GLdouble wrist_incr = -1; // jumping motion parameters GLdouble speed_up = 2; GLdouble jump_x = 0.0; // initial x GLdouble jump_y = 0.0; // initial y GLdouble jump_incr_x = 1.0; GLdouble jump_incr_y = 1.0; GLsizei wnd_w = 500; // display window width GLsizei wnd_h = 500; // display window height //prototypes void myinit(); // OpenGL init void display(); // display callback void idle(); // idle callback void defineParts(void); // defines the display lists void draw_robot(); // draws the robot /****************/ /***** MAIN *****/ /****************/ int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB); glutInitWindowSize(wnd_w, wnd_h); glutInitWindowPosition(0,0); glutCreateWindow("the jumping robot from Hofstra"); myinit(); glutDisplayFunc(display); glutIdleFunc(idle); glutMainLoop(); return 0; } /********************************/ /***** FUNCTION DEFINITIONS *****/ /********************************/ /*********************************************************************************/ // OpenGL init /*********************************************************************************/ void myinit() { glClearColor(0.0,0.0,0.0,0.0); // black glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(-HALF_BODY_W, 4*(BODY_H+ARM_H+WRIST_H), 0.0,4*(BODY_H+ARM_H+WRIST_H)+HALF_BODY_W); // clipping window glMatrixMode(GL_MODELVIEW); defineParts(); } /*********************************************************************************/ // defines display lists for the individual components /*********************************************************************************/ void defineParts(void) { // wrist, // frame is right handed // origin is at midle of wrist base // y axis is the vertical axis of symmetry for the wrist glNewList(WRIST,GL_COMPILE); // begin WRIST glPushMatrix(); glPushAttrib(GL_COLOR); glColor3f(1.0,1.0,0.0); // wrist color glBegin(GL_TRIANGLE_STRIP); // counter clockwise going from // start at tip of left finger // and end at tip of right finger glVertex2f( -HALF_WRIST_BASE, WRIST_H); // left finger tip glVertex2f( -HALF_MAX_WRIST_W, MIN_WRIST_H); glVertex2f( -HALF_WRIST_BASE, WRIST_H/2); glVertex2f( -HALF_WRIST_BASE, 0.0); glVertex2f( 0.0, MIN_WRIST_H); glVertex2f( HALF_WRIST_BASE, 0.0); glVertex2f( HALF_WRIST_BASE, WRIST_H/2); glVertex2f( HALF_MAX_WRIST_W, MIN_WRIST_H); glVertex2f( HALF_WRIST_BASE, WRIST_H); // right finger tip glEnd(); glPopAttrib(); glPopMatrix(); glEndList(); // end WRIST // arm: // frame is right handed, origin at middle of base // coordinate axis are alingned with the axis of symmetry of // the arm (as in the picture in handout) glNewList(ARM, GL_COMPILE); // begin ARM glPushMatrix(); glPushAttrib(GL_COLOR); glColor3f(1.0,0.0,0.0); // arm color glBegin(GL_POLYGON); // vertices in counter clockwise glVertex2f( HALF_ARM_W, 0.0); glVertex2f( HALF_ARM_W, ARM_H); glVertex2f( -HALF_ARM_W, ARM_H); glVertex2f( -HALF_ARM_W, 0.0); glEnd(); glPopAttrib(); glPopMatrix(); glEndList(); // end ARM // body: // frame is right handed, origin at middle of base // coordinate axis are alingned with the axis of symmetry of // the body (as in the picture in handout) glNewList(BODY, GL_COMPILE); // begin BODY glPushMatrix(); glPushAttrib(GL_COLOR); glColor3f(1.0,0.0,0.0); // body color glBegin(GL_POLYGON); // vertices in counter clockwise glVertex2f( HALF_BODY_W, 0.0); glVertex2f( HALF_BODY_W, BODY_H); glVertex2f( -HALF_BODY_W, BODY_H); glVertex2f( -HALF_BODY_W, 0.0); glEnd(); glPopAttrib(); glPopMatrix(); glEndList(); // end BODY // neck: // frame is right handed, origin at middle of base // coordinate axis are alingned with the axis of symmetry of // the neck (as in the picture in handout) glNewList(NECK, GL_COMPILE); // begin NECK glPushMatrix(); glPushAttrib(GL_COLOR); glColor3f(1.0,1.0,0.0); // neck color glBegin(GL_POLYGON); // vertices in counter clockwise glVertex2f( HALF_NECK_W, 0.0); glVertex2f( HALF_NECK_W, NECK_H); glVertex2f( -HALF_NECK_W, NECK_H); glVertex2f( -HALF_NECK_W, 0.0); glEnd(); glPopAttrib(); glPopMatrix(); glEndList(); // end NECK } // end defineParts() /*********************************************************************************/ // draw wrist, swingin back and fort at R1_th angle at its base /*********************************************************************************/ void draw_wrist() { glRotatef(wrist_motion,0.0,0.0,1.0); // swing wrist glCallList(WRIST); } /*********************************************************************************/ // draw hand which is the arm with the wrist on top /*********************************************************************************/ void draw_hand() { glRotatef(arm_motion,0.0,0.0,1.0); // swing arm back and fort at arm_motion angle glCallList(ARM); // draw arm glTranslatef(T1_x, T1_y, 0.0); // put wrist on arm draw_wrist(); // draw swinging wrist } /*********************************************************************************/ // draw robot which has a neck and a hand, see tree in comment on // top of the program /*********************************************************************************/ void draw_robot() { glCallList(BODY); // draw body glPushMatrix(); // will come back to draw neck glTranslatef(T2_x, T2_y, 0.0); // put hand on body glRotatef(R2_th, 0.0,0.0,1.0); // rotate hand at its own base draw_hand(); // draw swinging hand glPopMatrix(); glTranslatef(T3_x, T3_y, 0.0); // put neck on body glCallList(NECK); // draw neck } /*********************************************************************************/ // display callback /*********************************************************************************/ void display() { glClear(GL_COLOR_BUFFER_BIT); glPushMatrix(); // to isolate motion in consecutive moves glTranslatef(jump_x, jump_y, 0.0); // jump draw_robot(); // draw robot glPopMatrix(); glutSwapBuffers(); } /*********************************************************************************/ // idle callback updates rotation angles and translation parameters /*********************************************************************************/ void idle() { // update global motion parameters // jump up jump_x += speed_up*jump_incr_x; jump_y += speed_up*jump_incr_y; if (jump_y > 2*(BODY_H+ARM_H+WRIST_H)) { jump_incr_x = 0; jump_incr_y = -1; speed_up = 0.25; } // jump down if (jump_y < 0) { jump_incr_x = -1; jump_incr_y = 0; speed_up = 0.5; } // go back if (jump_x < 0) { glLoadIdentity(); jump_incr_x = 1; jump_incr_y = 1; speed_up = 1; } // flip wrist wrist_motion += wrist_incr; if (wrist_motion > 45) wrist_incr = -1; if (wrist_motion < -45) wrist_incr = 1; // flip arm arm_motion += arm_incr; if (arm_motion>20) arm_incr = -1; if (arm_motion < -20) arm_incr = 1; glutPostRedisplay(); }