ruixp

03-04-2003, 04:47 PM

is there any examples i can download?

any advice is welcome!

any advice is welcome!

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

ruixp

03-04-2003, 04:47 PM

is there any examples i can download?

any advice is welcome!

any advice is welcome!

Rob Fletcher

03-04-2003, 11:57 PM

Get some code at

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

r

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

r

JustHanging

03-05-2003, 12: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

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, 08:22 PM

Originally posted by ruixp:

is there any examples i can download?

any advice is welcome!

is there any examples i can download?

any advice is welcome!

ruixp

03-05-2003, 08: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?

i use gluLookat

to move eye in 3d scene,i dont' know the relationship between 2d mouse and 3d scene?

ruixp

03-05-2003, 10: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

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, 10: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);

}

}

}

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, 12: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

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, 02: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

-Ilkka

ruixp

03-06-2003, 02: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

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, 12: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

-Ilkka

ruixp

03-07-2003, 03:07 AM

i am glad to get help from you,thanks!

JustHanging

03-07-2003, 04: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

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, 12:53 AM

Hi JustHanging

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

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

Powered by vBulletin® Version 4.2.5 Copyright © 2018 vBulletin Solutions Inc. All rights reserved.