PDA

View Full Version : how to control rotation use mouse based on Quaternion



ruixp
03-04-2003, 05:47 PM
is there any examples i can download?
any advice is welcome!

Rob Fletcher
03-05-2003, 12:57 AM
Get some code at

http://www.york.ac.uk/services/cserv/sw/graphics/OPENGL/crystal.c

r

JustHanging
03-05-2003, 01:01 AM
Hi,

Of course it depends on what kind of rotation you want, but this works for me and creates a similar rotation to the one that seems to be used in many other 3d programs as well. I assume you already know how to use quaternions to rotate around an arbitary axis, the rest goes as follows:

For a view I have eye and target positions and an up vector. In this case the up vector needs to be propotional to the eye->target vector, otherwise you'll get crappy euler style rotation.

Now, let's say you have dx and dy refering to the amounts the mouse x and y have been changed. From those you derive angleX and angleY by scaling with a convinient factor.

Let v be vector from target to eye. First rotate v angleX degrees around the view's up vector. Then get a right vector, being the cross product of up and v. Then rotate both v and up angleY degrees around the right vector.

Finally set the new eye position to target+v. That's it, I hope it helps.

-Ilkka

ruixp
03-05-2003, 09:22 PM
Originally posted by ruixp:
is there any examples i can download?
any advice is welcome!

ruixp
03-05-2003, 09:26 PM
thanks,Rob Fletcher&JustHanging
i use gluLookat
to move eye in 3d scene,i dont' know the relationship between 2d mouse and 3d scene?

ruixp
03-05-2003, 11:33 PM
assume that
when i draw scene,i use
gluLookAt(eyePos[0],eyePos[1],eyePos[2],cenPos[0],cenPos[1],cenPos[2],0,0,1);

then

void CStratumVisView::OnLButtonDown(UINT nFlags, CPoint point)
{
glMouseDownX = point.x;
glMouseDownY = point.y;
gbLeftMouse = true;
}

void CStratumVisView::OnLButtonUp(UINT nFlags, CPoint point)
{
gbLeftMouse = false;
}

void CStratumVisView::OnMouseMove(UINT nFlags, CPoint point)
{
if(gbLeftMouse)
{
int dx,dy;
dx = glMouseDownX - point.x;
dy = glMouseDownY - point.y;
???????????
glMouseDownX = point.x;
glMouseDownY = point.y;
InvalidateRect(NULL,FALSE);
}
}

i don't know how to determine witch axis ,my eye will rotate with?

who can tell me how to fill ????????? in my code

cirityone
03-05-2003, 11:56 PM
Hi, these equations can help you...

GLvoid APIENTRY
mouseMove( AUX_EVENTREC *event )
{
x_old = xPos;
y_old = yPos;

xPos = event->data[AUX_MOUSEX];
yPos = event->data[AUX_MOUSEY];

/** Right/Left **/

if (event->data[AUX_MOUSESTATUS] == AUX_RIGHTBUTTON)
{
if (fabs(xPos-x_old) > fabs(yPos-y_old))
{
if (xPos > x_old)
{
incx -= 0.5f;
if (incx < 0.0f) incx = 359.5f;
}
else
{
incx += 0.5f;
if (incx > 359.5f) incx = 0.0f;
}
} // UP/DOWN
else if (yPos > y_old)
{
pos[2] -= 5.0f;
}
else pos[2] += 5.0f;
}
pos[0]= eye[0]+1000.0f* (GLfloat)cos((incx+90.0f)*2RAD);
pos[1] = eye[1]+1000.0f*(GLfloat)sin((incx+90.0f)*2RAD);
hdg = 360.0f - incx;

/** FORWARD/BACKWARD **/

if (event->data[AUX_MOUSESTATUS] == AUX_LEFTBUTTON)
{
if (yPos < y_old)
{
eye[0] += (GLfloat)(cos((incx+90.0f)*2RAD)*10.0f);
eye[1] += (GLfloat)(sin((incx+90.0f)*2RAD)*10.0f);
}
else
{
eye[0] -= (GLfloat)(cos((incx+90.0f)*ARAD)*10.0f);
eye[1] -= (GLfloat)(sin((incx+90.0f)*ARAD)*10.0f);
}

}
}

ruixp
03-06-2003, 01:32 AM
thanks cirityone!
your methods just like using keyboards to control 3d scene,but i want to control the rotation only by left button of mouse http://www.opengl.org/discussion_boards/ubb/smile.gif

