# annoying rotation problem

## Recommended Posts

Silex    140
I'm using mouse motion to rotate my scene. It works fine if you just click and drag. The problem is when you release the mouse and then try to drag again: unless you do it from exactly the same spot, it seems to generate a new rotation when it should start from where you leave off. In other words, it doesn't modify the existing rotation matrix it seems to create a new one. I want it to make incremental changes. Here is the relevant code, any ideas what's causing the problem?
int camera::begin_tracking(int x, int y,int width,int height)
{   tracking=true;
init_tb(x,y,width,height);
return 1;
}

int camera::stop_tracking(void)
{   tracking=false;
return 1;
}

//assumes that we are tracking
int camera::mouse_motion(int x, int y, int scr_width, int scr_height)
{   update_tb(x,y,scr_width,scr_height);

return 1;
}


void camera::trackball_ptov(int x, int y, int width, int height, float v[3])
{   float d, a;
/* project x,y onto a hemi-sphere centered within width, height */
v[0] = (2.0F*x - width) / width;
v[1] = (height - 2.0F*y) / height;
d = (float) sqrt(v[0]*v[0] + v[1]*v[1]);
v[2] = (float) cos((M_PI/2.0F) * ((d < 1.0F) ? d : 1.0F));
a = 1.0F / (float) sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
v[0] *= a;
v[1] *= a;
v[2] *= a;
}

void camera::init_tb(int x, int y, int width, int height )
{   trackball_ptov(x, y, width, height, last_pos);
}

void camera::update_tb(int x, int y, int width, int height)
{   float cur_pos[3], dx, dy, dz, angle, axis[3];
trackball_ptov( x, y, width, height, cur_pos );

dx = cur_pos[0] - last_pos[0];
dy = cur_pos[1] - last_pos[1];
dz = cur_pos[2] - last_pos[2];

if ( fabs(dx) > 0 || fabs(dy) > 0 || fabs(dz) > 0 )
{   angle = 90 * sqrt( dx*dx + dy*dy + dz*dz );

axis[0] = last_pos[1]*cur_pos[2] - last_pos[2]*cur_pos[1];
axis[1] = last_pos[2]*cur_pos[0] - last_pos[0]*cur_pos[2];
axis[2] = last_pos[0]*cur_pos[1] - last_pos[1]*cur_pos[0];

last_pos[0] = cur_pos[0];
last_pos[1] = cur_pos[1];
last_pos[2] = cur_pos[2];

glPushMatrix();
glRotatef(angle, axis[0], axis[1], axis[2]);
glMultMatrixf(tb_matrix);
glGetFloatv(GL_MODELVIEW_MATRIX, tb_matrix);
glPopMatrix();
}
}



##### Share on other sites
Dave Hunt    4872
Try setting last_pos = cur_pos in begin_tracking. The way your code is now, last_pos still contains the position where you last stopped dragging.

##### Share on other sites
Silex    140
The last_pos is set equal to cur_pos each time update_tb is called and cur_pos is local to the update_tb function; am I misunderstanding you?

[Edited by - Silex on December 5, 2005 2:03:41 PM]

##### Share on other sites
Dave Hunt    4872
I made the assumption (I know, bad idea) that your update_tb was only being called while tracking was true. In that case, you would need to initialize last_pos to the current position at the time begin_tracking is called. I used cur_pos generically to refer to the current position.

However, if you are always calling update_tb - even when not tracking - then I'm not sure what the problem might be.

##### Share on other sites
Silex    140
No, you assumed correctly. update_tb is only called on mouse_motion events where tracking==true.

Could you clarify which current position you're talking about? Are we talking mouse coordinates or the projected position on the hemi-sphere calculated with trackball_ptov?

In the former case, isn't that what my init_tb function is doing? Because update_tb will be called right after and that's where cur_pos is calculated, so they should be the same (or very close) but that doesn't explain the "jerk" in rotation I'm seeing.