#include #include #ifdef __APPLE__ #include #else #include #endif #include /* Parametres */ /* Part of the arm that moves */ #define TOP 0 #define MIDDLE 1 #define BOTTOM 2 int objectMoving = 2; /* quel morceau du bras on bouge */ /* Drawing method */ #define BareBones 0 #define JustFlesh 1 #define Continuous 2 #define Skinning 3 #define SkinningPropre 4 int drawingMethod = 0; int creationLines = 0; float rotations[3]; float length[3]; /* Pr interface utilisateur */ int beginx, beginy, width, height; float beginAngle; float tmin; void drawFlesh(float tmin) { float tmax = 1-tmin; float x,y; float x0, y0; int i; float radius = 0.1; float angle = 0; x0 = -1; y0 = -0.5; angle = 0; glLineWidth(2.0); glBegin(GL_LINES); for (i = 0; i < 3; i++) { angle += rotations[i]; if (i != 0) { x = x0 + cos(angle)*length[i]*tmin + sin(-angle)*radius; y = y0 + sin(angle)*length[i]*tmin + cos(angle)*radius; } else { x = x0 + sin(-angle)*radius; y = y0 + cos(angle)*radius; } glVertex2f(x,y); if (i == 0) { x += cos(angle)*length[i]*tmax; y += sin(angle)*length[i]*tmax; } else if (i == 2) { x += cos(angle)*length[i]*(1.0-tmin); y += sin(angle)*length[i]*(1.0-tmin); } else { x += cos(angle)*length[i]*(tmax-tmin); y += sin(angle)*length[i]*(tmax-tmin); } glVertex2f(x,y); x0 += cos(angle)*length[i]; y0 += sin(angle)*length[i]; } glEnd(); x0 = -1; y0 = -0.5; angle = 0; glBegin(GL_LINES); for (i = 0; i < 3; i++) { angle += rotations[i]; if (i != 0) { x = x0 + cos(angle)*length[i]*tmin - sin(-angle)*radius; y = y0 + sin(angle)*length[i]*tmin - cos(angle)*radius; } else { x = x0 - sin(-angle)*radius; y = y0 - cos(angle)*radius; } glVertex2f(x,y); if (i == 0) { x += cos(angle)*length[i]*tmax; y += sin(angle)*length[i]*tmax; } else if (i == 2) { x += cos(angle)*length[i]*(1.0-tmin); y += sin(angle)*length[i]*(1.0-tmin); } else { x += cos(angle)*length[i]*(tmax-tmin); y += sin(angle)*length[i]*(tmax-tmin); } glVertex2f(x,y); x0 += cos(angle)*length[i]; y0 += sin(angle)*length[i]; } glEnd(); x0 = -1; y0 = -0.5; angle = 0; glLineWidth(2.0); glBegin(GL_LINES); for (i = 0; i < 3; i++) { angle += rotations[i]; if (i != 0) { x = x0 + cos(angle)*length[i]*tmin + sin(-angle)*radius; y = y0 + sin(angle)*length[i]*tmin + cos(angle)*radius; } else { x = x0 + sin(-angle)*radius; y = y0 + cos(angle)*radius; } glVertex2f(x,y); if (i != 0) { x = x0 + cos(angle)*length[i]*tmin - sin(-angle)*radius; y = y0 + sin(angle)*length[i]*tmin - cos(angle)*radius; } else { x = x0 - sin(-angle)*radius; y = y0 - cos(angle)*radius; } glVertex2f(x,y); if (i != 2) { x = x0 + cos(angle)*length[i]*tmax + sin(-angle)*radius; y = y0 + sin(angle)*length[i]*tmax + cos(angle)*radius; } else { x = x0 + cos(angle)*length[i] + sin(-angle)*radius; y = y0 + sin(angle)*length[i] + cos(angle)*radius; } glVertex2f(x,y); if (i!= 2) { x = x0 + cos(angle)*length[i]*tmax - sin(-angle)*radius; y = y0 + sin(angle)*length[i]*tmax - cos(angle)*radius; } else { x = x0 + cos(angle)*length[i] - sin(-angle)*radius; y = y0 + sin(angle)*length[i] - cos(angle)*radius; } glVertex2f(x,y); x0 += cos(angle)*length[i]; y0 += sin(angle)*length[i]; } glEnd(); } void drawObject() { float x, y; float x0, y0; float radius = 0.1; float tmax = 1 - tmin; float angle = 0; int i; glPushMatrix(); x = -1.0; y = -0.5; // Drawing the skeletton: glColor3f(1.0, 0.0, 0.0); glLineWidth(5.0); glBegin(GL_LINES); for (i = 0; i < 3; i++) { glVertex2f(x,y); angle += rotations[i]; x += cos(angle)*length[i]; y += sin(angle)*length[i]; glVertex2f(x,y); } glEnd(); x = -1.0; y = -0.5; angle = 0; // And its articulations: glPointSize(10.0); glColor3f(1.0, 1.0, 0.0); glBegin(GL_POINTS); for (i = 0; i < 3; i++) { glVertex2f(x,y); angle += rotations[i]; x += cos(angle)*length[i]; y += sin(angle)*length[i]; } glEnd(); // The drawing of the "flesh" glColor3f(0.0, 0.0, 1.0); glLineWidth(1.0); if ((drawingMethod >= 1) && (drawingMethod < SkinningPropre)) { drawFlesh(tmin); } switch (drawingMethod) { case BareBones: break; case JustFlesh: break; case Continuous: { float xM, yM; x0 = -1; y0 = -0.5; angle = 0; glBegin(GL_LINES); for (i = 0; i < 3; i++) { angle += rotations[i]; x = x0 + cos(angle)*length[i]*tmin + sin(-angle)*radius; y = y0 + sin(angle)*length[i]*tmin + cos(angle)*radius; if (i != 0) glVertex2f(x,y); glVertex2f(x,y); x += cos(angle)*length[i]*(tmax-tmin); y += sin(angle)*length[i]*(tmax-tmin); glVertex2f(x,y); if (i != 2) glVertex2f(x,y); else {xM = x; yM = y;} x0 += cos(angle)*length[i]; y0 += sin(angle)*length[i]; } glEnd(); glVertex2f(x,y); x0 = -1; y0 = -0.5; angle = 0; glBegin(GL_LINES); for (i = 0; i < 3; i++) { angle += rotations[i]; x = x0 + cos(angle)*length[i]*tmin - sin(-angle)*radius; y = y0 + sin(angle)*length[i]*tmin - cos(angle)*radius; if (i != 0) glVertex2f(x,y); glVertex2f(x,y); x += cos(angle)*length[i]*(tmax-tmin); y += sin(angle)*length[i]*(tmax-tmin); glVertex2f(x,y); if (i != 2) glVertex2f(x,y); else { glVertex2f(xM, yM); glVertex2f(x,y); } x0 += cos(angle)*length[i]; y0 += sin(angle)*length[i]; } glEnd(); break; } case Skinning: { /* Lignes de constructions */ float x1, y1; float x2, y2; float xm, ym; float x1a, y1a; float x2a, y2a; /* top part */ x0 = -1; y0 = -0.5; angle = 0; for (i = 0; i < 3; i++) { angle += rotations[i]; x1 = x0 + cos(angle)*length[i]*tmin + sin(-angle)*radius; y1 = y0 + sin(angle)*length[i]*tmin + cos(angle)*radius; x1a = x0 + sin(-angle)*radius; y1a = y0 + cos(angle)*radius; if (i != 0) { xm = 0.5*(x1a+x2a); ym = 0.5*(y1a+y2a); glColor3f(0.0,0.0,1.0); glLineWidth(2.0); glBegin(GL_LINES); glVertex2f(x1,y1); glVertex2f(xm,ym); glVertex2f(xm,ym); glVertex2f(x2,y2); glEnd(); } if (creationLines) { if (i != 0) { glLineWidth(1.0); glColor3f(1.0,1.0,0.0); glBegin(GL_LINES); glVertex2f(x2a,y2a); glVertex2f(x1a,y1a); glEnd(); glColor3f(1.0,0.0,0.0); glPointSize(3.0); glBegin(GL_POINTS); glVertex2f(x1a,y1a); glVertex2f(x2a,y2a); glEnd(); } } x2 = x0 + cos(angle)*length[i]*tmax + sin(-angle)*radius; y2 = y0 + sin(angle)*length[i]*tmax + cos(angle)*radius; x2a = x0 + cos(angle)*length[i] + sin(-angle)*radius; y2a = y0 + sin(angle)*length[i] + cos(angle)*radius; if (creationLines) { glLineWidth(1.0); glColor3f(1.0,0.0,0.0); glBegin(GL_LINES); if (i != 0) { glVertex2f(x1,y1); glVertex2f(x1a,y1a); } if (i != 2) { glVertex2f(x2,y2); glVertex2f(x2a,y2a); } glEnd(); } x0 += cos(angle)*length[i]; y0 += sin(angle)*length[i]; } /* Bottom part */ x0 = -1; y0 = -0.5; angle = 0; for (i = 0; i < 3; i++) { angle += rotations[i]; x1 = x0 + cos(angle)*length[i]*tmin - sin(-angle)*radius; y1 = y0 + sin(angle)*length[i]*tmin - cos(angle)*radius; x1a = x0 - sin(-angle)*radius; y1a = y0 - cos(angle)*radius; if (i != 0) { xm = 0.5*(x1a+x2a); ym = 0.5*(y1a+y2a); glColor3f(0.0,0.0,1.0); glLineWidth(2.0); glBegin(GL_LINES); glVertex2f(x1,y1); glVertex2f(xm,ym); glVertex2f(xm,ym); glVertex2f(x2,y2); glEnd(); } if (creationLines) { if (i != 0) { glLineWidth(1.0); glColor3f(1.0,1.0,0.0); glBegin(GL_LINES); glVertex2f(x2a,y2a); glVertex2f(x1a,y1a); glEnd(); glColor3f(1.0,0.0,0.0); glPointSize(3.0); glBegin(GL_POINTS); glVertex2f(x1a,y1a); glVertex2f(x2a,y2a); glEnd(); } } x2 = x0 + cos(angle)*length[i]*tmax - sin(-angle)*radius; y2 = y0 + sin(angle)*length[i]*tmax - cos(angle)*radius; x2a = x0 + cos(angle)*length[i] - sin(-angle)*radius; y2a = y0 + sin(angle)*length[i] - cos(angle)*radius; if (creationLines) { glLineWidth(1.0); glColor3f(1.0,0.0,0.0); glBegin(GL_LINES); if (i != 0) { glVertex2f(x1,y1); glVertex2f(x1a,y1a); } if (i != 2) { glVertex2f(x2,y2); glVertex2f(x2a,y2a); } glEnd(); } x0 += cos(angle)*length[i]; y0 += sin(angle)*length[i]; } break; } case SkinningPropre: { float x1, y1; float x2, y2; float x3, y3; float x4, y4; float x5, y5; float x6, y6; float xa, ya; float xb, yb; float xc, yc; float xbegin, ybegin, xend, yend; /* top part */ x0 = -1; y0 = -0.5; angle = 0; for (i = 0; i < 3; i++) { angle += rotations[i]; if (i != 0) { x1 = x0 - cos(angle)*length[i-1]*tmin + sin(-angle)*radius; y1 = y0 - sin(angle)*length[i-1]*tmin + cos(angle)*radius; x2 = x0 + sin(-angle)*radius; y2 = y0 + cos(angle)*radius; x3 = x0 + cos(angle)*length[i]*tmin + sin(-angle)*radius; y3 = y0 + sin(angle)*length[i]*tmin + cos(angle)*radius; xa = 0.25*x1 + 0.75*x4; ya = 0.25*y1 + 0.75*y4; xb = 0.5*(x2+x5); yb = 0.5*(y2+y5); glColor3f(0.0,0.0,1.0); glLineWidth(2.0); glBegin(GL_LINES); glVertex2f(xc,yc); glVertex2f(xa,ya); glVertex2f(xa,ya); glVertex2f(xb,yb); xc = 0.75*x3 + 0.25*x6; yc = 0.75*y3 + 0.25*y6; glVertex2f(xb,yb); glVertex2f(xc,yc); glEnd(); if (creationLines) { glLineWidth(1.0); glColor3f(1.0,0.0,0.0); glBegin(GL_LINES); glVertex2f(x1,y1); glVertex2f(x2,y2); glVertex2f(x2,y2); glVertex2f(x3,y3); glVertex2f(x4,y4); glVertex2f(x5,y5); glVertex2f(x5,y5); glVertex2f(x6,y6); glColor3f(1.0,1.0,0.0); glVertex2f(x1,y1); glVertex2f(x4,y4); glVertex2f(x2,y2); glVertex2f(x5,y5); glVertex2f(x3,y3); glVertex2f(x6,y6); glColor3f(1.0,0.0,0.0); glEnd(); glPointSize(3.0); glBegin(GL_POINTS); glVertex2f(x1,y1); glVertex2f(x2,y2); glVertex2f(x3,y3); glVertex2f(x4,y4); glVertex2f(x5,y5); glVertex2f(x6,y6); glEnd(); } } else { x1 = x0 + sin(-angle)*radius; y1 = y0 + cos(angle)*radius; x2 = x1; y2 = y1; x3 = x1; y3 = y1; xc = x1; yc = y1; xbegin = x1; ybegin = y1; } x4 = x0 + cos(angle)*length[i]*tmax + sin(-angle)*radius; y4 = y0 + sin(angle)*length[i]*tmax + cos(angle)*radius; x5 = x0 + cos(angle)*length[i] + sin(-angle)*radius; y5 = y0 + sin(angle)*length[i] + cos(angle)*radius; if (i < 2) { x6 = x0 + cos(angle)*(length[i] + tmin*length[i+1]) + sin(-angle)*radius; y6 = y0 + sin(angle)*(length[i] + tmin*length[i+1]) + cos(angle)*radius; } else { x6 = x5; y6 = y5; x4 = x5; y4 = y5; xend = x5; yend = y5; } if (creationLines) { glLineWidth(1.0); glColor3f(1.0,0.0,0.0); glBegin(GL_LINES); glVertex2f(x3,y3); glVertex2f(x4,y4); glEnd(); } x0 += cos(angle)*length[i]; y0 += sin(angle)*length[i]; } glColor3f(0.0,0.0,1.0); glLineWidth(2.0); glBegin(GL_LINES); glVertex2f(xc,yc); glVertex2f(x5,y5); glEnd(); /* bottom part */ x0 = -1; y0 = -0.5; angle = 0; for (i = 0; i < 3; i++) { angle += rotations[i]; if (i != 0) { x1 = x0 - cos(angle)*length[i-1]*tmin - sin(-angle)*radius; y1 = y0 - sin(angle)*length[i-1]*tmin - cos(angle)*radius; x2 = x0 - sin(-angle)*radius; y2 = y0 - cos(angle)*radius; x3 = x0 + cos(angle)*length[i]*tmin - sin(-angle)*radius; y3 = y0 + sin(angle)*length[i]*tmin - cos(angle)*radius; xa = 0.25*x1 + 0.75*x4; ya = 0.25*y1 + 0.75*y4; xb = 0.5*(x2+x5); yb = 0.5*(y2+y5); glColor3f(0.0,0.0,1.0); glLineWidth(2.0); glBegin(GL_LINES); glVertex2f(xc,yc); glVertex2f(xa,ya); glVertex2f(xa,ya); glVertex2f(xb,yb); xc = 0.75*x3 + 0.25*x6; yc = 0.75*y3 + 0.25*y6; glVertex2f(xb,yb); glVertex2f(xc,yc); glEnd(); if (creationLines) { glLineWidth(1.0); glColor3f(1.0,0.0,0.0); glBegin(GL_LINES); glVertex2f(x1,y1); glVertex2f(x2,y2); glVertex2f(x2,y2); glVertex2f(x3,y3); glVertex2f(x4,y4); glVertex2f(x5,y5); glVertex2f(x5,y5); glVertex2f(x6,y6); glColor3f(1.0,1.0,0.0); glVertex2f(x1,y1); glVertex2f(x4,y4); glVertex2f(x2,y2); glVertex2f(x5,y5); glVertex2f(x3,y3); glVertex2f(x6,y6); glColor3f(1.0,0.0,0.0); glEnd(); glPointSize(3.0); glBegin(GL_POINTS); glVertex2f(x1,y1); glVertex2f(x2,y2); glVertex2f(x3,y3); glVertex2f(x4,y4); glVertex2f(x5,y5); glVertex2f(x6,y6); glEnd(); } } else { x1 = x0 - sin(-angle)*radius; y1 = y0 - cos(angle)*radius; x2 = x1; y2 = y1; x3 = x1; y3 = y1; xc = x1; yc = y1; glLineWidth(2.0); glColor3f(0.0,0.0,1.0); glBegin(GL_LINES); glVertex2f(xbegin,ybegin); glVertex2f(x1,y1); glEnd(); } x4 = x0 + cos(angle)*length[i]*tmax - sin(-angle)*radius; y4 = y0 + sin(angle)*length[i]*tmax - cos(angle)*radius; x5 = x0 + cos(angle)*length[i] - sin(-angle)*radius; y5 = y0 + sin(angle)*length[i] - cos(angle)*radius; if (i < 2) { x6 = x0 + cos(angle)*(length[i] + tmin*length[i+1]) - sin(-angle)*radius; y6 = y0 + sin(angle)*(length[i] + tmin*length[i+1]) - cos(angle)*radius; } else { x6 = x5; y6 = y5; x4 = x5; y4 = y5; glLineWidth(2.0); glColor3f(0.0,0.0,1.0); glBegin(GL_LINES); glVertex2f(x5,y5); glVertex2f(xend,yend); glEnd(); } if (creationLines) { glLineWidth(1.0); glColor3f(1.0,0.0,0.0); glBegin(GL_LINES); glVertex2f(x3,y3); glVertex2f(x4,y4); glEnd(); } x0 += cos(angle)*length[i]; y0 += sin(angle)*length[i]; } glColor3f(0.0,0.0,1.0); glLineWidth(2.0); glBegin(GL_LINES); glVertex2f(xc,yc); glVertex2f(x5,y5); glEnd(); break; } } glPopMatrix(); } void handle_main_menu(int item) { switch(item) { case TOP: objectMoving = 0; glutPostRedisplay(); break; case MIDDLE: objectMoving = 1; glutPostRedisplay(); break; case BOTTOM: objectMoving = 2; break; } } void mouse(int button, int state, int x, int y) { if (state == GLUT_DOWN) { beginx = x; beginy = y; beginAngle = rotations[objectMoving]; } glutPostRedisplay(); } void motion(int x, int y) { rotations[objectMoving] = beginAngle + (y - beginy)/(float)width; glutPostRedisplay(); } void parsekey(unsigned char key, int x, int y) { switch (key) { case 27: exit(0); case ' ': rotations[0] = 0.0; rotations[1] = 0.0; rotations[2] = 0.0; break; case 'a': objectMoving = TOP; break; case 'z': objectMoving = MIDDLE; break; case 'e': objectMoving = BOTTOM; break; case 'q': drawingMethod = BareBones; break; case 's': drawingMethod = JustFlesh; break; case 'd': drawingMethod = Continuous; break; case 'f': drawingMethod = Skinning; break; case 'g': drawingMethod = SkinningPropre; break; case 'c': creationLines = !creationLines; break; default: return; } glutPostRedisplay(); } void parsekey_special(int key, int x, int y) { switch (key) { case GLUT_KEY_UP: rotations[objectMoving] += 0.02; break; case GLUT_KEY_DOWN: rotations[objectMoving] -= 0.02; break; case GLUT_KEY_RIGHT: tmin += 0.02; if (tmin > 0.3) tmin = 0.3; break; case GLUT_KEY_LEFT: tmin -= 0.02; if (tmin < 0) tmin = 0; break; default: return; } glutPostRedisplay(); } void myReshape(int w, int h) { int xmin, ymin; xmin = 0; ymin = 0; if (w > h) { xmin = (w-h)/2; w = h; } else { ymin = (h-w)/2; h = w; } width = w; height = h; glViewport(xmin, ymin, w, h); glutPostRedisplay(); } void display(void) { glPushMatrix(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); drawObject(); glutSwapBuffers(); glPopMatrix(); } void myinit(void) { glDepthRange (0.1, 10); glLoadIdentity(); glClearColor(0.0, 0.0, 0.0, 1.0); rotations[0] = 0.0; rotations[1] = 0.0; rotations[2] = 0.0; length[0] = 0.7; length[1] = 0.5; length[2] = 0.5; objectMoving = TOP; } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE | GLUT_STENCIL); glutCreateWindow("TD2"); glutDisplayFunc(display); glutInitWindowSize(1200, 1200); glutInitWindowPosition(200, 0); glutMouseFunc(mouse); glutMotionFunc(motion); glutKeyboardFunc(parsekey); glutSpecialFunc(parsekey_special); glutReshapeFunc(myReshape); myinit(); glutCreateMenu(handle_main_menu); glutAddMenuEntry("Moving the upper part of the arm", TOP); glutAddMenuEntry("Moving the middle of the arm", MIDDLE); glutAddMenuEntry("Moving the bottom of the arm", BOTTOM); glutAttachMenu(GLUT_RIGHT_BUTTON); glutSwapBuffers(); glutMainLoop(); return 0; }