Slookeur

11-25-2014, 10:55 AM

Hello everyone,

I recently decided to implement a trackball/arcball rotation in my code.

The internet is full of tutorial about that so I found plenty of help, and I did implement the rotation,

only the results are not the ones that I expected and I wonder where or even if I did something wrong ...

I guess that something is wrong in my code only I cannot find what, I probably lack the appropriate

knowledge, thus I decided to ask for help.

My problem is the following, I implemented the trackball rotation not to have mouse-based rotations

axis limitated the x, y and z axis, that was the case previously in my code using:

void on_pressed (int x, int y)

{

mouseX = x;

mouseY = y;

}

float cameraAngleX = 0.0;

float cameraAngleY = 0.0;

// on mouse motion I change the rotation angle ...

void on_motion (int x, int y)

{

cameraAngleY += (double) 0.5*(x - mouseX);

cameraAngleX += (double) 0.5*(y - mouseY);

render_scene ();

view -> mouseX = x;

view -> mouseY = y;

}

/// ... and later I rotate the scene accordingly

void render_scene ()

{

...

glRotated (cameraAngleY, 0.0, 1.0, 0.0);

glRotated (cameraAngleX, 1.0, 0.0, 0.0);

...

}

Now my new code for the trackball rotation:

#define SIZE_X 640

#define SIZE_Y 480

float dot_product (float vect_a[3], float vect_b[3])

{

int i;

float v;

v = 0.0;

for (i=0; i<3; i++)

{

v += vect_a[i]*vect_b[i];

}

return v;

}

void cross_product (float vect_a[3], float vect_b[3], float cross[3])

{

cross[0] = vect_a[1]*vect_b[2] - vect_a[2]*vect_b[1];

cross[1] = vect_a[2]*vect_b[0] - vect_a[0]*vect_b[2];

cross[2] = vect_a[0]*vect_b[1] - vect_a[1]*vect_b[0];

}

void normalize (float vect[3])

{

int i;

float mod_vect = 0.0;

for (i=0; i<3; i++) mod_vect += vect[i]*vect[i];

mod_vect = sqrt(mod_vect);

for (i=0; i<3; i++) vect[i] /= mod_vect;

}

void get_arc_ball_vector (int x, int y, float vect[3])

{

vect[0] = 2.0*x/SIZE_X - 1.0;

y =SIZE_Y - y;

vect[1] = 2.0*y/SIZE_Y - 1.0;

float norm_arc = vect[0]*vect[0] + vect[1]*vect[1];

if (norm_arc > 1.0)

{

vect[2] = 0.0;

}

else

{

vect[2] = sqrt(1.0 - norm_arc);

}

normalize (vect);

}

float arc_ball_init[3];

float arc_ball_new[3];

void on_pressed (int x, int y)

{

mouseX = x;

mouseY = y;

get_arc_ball_vector (x, y, arc_ball_init);

}

// on mouse motion I change the rotation angle ...

void on_motion (int x, int y)

{

float rot_angle;

float rot_axis[3];

get_arc_ball_vector (x, y, arc_ball_new);

rot_axis = cross_product (arc_ball_init, arc_ball_new);

if (norm(rot_axis) > 0.0)

{

rot_angle = acos(dot_product(arc_ball_init, arc_ball_new));

glRotatef (rot_angle, rot_axis[0], rot_axis[1], rot_axis[2]);

}

render_scene ();

}

My problem is the following: both methods give me exactly the same result, ie. rotations that are around

x, y and z axis ... which is precisely what I would l like to avoid ... I tried with quaternions and naturally

got the exact same result ... I would really appreciate your help to understand what I am missing here.

Thanks in advance.

S.

I recently decided to implement a trackball/arcball rotation in my code.

The internet is full of tutorial about that so I found plenty of help, and I did implement the rotation,

only the results are not the ones that I expected and I wonder where or even if I did something wrong ...

I guess that something is wrong in my code only I cannot find what, I probably lack the appropriate

knowledge, thus I decided to ask for help.

My problem is the following, I implemented the trackball rotation not to have mouse-based rotations

axis limitated the x, y and z axis, that was the case previously in my code using:

void on_pressed (int x, int y)

{

mouseX = x;

mouseY = y;

}

float cameraAngleX = 0.0;

float cameraAngleY = 0.0;

// on mouse motion I change the rotation angle ...

void on_motion (int x, int y)

{

cameraAngleY += (double) 0.5*(x - mouseX);

cameraAngleX += (double) 0.5*(y - mouseY);

render_scene ();

view -> mouseX = x;

view -> mouseY = y;

}

/// ... and later I rotate the scene accordingly

void render_scene ()

{

...

glRotated (cameraAngleY, 0.0, 1.0, 0.0);

glRotated (cameraAngleX, 1.0, 0.0, 0.0);

...

}

Now my new code for the trackball rotation:

#define SIZE_X 640

#define SIZE_Y 480

float dot_product (float vect_a[3], float vect_b[3])

{

int i;

float v;

v = 0.0;

for (i=0; i<3; i++)

{

v += vect_a[i]*vect_b[i];

}

return v;

}

void cross_product (float vect_a[3], float vect_b[3], float cross[3])

{

cross[0] = vect_a[1]*vect_b[2] - vect_a[2]*vect_b[1];

cross[1] = vect_a[2]*vect_b[0] - vect_a[0]*vect_b[2];

cross[2] = vect_a[0]*vect_b[1] - vect_a[1]*vect_b[0];

}

void normalize (float vect[3])

{

int i;

float mod_vect = 0.0;

for (i=0; i<3; i++) mod_vect += vect[i]*vect[i];

mod_vect = sqrt(mod_vect);

for (i=0; i<3; i++) vect[i] /= mod_vect;

}

void get_arc_ball_vector (int x, int y, float vect[3])

{

vect[0] = 2.0*x/SIZE_X - 1.0;

y =SIZE_Y - y;

vect[1] = 2.0*y/SIZE_Y - 1.0;

float norm_arc = vect[0]*vect[0] + vect[1]*vect[1];

if (norm_arc > 1.0)

{

vect[2] = 0.0;

}

else

{

vect[2] = sqrt(1.0 - norm_arc);

}

normalize (vect);

}

float arc_ball_init[3];

float arc_ball_new[3];

void on_pressed (int x, int y)

{

mouseX = x;

mouseY = y;

get_arc_ball_vector (x, y, arc_ball_init);

}

// on mouse motion I change the rotation angle ...

void on_motion (int x, int y)

{

float rot_angle;

float rot_axis[3];

get_arc_ball_vector (x, y, arc_ball_new);

rot_axis = cross_product (arc_ball_init, arc_ball_new);

if (norm(rot_axis) > 0.0)

{

rot_angle = acos(dot_product(arc_ball_init, arc_ball_new));

glRotatef (rot_angle, rot_axis[0], rot_axis[1], rot_axis[2]);

}

render_scene ();

}

My problem is the following: both methods give me exactly the same result, ie. rotations that are around

x, y and z axis ... which is precisely what I would l like to avoid ... I tried with quaternions and naturally

got the exact same result ... I would really appreciate your help to understand what I am missing here.

Thanks in advance.

S.