any advice are welcome

JustHanging
03-06-2003, 03:14 AM
So what's wrong with the algorithm I gave you? Just code it and plug it in the ????? place in your mouseMove routine. If you understand quaternions it should be very straightforward.

-Ilkka

ruixp
03-06-2003, 03:35 PM
hi
JustHanging
i think your algrothim is just what i want!! http://www.opengl.org/discussion_boards/ubb/smile.gif

do u have any examples to share?

i really don't have much knowledge about quantion,just one of my friends tell me that,
so i want to get help from you

JustHanging
03-07-2003, 01:31 AM
Well, I guess I could post you some Delphi code when I get home... Would that help? It's all pretty close to c/c++.

-Ilkka

ruixp
03-07-2003, 04:07 AM
i am glad to get help from you,thanks!

JustHanging
03-07-2003, 05:26 AM
Ok, let's see. Here are the contents of my mousemove routine. The idea is to rotate the eye around the target based on the mouse movements:



procedure TPanTool.mouseDrag(x, y : integer; view : TViewport);
var
a1, a2 : float;
v, r : vector;
begin
// Determine rotation angles from the change in mouse position
a1:=(x-oldx)/2;
a2:=(y-oldy)/2;

// Rotate the target->eye vectoraround the up vector
v:=vectorTo(view.target, view.eye);
v:=rotateAround(a1, v, view.up);

// Determine the right vector and rotate the target->eye and up around it
r:=cross(view.up, v);
v:=rotateAround(a2, v, r);
view.up:=rotateAround(a2, view.up, r);

// Set the new eye position and repaint
view.eye:=vectorSum(view.target, v);
View.caption:='Free view';
view.paint;

// Update the mouse current position
oldx:=x;
oldy:=y;
end;

And then the tricky rotation around an arbitary axis:



function rotateAround(an : float; vec, axis : vector): vector;
var
temp, v : vector;
mat : matrix4;
x, y, z, w : float;
a : float;
begin
// Make a quaternion from the angle and the axis
a:=degToRad(an/2);
v:=vMult(normalize(axis), sin(a));
x:=v[0]; y:=v[1]; z:=v[2]; w:=cos(a);

// Construct a transformation matrix from the quaternion
mat[0, 0]:=sqr(w)+sqr(x)-sqr(y)-sqr(z);
mat[1, 0]:=2*x*y+2*w*z;
mat[2, 0]:=2*x*z-2*w*y;
mat[3, 0]:=0;

mat[0, 1]:=2*x*y-2*w*z;
mat[1, 1]:=sqr(w)-sqr(x)+sqr(y)-sqr(z);
mat[2, 1]:=2*y*z+2*w*x;
mat[3, 1]:=0;

mat[0, 2]:=2*x*z+2*w*y;
mat[1, 2]:=2*y*z-2*w*x;
mat[2, 2]:=sqr(w)-sqr(x)-sqr(y)+sqr(z);
mat[3, 2]:=0;

mat[0, 3]:=0;
mat[1, 3]:=0;
mat[2, 3]:=0;
mat[3, 3]:=sqr(w)+sqr(x)+sqr(y)+sqr(z);

// Return the original vector transformed by the matrix
rotateAround:=transform4(vec, mat);
end;

And in case you don't know how to transform a vector by a 4x4 matrix,



function transform4(v : vector; mat : matrix4): vector;
var
temp : vector;
w : float;
begin
w:=v[0]*mat[0, 3]+v[1]*mat[1, 3]+v[2]*mat[2, 3]+mat[3, 3];

temp[0]:=(v[0]*mat[0, 0]+v[1]*mat[1, 0]+v[2]*mat[2, 0]+mat[3, 0])/w;
temp[1]:=(v[0]*mat[0, 1]+v[1]*mat[1, 1]+v[2]*mat[2, 1]+mat[3, 1])/w;
temp[2]:=(v[0]*mat[0, 2]+v[1]*mat[1, 2]+v[2]*mat[2, 2]+mat[3, 2])/w;
transform4:=temp;
end;

That should be the essentials, the rest of the functions are just basic vector manipulation functions. If you code in c, you're going to have to use one dimensional arrays for the matrice and pass pointers to the functions to be able to return vectors. Otherwise it should be easy to translate.

I hope that helps,

-Ilkka

ruixp
03-08-2003, 01:53 AM
Hi JustHanging
thank u very much ,i will try based on your codes!