PDA

View Full Version : Rotation around a point in 3d

infinitecmdz
10-31-2005, 03:17 PM
Hey guys,

I have a problem. I need to rotate the camera around a fixed point in 3d. In other words, the camera must be able to traverse a sphere. So I have a class called CCamera and a member function like this:

GLvoid RotateAroundPoint(CVector3 vCenter, float angle, float x, float y, float z)
{
CVector3 vNewPosition;

CVector3 vPos = mPosition - vCenter;

// Calculate the sine and cosine of the angle once
float cosTheta = (float)cos(angle);
float sinTheta = (float)sin(angle);

// Find the new x position for the new rotated point
vNewPosition.x = (cosTheta + (1 - cosTheta) * x * x) * vPos.x;
vNewPosition.x += ((1 - cosTheta) * x * y - z * sinTheta) * vPos.y;
vNewPosition.x += ((1 - cosTheta) * x * z + y * sinTheta) * vPos.z;

// Find the new y position for the new rotated point
vNewPosition.y = ((1 - cosTheta) * x * y + z * sinTheta) * vPos.x;
vNewPosition.y += (cosTheta + (1 - cosTheta) * y * y) * vPos.y;
vNewPosition.y += ((1 - cosTheta) * y * z - x * sinTheta) * vPos.z;

// Find the new z position for the new rotated point
vNewPosition.z = ((1 - cosTheta) * x * z - y * sinTheta) * vPos.x;
vNewPosition.z += ((1 - cosTheta) * y * z + x * sinTheta) * vPos.y;
vNewPosition.z += (cosTheta + (1 - cosTheta) * z * z) * vPos.z;

// Now we just add the newly rotated vector to our position to set
// our new rotated position of our camera.
mPosition = vCenter + vNewPosition;
}

Well i guess when I use the key board arrow keys it works well. But when using glutMotionFunc to drag around the scene it gets bad. And the thing is in keybard func, we'd be calling the function rotate about a single axis one at a time. So it aint a problem. But i want to rotate the about the point freely using the mouse.

Heres how my motion drag func goes"

GLvoid MouseDrag(int x, int y)
{
if(!InitDrag)
{
NewDragX = x ;
NewDragY = y ;
InitDrag = true ;
}
else
{

if(y > NewDragY)
{
if(!bActivateSet1&&!bActivateSet2&&!bActivateSet3)
{

CameraObj.RotateAroundPoint(CameraObj.mView , (-CAMERASPEED/FACTOR) , 1.0f , 0.0f , 0.0f) ;
}
}
else
{
if(!bActivateSet1&&!bActivateSet2&&!bActivateSet3)
{
CameraObj.RotateAroundPoint(CameraObj.mView , (CAMERASPEED/FACTOR) , 1.0f , 0.0f , 0.0f) ;
}

}

if(x > NewDragX)
{
if(!bActivateSet1&&!bActivateSet2&&!bActivateSet3)
{
CameraObj.RotateAroundPoint(CameraObj.mView , (CAMERASPEED/FACTOR) , 0.0f , 1.0f , 0.0f) ;
}
}
else
{
if(!bActivateSet1&&!bActivateSet2&&!bActivateSet3)
{
CameraObj.RotateAroundPoint(CameraObj.mView , (-CAMERASPEED/FACTOR) , 0.0f , 1.0f , 0.0f) ;
}

}

}

glutPostRedisplay() ;
}

If anyone knows how to go about this..please let me know...write now it gives me kinda wierd motion around the point.

Yours

Siddharth

songho
11-01-2005, 12:04 PM
infinitecmdz,
I cannot verify your rotation function, but I assume it is right since you have tested.

I have noticed some logic problems in your mouse motion callback function. It looks to me that it only compares the current cursor positions with the position before the mouse button pressed, instead of comparing with the previous one.

Let's say (x,y) was (100,100) before button pressed and the current position is (200,200). It should rotate certain direction. However, what if you decide to change rotation to opposite direction, for example, move the cursor from (200,200) to (150,150)? It should rotate to opposite direction, but (150,150) is still bigger than (100,100) in your logic, therefore keep rotating in same direction.

The other thing you may concern is that you are rotating with constant speed every frame. But the animation speed will be vary on high-end system and slow system, because of different frame rates on different system. It would be better use delta amount based on frame rates.

==song==

infinitecmdz
11-02-2005, 08:23 AM
yes, I understand what you mean. So you're asking me to find the difference between the two positions(that is the previous one and the current one) and move in the positive direction if delta is positive otherwise move in the opposite direction. Am i right?

The thing that concerns me is when the user moves in both the x and y direction, then how should i make my code?so now the scene will be goign in a kindof diagonal way. And which rotation should i do first? Since I am rotating 3d on the xz plane and well as the yz plane. Its a bit confusing to me...

Could you explain if you have any ideas.

Thanx

glbrand7
11-02-2005, 01:53 PM
Just translate delta x and y (of the mouse moves) into radians or degrees of rotation. X represents horizontal rotation. Y represents vertical rotation. A potential problem is if the camera reaches the top of the sphere and starts to go over the top so that the camera would get flipped upside down. I can think of a couple of solutions but nothing explicit I could put into code. I'm new at this. I have yet to go through the tutorials and documentation.

