# how to control rotation use mouse based on Quaternion

is there any examples i can download?
any advice is welcome!

Get some code at

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

r

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

Originally posted by ruixp:
is there any examples i can download?
any advice is welcome!

thanks,Rob Fletcher&JustHanging
i use gluLookat
to move eye in 3d scene,i dont’ know the relationship between 2d mouse and 3d scene?

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

Hi, these equations can help you…

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

``````xPos = event-&gt;data[AUX_MOUSEX];
yPos = event-&gt;data[AUX_MOUSEY];

/** Right/Left **/

if (event-&gt;data[AUX_MOUSESTATUS] == AUX_RIGHTBUTTON)
{
if (fabs(xPos-x_old) &gt; fabs(yPos-y_old))
{
if (xPos &gt; x_old)
{
incx -= 0.5f;
if (incx &lt; 0.0f) incx = 359.5f;
}
else
{
incx += 0.5f;
if (incx &gt; 359.5f) incx = 0.0f;
}
}          // UP/DOWN
else if (yPos &gt; 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-&gt;data[AUX_MOUSESTATUS] == AUX_LEFTBUTTON)
{
if (yPos &lt; 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);
}

}
``````

}

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

any advice are welcome

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

hi
JustHanging
i think your algrothim is just what i want!!

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

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

i am glad to get help from you,thanks!

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]:=2xy+2wz;
mat[2, 0]:=2xz-2wy;
mat[3, 0]:=0;

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

mat[0, 2]:=2xz+2wy;
mat[1, 2]:=2yz-2wx;
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

Hi JustHanging
thank u very much ,i will try based on your codes!