YATIFN "Yet Another Trackball Implementation that Fails miserably ... or Not"

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.

Up,
anyone to help me out on this one, I am still stuck …

Thanks in advance.

S.

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…

Thank you for your input, but that’s not it and I am still struggling.

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.