songho
11-04-2005, 06:22 AM
I mostly use Yaw -> Pitch -> Roll order.
Luckly, Roll is not necessary in your case.
And I found Yaw->Pitch is better than Pitch->Yaw for orbital rotation. (Try both order yourself which is suitable for you)

Yaw: rotate xz plane about y axis
Pitch: rotate yz plane about x axis

==song==

11-09-2005, 12:04 AM
Well finally I did get something that I wanted. Well these codes I read from online adapted. So chris , u can understand these codes and let me know how it works

//Class for a camera.
class CCamera
{
public:

CVector3 mPosition ;
CVector3 mView ;
CVector3 mUp ;

//Moves the camera forward and backward.
GLvoid MoveCamera(GLfloat Speed)
{
CVector3 Vect = mView - mPosition ;

mPosition.x = mPosition.x + Vect.x * Speed ;
mPosition.z = mPosition.z + Vect.z * Speed ;

mView.x = mView.x + Vect.x * Speed ;
mView.z = mView.z + Vect.z * Speed ;
}

GLvoid PositionCamera(GLfloat PosX , GLfloat PosY , GLfloat PosZ ,
GLfloat ViewX , GLfloat ViewY , GLfloat ViewZ ,
GLfloat UpX , GLfloat UpY , GLfloat UpZ)
{
mPosition = CVector3(PosX , PosY , PosZ) ;
mView = CVector3(ViewX , ViewY , ViewZ) ;
mUp = CVector3(UpX , UpY , UpZ) ;
}

GLvoid RotateCamera(GLfloat Speed)
{
CVector3 Vector = mView - mPosition ; // Get the view

mView.x = (GLfloat)(mPosition.x + Vector.x * cos(Speed) - Vector.z *
sin(Speed)) ;
mView.z = (GLfloat)(mPosition.z + Vector.x * sin(Speed) + Vector.z *
cos(Speed)) ;
}

//This rotates the view around the position using an axis-angle
//rotation
GLvoid RotateView(float angle, float x, float y, float z)
{
CVector3 vNewView;

// Get the view vector (The direction we are facing)
CVector3 vView = mView - mPosition;

// Calculate the sine and cosine of the angle once
float cosTheta = (float)cos(angle);
float sinTheta = (float)sin(angle);

// Find the new x position for the new rotated point
vNewView.x = (cosTheta + (1 - cosTheta) * x * x) * vView.x;
vNewView.x += ((1 - cosTheta) * x * y - z * sinTheta) * vView.y;
vNewView.x += ((1 - cosTheta) * x * z + y * sinTheta) * vView.z;

// Find the new y position for the new rotated point
vNewView.y = ((1 - cosTheta) * x * y + z * sinTheta) * vView.x;
vNewView.y += (cosTheta + (1 - cosTheta) * y * y) * vView.y;
vNewView.y += ((1 - cosTheta) * y * z - x * sinTheta) * vView.z;

// Find the new z position for the new rotated point
vNewView.z = ((1 - cosTheta) * x * z - y * sinTheta) * vView.x;
vNewView.z += ((1 - cosTheta) * y * z + x * sinTheta) * vView.y;
vNewView.z += (cosTheta + (1 - cosTheta) * z * z) * vView.z;

// Now we just add the newly rotated vector to our position to set
// our new rotated view of our camera.
mView = mPosition + vNewView;
}

GLvoid RotateAroundPoint(CVector3 vCenter, float angle, float x, float
y, float z)
{
CVector3 vNewPosition;

CVector3 vPos = mPosition - vCenter;

// Calculate the sine and cosine of the angle once
float cosTheta = (float)cos(angle);
float sinTheta = (float)sin(angle);

// Find the new x position for the new rotated point
vNewPosition.x = (cosTheta + (1 - cosTheta) * x * x) * vPos.x;
vNewPosition.x += ((1 - cosTheta) * x * y - z * sinTheta) * vPos.y;
vNewPosition.x += ((1 - cosTheta) * x * z + y * sinTheta) * vPos.z;

// Find the new y position for the new rotated point
vNewPosition.y = ((1 - cosTheta) * x * y + z * sinTheta) * vPos.x;
vNewPosition.y += (cosTheta + (1 - cosTheta) * y * y) * vPos.y;
vNewPosition.y += ((1 - cosTheta) * y * z - x * sinTheta) * vPos.z;

// Find the new z position for the new rotated point
vNewPosition.z = ((1 - cosTheta) * x * z - y * sinTheta) * vPos.x;
vNewPosition.z += ((1 - cosTheta) * y * z + x * sinTheta) * vPos.y;
vNewPosition.z += (cosTheta + (1 - cosTheta) * z * z) * vPos.z;

// Now we just add the newly rotated vector to our position to set
// our new rotated position of our camera.
mPosition = vCenter + vNewPosition;
}

} ;

Thats a class for class which has everything

cheers

Siddharth