PDA

View Full Version : YATIFN "Yet Another Trackball Implementation that Fails miserably ... or Not"



Slookeur
11-25-2014, 09: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.

Slookeur
12-02-2014, 08:12 AM
Up,
anyone to help me out on this one, I am still stuck ...

Thanks in advance.

S.

sueyllam
12-02-2014, 05:14 PM
May be because x and y of mouse map to axis x and axis z vec[0] and vec[2], then you compute axis y: vec[1] = 1- (vec[0]^2+vec[2]^2)...Currently you map x and y of mouse to axis x and y instead....

Slookeur
12-04-2014, 01:22 AM
Thank you for your input, but that's not it and I am still struggling.

Slookeur
12-05-2014, 02:24 AM
I solved my problem, describing the rotation using quaternions and an appropriate order for the multiplication
of the quaternions from one step to the next.