Hello,
I am trying to implement arcball / trackball camera rotation to my program but It doesn't work. I read some articles about matrices, quaternions etc. and I tought I finally understood the idea, but apparently I am doing something wrong. Basically I register two mouse positions, create axis of rotation, calculate angle, converted this information to quaternion and then quaternion to rotation matrix. It looks like it's rotating, but not in the way I want. So i would appreciate some help because I am desperate.
Most of the code on the internet use glu, but I don't want to because I have already started to learn SDL and I like it. Here's part of the most important code:
void Vector3D::SetZ(float r) //set z coord. - projection to sphere, r - sphere radius
{
float delta = sqrt(x*x + y*y);
if (delta <= r*0.70710678118)
z = sqrt(r*r - delta*delta);
else
z = (r*r*0.5)/delta;
}
//from main.cpp:
. . .
SDL_GetMouseState(&currMX, &currMY);
relx = event.motion.xrel;
rely = event.motion.yrel;
cMX = 2.*currMX/screen_width-1.; //normalizing screen coordinates
cMY = screen_height - currMY;
cMY = 2.*cMY/screen_height-1.;
rely = -rely;
if(relx<0)relx = -relx;
if(rely<0)rely = -rely;
if(rot)
{
d.Set(relx,rely,0); //distance vector from point 1 to point 2
if(d.Length() - eps >0)
{
z.Set(cMX, cMY, 0); //projection on sphere
k.Set(z[0]+d[0],z[1]+d[1],z[2]+d[2]); // z - start position, k - end position
k.SetZ(1);
z.SetZ(1);
rotaxis.CrossProduct(z, k); //rotation axis
k.Normalize(); //normalizing vectors
z.Normalize();
rotaxis.Normalize();
float pom = z[0]*k[0]+z[1]*k[1]+z[2]*k[2]; //dot product
if(pom<-1) //setting angle (had problems that acos returned NAN)
angle = -M_PI;
else if (pom>1)
angle = 0;
else
angle = acos(pom);
float qw = cos(angle*0.5); //setting up quaternion
float qx = rotaxis[0]*sin(angle*0.5);
float qy = rotaxis[1]*sin(angle*0.5);
float qz = rotaxis[2]*sin(angle*0.5);
//quaternion transformed to rotation matrix
ball.set(
qw*qw + qx*qx - qy*qy - qz*qz, 2*qx*qy + 2*qw*qz, 2*qx*qz - 2*qw*qy, 0,
2*qx*qy - 2*qw*qz, qw*qw - qx*qx + qy*qy - qz*qz, 2*qy*qz + 2*qw*qx, 0,
2*qx*qz + 2*qw*qy, 2*qy*qz - 2*qw*qx, qw*qw - qx*qx - qy*qy + qz*qz, 0,
0, 0, 0, qw*qw + qx*qx + qy*qy + qz*qz
);
}
else
ball.identity();
ball_new = ball_old * ball;
ball_old = ball;
}
//RENDERING
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// camera transformation:
matrixView.identity();
matrixView.rotate(-cameraAngleX, 1,0,0); // 1: rotate on x-axis
matrixView.rotate(-cameraAngleY, 0,1,0); // 2: rotate on y-axis
matrixView.rotate(-cameraAngleZ, 0,0,1); // 3: rotate on z-axis
matrixView.translate(0, 0, -cameraDistance);
// model transform:
//matrixModel.identity();
//matrixModel.rotate(45, 0,1,0); // 1st transform
//matrixModel.translate(0, 2, 0); // 2nd transform
//matrixModel.translate(0, 0, -2);
// build modeview matrix: Mmv = Mv * Mm
matrixModelView.identity();
matrixModelView = matrixView * matrixModel * ball_new;
glLoadMatrixf(matrixModelView.getTranspose());
//drawing
Thanks for any help suggestions!
Mako