rotate around arbitrary point

Started by
0 comments, last by thinhare 14 years, 3 months ago
Hi, all I'd like to do something like Gooogle earth e.g., if I click on an arbitrary location on the map and drag the mouse, the whole map should rotate about the location where mouse is clicked at. I did it like this: (following are MATLAB code, realvec is the absolute coordinate in OpenGL world, lastvec and currvec are cross products of M.v)

lastmat = rotm(-90, 0, 0, 0, 0, -15);
lastvec = [2.5601 -0.0001 1.7256 1]
realvec = (inv(lastmat)*lastvec')'

currmat = rotm(-90, -5, 0, 0, 0, -15);
currvec = (currmat*realvec')'
currmat(1:4,4) = currmat(1:4,4)-(currvec-lastvec)';

thisvec = (currmat*origvec')'



I had it tested in MatLab, it seemed perfectly alright, but when implemented in OpenGL, it did not. I've been stuck here for a while, does anyone know how on this?

function X = rotm(xAngle, yAngle, zAngle, xOffset, yOffset, zOffset);

xAngleRad = xAngle/180.0*pi;
yAngleRad = yAngle/180.0*pi;
zAngleRad = zAngle/180.0*pi;

xMatrix = [1 0 0 0; 0 cos(xAngleRad) sin(xAngleRad) 0; 0 -sin(xAngleRad) cos(xAngleRad) 0; 0 0 0 1];
yMatrix = [cos(yAngleRad) 0 -sin(yAngleRad) 0; 0 1 0 0; sin(yAngleRad) 0 cos(yAngleRad) 0; 0 0 0 1];
zMatrix = [cos(zAngleRad) sin(zAngleRad) 0 0; -sin(zAngleRad) cos(zAngleRad) 0 0; 0 0 1 0; 0 0 0 1];

txMatrix = [1 0 0 xOffset; 0 1 0 0; 0 0 1 0; 0 0 0 1];
tyMatrix = [1 0 0 0; 0 1 0 yOffset; 0 0 1 0; 0 0 0 1];
tzMatrix = [1 0 0 0; 0 1 0 0; 0 0 1 zOffset; 0 0 0 1];

X = txMatrix * tyMatrix * tzMatrix * xMatrix * yMatrix * zMatrix;



Thanks! [Edited by - thinhare on January 3, 2010 3:44:45 PM]
Advertisement
I've tried to put together some c code to show the problem.



Up to now, what I achieved is when I click on a point on the white line, the sheet rotate around that point, but if I click not on the white line, the sheet will rotate around a point on the white line, and that point is aligned vertically with the point I click.

Not sure if I have made myself clear, maybe the code explains better.

(You can press ESC to reset the scene)

#include <GL/gl.h>#include <GL/glu.h>#include <glut.h>#include <math.h>int mWidth, mHeight;float mZTrans;float mYAngle;int mMouseX, mMouseY;double mPosX, mPosY, mPosZ;int mMouseMove;void getClickCoord(int x, int y, double *posX, double *posY, double *posZ){  int viewport[4];  double modelview[16];  double projection[16];  float winX, winY, winZ;    glGetDoublev(GL_MODELVIEW_MATRIX, modelview);  glGetDoublev(GL_PROJECTION_MATRIX, projection);  glGetIntegerv(GL_VIEWPORT, viewport);  winX = (float)x;  winY = (float)(viewport[3] - y - 1);  glReadPixels((int)winX, (int)winY, 1, 1,      GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );  gluUnProject(winX, winY, winZ, modelview, projection, viewport,      posX, posY, posZ);}float normalizeAngle(float angle){  angle -= (360*(int)(angle/360));  if (angle < 0) angle += 360;  return angle;}void glOrthoBegin(){  glMatrixMode(GL_PROJECTION);  glPushMatrix();  glLoadIdentity();  glOrtho(0, mWidth, 0, mHeight, -1, 1);  glMatrixMode(GL_MODELVIEW);  glPushMatrix();  glLoadIdentity();}void glOrthoEnd(){  glMatrixMode(GL_PROJECTION);  glPopMatrix();  glMatrixMode(GL_MODELVIEW);  glPopMatrix();}void paintCircle(float radius, GLint xoffset, GLint yoffset){  float delta = 0.05;  glPushAttrib(GL_CURRENT_BIT);  glColor3f(0.0, 1.0, 0.0);  glBegin(GL_LINE_LOOP);  float theta;  for (theta = 0; theta < 2*M_PI; theta += delta) {    glVertex2i((int)(radius*cos(theta))+xoffset,        (int)(radius*sin(theta))+yoffset);  }  glEnd();  glPopAttrib();}void paintQuads(){  int row, col;  float xoffset, zoffset;  glPushAttrib(GL_CURRENT_BIT);  glBegin(GL_QUADS);  for (row = 0; row < 10; row++) {    zoffset = 1*row+0.5 - 5;    for (col = 0; col < 10; col++) {      xoffset = 1*col+0.5 - 5;      glColor3f(row*0.1, col*0.1, 0.0);      glVertex3f(-0.5+xoffset, 0, -0.5+zoffset);      glVertex3f(-0.5+xoffset, 0,  0.5+zoffset);      glVertex3f( 0.5+xoffset, 0,  0.5+zoffset);      glVertex3f( 0.5+xoffset, 0, -0.5+zoffset);    }  }  glEnd();  glPopAttrib();}void reset(){  mZTrans = -15.0;  mYAngle = 0.0;  mMouseX = mMouseY = 0;  mMouseMove = 0;}void init() {  glClearColor(0.0, 0.0, 0.0, 1.0);  glClearDepth(1.0);  glShadeModel(GL_SMOOTH);  glDepthFunc(GL_LEQUAL);  glEnable(GL_DEPTH_TEST);  glEnable(GL_CULL_FACE);  float ambient[] = {0.5, 0.5, 0.5, 1.0};  float diffuse[] = {0.8, 0.8, 0.8, 1.0};  float specular[] = {1.0, 1.0, 1.0, 1.0};  float position[] = {0.0, 0.0, 0.0, 1.0};  glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);  glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);  glLightfv(GL_LIGHT0, GL_SPECULAR, specular);  glLightfv(GL_LIGHT0, GL_POSITION, position);  glEnable(GL_LIGHTING);  glEnable(GL_LIGHT0);  glEnable(GL_COLOR_MATERIAL);}void display(){  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  glLoadIdentity();  glTranslatef(0, 0, mZTrans);  if (mMouseMove) glTranslatef(mPosX, mPosY, mPosZ);  glRotatef(45.0, 1, 0, 0);  glRotatef(mYAngle, 0, 1, 0);  if (mMouseMove) glTranslatef(-mPosX, -mPosY, -mPosZ);  paintQuads();  if (mMouseMove) {    glOrthoBegin();    paintCircle(20.0, mMouseX, (mHeight-mMouseY-1));    glOrthoEnd();  }  mMouseMove = 0;  glutSwapBuffers();}void reshape(int width, int height) {  glViewport(0, 0, width, height);  glMatrixMode(GL_PROJECTION);  glLoadIdentity();  mWidth = width; mHeight = height;  float aspect = (float)width/(float)height;  float top, bottom, left, right;  top = 0.1*tan(20.0/180.0*M_PI);  if (aspect < 1.0) top *= (1.0/aspect);  bottom = -top;  right = top*aspect;  left = -right;  glFrustum(left, right, bottom, top, 0.1, 100);  glMatrixMode(GL_MODELVIEW);  glLoadIdentity();}void mouse(int button, int state, int x, int y){  if (state == GLUT_DOWN) {    mMouseX = x; mMouseY = y;    getClickCoord(x, y, &mPosX, &mPosY, &mPosZ);  }  else if (state == GLUT_UP) {    glutPostRedisplay();  }}void motion(int x, int y){  mYAngle = normalizeAngle(mYAngle + 5);  mMouseMove = 1;  glutPostRedisplay();}void keyboard(unsigned char key, int x, int y){  switch (key) {    case 27:      reset();      glutPostRedisplay();      break;    case '=':    case '+':      mZTrans /= 1.2;      glutPostRedisplay();      break;    case '-':    case '_':      mZTrans *= 1.2;      glutPostRedisplay();      break;    case 'Q':    case 'q':      exit(0);      break;    default:      break;  }}int main(int argc, char** argv){  glutInit(&argc, argv);  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);  glutInitWindowSize(640, 480);   glutInitWindowPosition(100, 60);  glutCreateWindow(argv[0]);  reset();  init();  glutDisplayFunc(display);   glutReshapeFunc(reshape);  glutMouseFunc(mouse);  glutMotionFunc(motion);  glutKeyboardFunc(keyboard);  glutMainLoop();  return 0;}

This topic is closed to new replies.

Advertisement