Hi working friends, I am developing a game which needs a node rotation exactly as Google Earth interface does with the earth model. I have solved the 2D-3D transforming by interacting with the mouse as well as to distinguish the bounding area for that node in order to avoid clicking on empty areas or other nodes. The problem comes with the rotation.
If you check the Google Earth interface you can see if your mouse move [up-down] your earth rotate downwards, or [right-left] your earth rotate leftwards, it doesn't matter the 3D model position. Oposite on my irrlicht project the rotation is exactly as Google Earth interface, but when I reach some "limits" the rotation becomes non-intuitive, I want to solve that problem.
I thing that I can make the RelativeTransformation becomes the AbsoluteTransformation every time I stop rotating the model but I don't know how can that be done. [/url]
Problems creating a Google Earth interface
Surely I will need a lot of math understanding that topics, could you please send more tutorials for understanding that maths and later usign it with irrlicht, I remember when I began my project usign GLUT the behavior of the rotation was very similar to Google Earth and there was a very few algorith besides, why is so dificult with Irrlicht?
This algorith received the x,y mouse position
This algorith use the alfa, beta and gama angles for the rotation :
It will be very useful to undestand quatenions with code examples, thanks
This algorith received the x,y mouse position
Code: Select all
void AreaMateria::moverModelo(int x, int y){
if(!false){
alfa = (alfa + (y - y0));
beta = (beta + (x - x0));
x0 = x; y0 = y;
}
else
if(false){
gama = (gama - (x - xz0));
xz0 = x;
gama= (gama - (y - yz0));
yz0=y;
}
glutPostRedisplay();
}
This algorith use the alfa, beta and gama angles for the rotation :
Code: Select all
void AreaMateria::despliega(){
glPushMatrix();
despliegaModelo(fondo,activarnormales);
glPopMatrix();
glPushMatrix();
glBlendFunc ( GL_SRC_ALPHA, GL_ONE );
glEnable(GL_BLEND );
glRotatef(alfa, 1.0f, 0.0f, 0.0f);
glRotatef(beta, 0.0f, 1.0f, 0.0f);
glRotatef(gama, 0.0f, 0.0f, 1.0f);
despliegaModelo(modelo1,activarnormales);
glDisable(GL_BLEND );
glPopMatrix();
}
I had the same problem. I've tried to figure out, how to make the same camera motions like in the game Lineage2. The basic principles are almost the same like in GoogleEarth. But I didn't know about any of these quaternions, Euler angles etc..
So, I took the paper sheet and began to draw my camera in 3d-coordinates
So, thats the code from my camera wrapper class(just a few trigonometry...) :
I hope, it will help...
So, I took the paper sheet and began to draw my camera in 3d-coordinates
So, thats the code from my camera wrapper class(just a few trigonometry...) :
Code: Select all
void CameraWrapper::UpdateData()
{
*curr_pos = this->camera_node->getPosition();
*targ_pos = this->camera_node->getTarget();
R = this->camera_node->getPosition().getDistanceFrom(*targ_pos);
D->X = curr_pos->X - targ_pos->X;
D->Y = curr_pos->Y - targ_pos->Y;
D->Z = curr_pos->Z - targ_pos->Z;
xr = atan(D->Z / D->Y) * 180.0f / PI;
yr = atan(D->Z / D->X) * 180.0f / PI;
zr = atan(D->Y / D->X) * 180.0f / PI;
curr_angle = acos(D->Y / R) * 180.0f / PI;
xangle = atan(D->Z / D->X) * 180.0f / PI;
zangle = atan(D->X / D->Z) * 180.0f / PI;
}
void CameraWrapper::SetNewPos()
{
newD->X = curr_pos->X - targ_pos->X;
newD->Y = curr_pos->Y - targ_pos->Y;
newD->Z = curr_pos->Z - targ_pos->Z;
if((D->X > 0) ^ (newD->X > 0))
if(newD->X > 0)
curr_pos->X -= 2*newD->X;
else
curr_pos->X += 2*newD->X;
if((D->Z > 0) ^ (newD->Z > 0))
if(newD->Z > 0)
curr_pos->Z -= 2*newD->Z;
else
curr_pos->Z += 2*newD->Z;
camera_node->setPosition(*curr_pos);
}
void CameraWrapper::TurnRight(f32 angle)
{
this->UpdateCurrPos();
curr_pos->rotateXZBy(angle, *targ_pos);
camera_node->setPosition(*curr_pos);
}
void CameraWrapper::TurnLeft(f32 angle)
{
this->TurnRight(-angle);
}
void CameraWrapper::TurnDown(f32 angle)
{
this->UpdateData();
if(curr_angle <= 88.9f)
{
curr_angle += angle;
curr_pos->Y = cos(curr_angle*PI/180.0f)*R + targ_pos->Y;
vSum = R * sin(curr_angle*PI/180.0f);
curr_pos->X = vSum * cos(xangle*PI/180.0f) + targ_pos->X;
curr_pos->Z = vSum * cos(zangle*PI/180.0f) + targ_pos->Z;
this->SetNewPos();
}
}
void CameraWrapper::TurnUp(f32 angle)
{
this->UpdateData();
if(curr_angle >= 1.1f)
{
curr_angle -= angle;
curr_pos->Y = cos(curr_angle*PI/180.0f)*R + targ_pos->Y;
vSum = R * sin(curr_angle*PI/180.0f);
curr_pos->X = vSum * cos(xangle*PI/180.0f) + targ_pos->X;
curr_pos->Z = vSum * cos(zangle*PI/180.0f) + targ_pos->Z;
this->SetNewPos();
}
}
Thanks Andrey it seems to be a posible answer to my problem, searching about quaternions I found some code to rotate with a quaternion variable, I don't undernstand very well but I think this is another solution, I hope some one can explain me this:
My original code
quaternion code
My original code
Code: Select all
alfa = (alfa+ (event.MouseInput.Y - y));
beta = (beta + (event.MouseInput.X - x));
x = event.MouseInput.X; y = event.MouseInput.Y;
node-> setRotation(core::vector3df( -0.5*alfa,
-0.5*beta,0 ));
Code: Select all
/*get the actual rotation and covert it to quaternion*/
core::vector3df euler = node->getRotation();
core::quaternion current(euler.X, euler.Y, euler.Z);
/*get angles because mouse movement*/
alfa = (alfa+ (event.MouseInput.Y - y));
beta = (beta + (event.MouseInput.X - x));
x= event.MouseInput.X; y = event.MouseInput.Y;
axis = core::vector3df(-0.5*alfa, -0.5*beta, 0.0f);
axis.normalize();
core::quaternion rotation;
rotation.fromAngleAxis(0.1*PI, axis);
rotation = current*rotation;
rotation.toEuler(euler);
/*conversion between radians and euler angles*/
node->setRotation(euler*57.2957795);
Hi again!! I have been working with those quaternions and I have made my project to work exactly as when I was using the simple setRotation (..)instruction, here is my code running correctly:
The end effect is the same as with the simple setRotation(..) instruction, remember what I need is simple end soft rotation interface as
Google Earth if you move your mouse left-rigth you need to rotate the node to rigth, it doesn't matter the relative or absolute rotation, if you move your mouse top-down you rotate down, thanks again the quaternions tutorial from Ogre Wiki was perfect!!!
Code: Select all
/*reference to obtain the actual rotation I haven't found the use of
current yet but in other post they used it*/
core::vector3df euler1 = node->getRotation();
core::quaternion current(euler1.X,euler1.Y,euler1.Z);
/*angles produced by mouse movement*/
alfa = (alfa+ (event.MouseInput.Y - y));
beta = (beta+ (event.MouseInput.X - x));
x = event.MouseInput.X;y = event.MouseInput.Y;
/*x-arounn rotation, y-around rotation and rotation*/
core::quaternion rotationX;
core::quaternion rotationY;
core::quaternion rotation;
/*the vectors where the rotations are made don't foget t
normalize*/
core::vector3df axisX(1.0f,0.0f,0.0f);
core::vector3df axisY(0.0f,1.0f,0.0f);
axisX.normalize();
axisY.normalize();
/*
angle/axis rotation for quaternions receive only
radians we have to convert it
radians = degrees *(PI/180)
*/
rotationX.fromAngleAxis(alfa*PI/180.0f,axisX);
rotationY.fromAngleAxis(-beta*PI/180.0f,axisY);
/*it doesn't matter the order rotationY*rotationX here because the
effect is the same
concatenate the X rotation with Y rotation*/
rotation = rotationX*rotationY;
/*convert the concatenated rotation to Euler angles on radians*/
rotation.toEuler(euler1);
/*set the rotation of auler angles converting radians to degrees*/
node->setRotation(euler1* 57.2957795);
Google Earth if you move your mouse left-rigth you need to rotate the node to rigth, it doesn't matter the relative or absolute rotation, if you move your mouse top-down you rotate down, thanks again the quaternions tutorial from Ogre Wiki was perfect!!!