• Create Account

## Problem with Arcball/Trackball implementation using SDL + Opengl

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

3 replies to this topic

### #1mako1131  Members

115
Like
0Likes
Like

Posted 05 April 2013 - 05:06 AM

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

// 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;

//drawing


Thanks for any help suggestions!

Mako

### #2HypnotiC  Members

162
Like
1Likes
Like

Posted 05 April 2013 - 06:28 PM

I haven't known much about quaternions yet, but it seems that something is wrong with your rotation matrix multiplication:

Should

ball_new = ball_old * ball;

ball_old = ball;

be

ball_new = ball * ball_old;

ball_old = ball_new; ?

Since we are concatenating the newly constructed rotation to the accumulated rotation so far.

(Seems ball_new is the accumulative rotation matrix)

Edited by HypnotiC, 05 April 2013 - 06:32 PM.

### #3mako1131  Members

115
Like
0Likes
Like

Posted 06 April 2013 - 04:07 AM

Yeah you are right it should probably be  ball_old = ball_new; ... But may I ask why should I multiply ball * ball_old  instead of ball_old * ball;?  I know that order of matrix multiplication is important and it's not the same multiplying matrices A*B and B*A, but somewhere I read that arcball matrix rotation should be placed after all other matrices...so I basically put the new rotation matrix at the end of everything.

### #4mako1131  Members

115
Like
0Likes
Like

Posted 07 April 2013 - 06:48 AM

I finally figured it out...it's working now.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.