views:

807

answers:

2

I am trying implement arcball/trackball rotation but I have a problem with the center of rotation. I want the center to be the center of my screen no matter what.

Let me explain what I have done so far.

I've created a quaterion (rotation axis: vector_start x vector_end, angle: vector_start * vector_end)

From that quaternion I've created a rotation matrix in order to use it with glMultMatrixf(matrix) and get the desired rotation.

The problem is that while my model seems to arcball rotate as it should it always rotates around its local origin. How could I make it rotate around the center of my screen no matter where its local origin is located?

I suppose a solution to that problem could be to translate the whole rotation axis in the center of the screen and then apply the rotation but is this possible? Do I miss something here? Please help.

+1  A: 

You should be able to solve this by applying rotation and translation matrices in the correct order. In your code you could translate back to the origin T(-pos_x, -pos_y, -pos_z), apply your rotation, and translate to the object center again T(pos_x, pos_y, pos_z). This should work in general, independent of how your rotation matrix is constructed.

catchmeifyoutry
Yes but when I apply glMultMatrixf() doesn't opengl rotates the model around its local origin?So if I translate to the origin rotate(not by using glRotatef() but glMultMatrix()) and then translate back again my model will be rotated again around its origin and not as if its origin was the center of screen for example.
arg
Translate with glTranslatef(), then multiply with your rotation matrix glMultMatrix(), and translate back again using glTranslatef(). This as opposed to just calling glMultMatrix(). That doesn't work?
catchmeifyoutry
No it doesn't work. What it does is that it rotates the model as told from the rotation matrix applied by glMultMatrixf but around its local origin. I've tried to convert the rotation quaternion toEuler angles and then apply glRotatef(Yaw,0.,0.,1.); glRotatef(Pich,0.,1.,0.); glRotatef(Roll,1.,0.,0.); instead of directly apply glMultMatrixf() but then while the rotation was about the center of the screen it has nothing to do with an arcballrotation!
arg
I've also tried to work only with transformation matrixes but with thesame results! I've created a translation matrix to the center lets say A then a rotation matrix by QuatMatrix*LastRotation and then atranslation matrix that correspond to "back where I was before" lets say B. So my final transformation matrix :Final = B * QuatMatrix * LastRotation * A. Finally apply glMultMatrix(Final) but the results were the same rotation around the local origin of my model.
arg
A: 

Here's some code I wrote a while ago for a 3-stage rocket launch viewer. I got most of the information from http://www.euclideanspace.com/maths/geometry/rotations

Note: yaw, pitch and roll may change for you based on how you set up your coordinate system

      // Assuming the angles are in radians.
            double p = curPitch * Math.PI/180.0 / 2.0;
            double y = curYaw * Math.PI/180.0 / 2.0;
            double r = curRoll * Math.PI/180.0 / 2.0;

            double sinp = Math.sin(p);
            double siny = Math.sin(y);
            double sinr = Math.sin(r);
            double cosp = Math.cos(p);
            double cosy = Math.cos(y);
            double cosr = Math.cos(r);

            Vector3 axis = new Vector3();

            //here's the important part: how you get your quaternion vector!
            axis.x = sinr * cosp * cosy - cosr * sinp * siny;
            axis.y = cosr * sinp * cosy + sinr * cosp * siny;
            axis.z = cosr * cosp * siny - sinr * sinp * cosy;

            //now normalize the vector in case we want to use it again later
            axis = Vector3.normalizeVector(axis);

            orientation[1] = axis.x;
            orientation[2] = axis.y;
            orientation[3] = axis.z;

            //w is omega: the angle to rotate about the quaternion
            double w = cosr * cosp * cosy + sinr * sinp * siny;

            w = Math.acos(w) * 2.0;

            orientation[0] = w;

            gl.glPushMatrix();

              //translate object first, then rotate it.
              gl.glTranslated(curDisplacement[0] + saveDisplacement[0], -curDisplacement[1] + saveDisplacement[2], curDisplacement[2] + saveDisplacement[1]);

              //this order might be messed up because I screwed up my coordinate system, but the idea is still there
              gl.glRotated(orientation[0]*180/Math.PI, orientation[2]*180/Math.PI, orientation[3]*180/Math.PI, orientation[1]*180/Math.PI);

             //place your objects
             gl.glPopMatrix();

Hope this helps!

bkritzer