#include "Screw.h" #include "Vector.h" #include "Listener.h" #include #include #include #include #include #include #include #include using namespace std; Vector* theNormal; // this variable holds the rotation in the x and y direction // used when nothing is clicked float xrot = 0.0; float yrot = 0.0; // the angle of the rotation used while panning (control held) float angleOfRot = 0.0; // the axis of rotation used while panning (control held) Vector* panRotation; // the point clicked Point3* pointClicked; // variable used when the alt key is held to move toward // and away from the point clicked float moveIn = 0.0f; // the x and y location of the mouse int mouseX; int mouseY; float ROTTIME = 0.5f; float ZOOMZOOM = 0.001f; int time1; int time2; float dtime; float drotx; float droty; GLfloat* m = new GLfloat[16]; GLfloat posesMatrix[10][16]; bool poseSaved[10]; Pose *poses1; Pose *poses2; float timeFactor = 0.f; bool bScrewing = false; bool firstTime = true; bool mouseDown = false; bool bKeepRot = false; bool bControlClicked = false; bool bMotion = false; bool bAltClicked = false; float distD = 1; void (*mouseFunc)(int, int, int, int) = NULL; void (*specialFunc)(int, int, int) = NULL; void (*keyboardFunc)(unsigned char, int, int) = NULL; void (*mouseMotionFunc)(int, int) = NULL; void (*displayFunc)(void) = NULL; void updateD() { GLfloat* prm = new GLfloat[16]; glGetFloatv(GL_PROJECTION_MATRIX, prm); distD = prm[5]; cout<<"D value is "<getX(), moveIn*pointClicked->getY(), moveIn*pointClicked->getZ()); pointClicked->setX(pointClicked->getX() + (moveIn*pointClicked->getX())); pointClicked->setY(pointClicked->getY() + (moveIn*pointClicked->getY())); pointClicked->setZ(pointClicked->getZ() + (moveIn*pointClicked->getZ())); glTranslatef(pointClicked->getX(), pointClicked->getY(), pointClicked->getZ()); // translate to the point clicked // Draw a sphere about the point of rotation glColor3f(0.0f,0.0f,1.0f); glutSolidSphere(0.07f, 8, 8); glLineWidth(0.5); glBegin(GL_LINES);{ glVertex3f(pointClicked->getX(), pointClicked->getY(), pointClicked->getZ()); glVertex3f(pointClicked->getX()+theNormal->getX(), pointClicked->getY()+theNormal->getY(), pointClicked->getZ()+theNormal->getZ()); } glEnd(); // rotate about the point by a certain rotation if(bControlClicked){ if(angleOfRot != 0){ glRotatef(-angleOfRot, panRotation->getX(), panRotation->getY(), -(panRotation->getZ())); angleOfRot = 0; } } else{ glRotatef(-xrot,1.0f, 0.0f, 0.0f); glRotatef(-yrot, 0.0f, 1.0f, 0.0f); } // translate back to scene origin glTranslatef(-(pointClicked->getX()), -(pointClicked->getY()), -(pointClicked->getZ())); if(!firstTime) glMultMatrixf(m); // multiply the top matrix in the stack by m else firstTime = false; // store the top matrix from the stack into m glGetFloatv(GL_MODELVIEW_MATRIX, m); glutSwapBuffers(); } void TesterKeyboardCallback(unsigned char key, int x, int y) { if(keyboardFunc != NULL) keyboardFunc(key, x, y); } void saveMatrix(int i) { poseSaved[i] = true; glGetFloatv(GL_MODELVIEW_MATRIX, posesMatrix[i]); } void setUpPose1() { poses1->ux = m[0]; poses1->uy = m[1]; poses1->uz = m[2]; poses1->vx = m[4]; poses1->vy = m[5]; poses1->vz = m[6]; poses1->wx = m[8]; poses1->wy = m[9]; poses1->wz = m[10]; poses1->ox = m[12]; poses1->oy = m[13]; poses1->oz = m[14]; } void setUpPose2(int i) { poses2->ux = posesMatrix[i][0]; poses2->uy = posesMatrix[i][1]; poses2->uz = posesMatrix[i][2]; poses2->vx = posesMatrix[i][4]; poses2->vy = posesMatrix[i][5]; poses2->vz = posesMatrix[i][6]; poses2->wx = posesMatrix[i][8]; poses2->wy = posesMatrix[i][9]; poses2->wz = posesMatrix[i][10]; poses2->ox = posesMatrix[i][12]; poses2->oy = posesMatrix[i][13]; poses2->oz = posesMatrix[i][14]; } Point3* getPointAt(int xloc, int yloc) { GLfloat* zbuf = new GLfloat[1]; // read the zbuffer at the location of the mouse click glReadPixels(xloc, glutGet(GLUT_WINDOW_HEIGHT)-yloc, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, zbuf); if(zbuf[0] != 1) { GLdouble* model = new GLdouble[16]; glGetDoublev(GL_MODELVIEW_MATRIX, model); GLdouble* proj = new GLdouble[16]; glGetDoublev(GL_PROJECTION_MATRIX, proj); GLint* vp = new GLint[4]; glGetIntegerv(GL_VIEWPORT, vp); GLdouble xt; GLdouble yt; GLdouble zt; // get the coordinates in the scene world gluUnProject(xloc, glutGet(GLUT_WINDOW_HEIGHT)-yloc, zbuf[0], model, proj, vp, &xt, &yt, &zt); return new Point3((float)xt, (float)yt, (float)zt); } // end if return NULL; } Vector* findNormalAt(int xloc, int yloc) { Point3* left = getPointAt(xloc-1, yloc); Point3* right = getPointAt(xloc+1, yloc); Point3* below = getPointAt(xloc, yloc+1); Point3* above = getPointAt(xloc, yloc-1); Vector* yVec = new Vector(below, above); Vector* xVec = new Vector(left, right); Vector* crossProd = xVec->cross(yVec); cout<<"xVec is ("<getX()<<","<getY()<<","<getZ()<<")\n"; cout<<"yVec is ("<getX()<<","<getY()<<","<getZ()<<")\n"; crossProd->setZ(-1.0*crossProd->getZ()); crossProd->normalize(); cout<<"The cross product is ("<getX()<<","<getY()<<","<getZ()<<")\n"; return crossProd; } void TesterSpecialCallback(int key, int x, int y) { int mod = glutGetModifiers(); switch(key) { case GLUT_KEY_F1: if(mod == GLUT_ACTIVE_SHIFT) saveMatrix(1); else if(mod == GLUT_ACTIVE_CTRL) { bScrewing = true; setUpPose1(); setUpPose2(1); initialize(poses1, poses2); } break; case GLUT_KEY_F2: if(mod == GLUT_ACTIVE_SHIFT) saveMatrix(2); else if(mod == GLUT_ACTIVE_CTRL) { bScrewing = true; setUpPose1(); setUpPose2(2); initialize(poses1, poses2); } break; case GLUT_KEY_F3: if(mod == GLUT_ACTIVE_SHIFT) saveMatrix(3); else if(mod == GLUT_ACTIVE_CTRL) { bScrewing = true; setUpPose1(); setUpPose2(3); initialize(poses1, poses2); } break; case GLUT_KEY_F4: if(mod == GLUT_ACTIVE_SHIFT) saveMatrix(4); else if(mod == GLUT_ACTIVE_CTRL) { bScrewing = true; setUpPose1(); setUpPose2(4); initialize(poses1, poses2); } break; case GLUT_KEY_F5: if(mod == GLUT_ACTIVE_SHIFT) saveMatrix(5); else if(mod == GLUT_ACTIVE_CTRL) { bScrewing = true; setUpPose1(); setUpPose2(5); initialize(poses1, poses2); } break; case GLUT_KEY_F6: if(mod == GLUT_ACTIVE_SHIFT) saveMatrix(6); else if(mod == GLUT_ACTIVE_CTRL) { bScrewing = true; setUpPose1(); setUpPose2(6); initialize(poses1, poses2); } break; case GLUT_KEY_F7: if(mod == GLUT_ACTIVE_SHIFT) saveMatrix(7); else if(mod == GLUT_ACTIVE_CTRL) { bScrewing = true; setUpPose1(); setUpPose2(7); initialize(poses1, poses2); } break; case GLUT_KEY_F8: if(mod == GLUT_ACTIVE_SHIFT) saveMatrix(8); else if(mod == GLUT_ACTIVE_CTRL) { bScrewing = true; setUpPose1(); setUpPose2(8); initialize(poses1, poses2); } break; case GLUT_KEY_F9: if(mod == GLUT_ACTIVE_SHIFT) saveMatrix(9); else if(mod == GLUT_ACTIVE_CTRL) { bScrewing = true; setUpPose1(); setUpPose2(9); initialize(poses1, poses2); } break; case GLUT_KEY_F10: if(mod == GLUT_ACTIVE_SHIFT) saveMatrix(0); else if(mod == GLUT_ACTIVE_CTRL) { bScrewing = true; setUpPose1(); setUpPose2(0); initialize(poses1, poses2); } break; } if(specialFunc != NULL) specialFunc(key, x, y); } void TesterMouseMotionCallback(int xloc, int yloc) { bMotion = true; if(mouseMotionFunc != NULL) mouseMotionFunc(xloc, yloc); if(bControlClicked) { GLdouble xt; GLdouble yt; GLdouble xe; GLdouble ye; Vector* prev; Vector* cur; GLdouble* model = new GLdouble[16]; GLdouble* proj = new GLdouble[16]; GLint* vp = new GLint[4]; glGetDoublev(GL_MODELVIEW_MATRIX, model); glGetDoublev(GL_PROJECTION_MATRIX, proj); glGetIntegerv(GL_VIEWPORT, vp); // get the coordinates in the scene world GLfloat xmax = glutGet(GLUT_WINDOW_WIDTH); GLfloat ymax = glutGet(GLUT_WINDOW_HEIGHT); // convert the points clicked to be between -1 and 1 xt = ((mouseX - (xmax / 2.0)) / (xmax / (2.0))); yt = (((ymax / 2) - mouseY) / (ymax / (2.0))); xe = ((xloc - (xmax / 2.0)) / (xmax / (2.0))); ye = (((ymax / 2) - yloc) / (ymax / (2.0))); prev = new Vector((float)xt, (float)yt, distD); cur = new Vector((float)xe, (float)ye, distD); prev->normalize(); cur->normalize(); panRotation = prev->cross(cur); float sincross = panRotation->magnitude(); panRotation->normalize(); angleOfRot += (180.0 * asinf(sincross) / 3.14159); } // end if else if(bAltClicked) moveIn = ZOOMZOOM*(pointClicked->getZ())*(mouseY-yloc); else // shift is clicked { time1 = time2; time2 = glutGet(GLUT_ELAPSED_TIME); yrot = ROTTIME * (float)(mouseX - xloc); xrot = ROTTIME * (float)(mouseY - yloc); } // end else if(!bControlClicked && !bAltClicked && ((mouseX - xloc) < -3) || ((mouseX - xloc) > 3) || ((mouseY - yloc) < -3) || ((mouseY - yloc) > 3)) { bKeepRot = true; droty = ROTTIME * (float)(mouseX - xloc); drotx = ROTTIME * (float)(mouseY - yloc); dtime = (float)(time2 - time1); } else bKeepRot = false; mouseX = xloc; mouseY = yloc; } // end TesterMouseMotionCallback void TesterMouseCallback(int button, int state, int xloc, int yloc) { if(mouseFunc != NULL) mouseFunc(button, state, xloc, yloc); glLoadIdentity(); int mod = glutGetModifiers(); if((button == GLUT_LEFT_BUTTON) && (state == GLUT_DOWN) && (mod == GLUT_ACTIVE_SHIFT)) { time2 = glutGet(GLUT_ELAPSED_TIME); mouseDown = true; pointClicked = getPointAt(xloc, yloc); theNormal = findNormalAt(xloc, yloc); } // end if else if((button == GLUT_LEFT_BUTTON) && (state == GLUT_DOWN) && (mod == GLUT_ACTIVE_CTRL)) { pointClicked->setX(0.f); pointClicked->setY(0.f); pointClicked->setZ(0.f); bControlClicked = true; mouseDown = true; } // end else else if((button == GLUT_LEFT_BUTTON) && (state == GLUT_DOWN) && (mod == GLUT_ACTIVE_ALT)){ mouseDown = true; bAltClicked = true; } else if((button == GLUT_LEFT_BUTTON) && (state == GLUT_UP)) { if(!bMotion) bKeepRot = false; if(bAltClicked || bControlClicked) bKeepRot = false; mouseDown = false; bAltClicked = false; bControlClicked = false; bMotion = false; angleOfRot = 0.0; moveIn = 0.0; } // end else mouseX = xloc; mouseY = yloc; } void TesterDisplayCallback(void) { if(!bScrewing) { processChange(); moveIn = 0.0; if(!bKeepRot || mouseDown) { xrot = 0.0f; yrot = 0.0f; } // end if else { time1 = time2; time2 = glutGet(GLUT_ELAPSED_TIME); yrot = droty * ((float)(time2 - time1) / dtime); xrot = drotx * ((float)(time2 - time1) / dtime); } } else { int diffTime = 100; int startT; while(timeFactor <= 1.f) { timeFactor += 0.0005f * diffTime; displayAt(timeFactor); startT = glutGet(GLUT_ELAPSED_TIME); if(displayFunc != NULL) { displayFunc(); } diffTime = glutGet(GLUT_ELAPSED_TIME) - startT; } pointClicked->setX(0.f); pointClicked->setY(0.f); pointClicked->setZ(0.f); xrot = 0.0f; yrot = 0.0f; moveIn = 0.f; bScrewing = false; timeFactor = 0.f; glGetFloatv(GL_MODELVIEW_MATRIX, m); } if(displayFunc != NULL) { displayFunc(); } } void setupListeners() { theNormal = new Vector(); for(int i = 0; i < 10; i++) { poseSaved[i] = false; } poses1 = (Pose*)malloc(sizeof(Pose)); poses2 = (Pose*)malloc(sizeof(Pose)); panRotation = new Vector(); pointClicked = new Point3(); glutKeyboardFunc(TesterKeyboardCallback); glutSpecialFunc(TesterSpecialCallback); glutMouseFunc(TesterMouseCallback); glutMotionFunc(TesterMouseMotionCallback); glutDisplayFunc(TesterDisplayCallback); } void setupDisplay(void (*ptrDisplayFunc)(void)) { displayFunc = ptrDisplayFunc; } void setupKeyboard(void (*ptrKeyboardFunc)(unsigned char, int, int)) { keyboardFunc = ptrKeyboardFunc; } void setupSpecial(void (*ptrSpecialFunc)(int, int, int)) { specialFunc = ptrSpecialFunc; }