Problems creating a Google Earth interface

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
itzjac
Posts: 57
Joined: Fri Nov 17, 2006 7:41 pm
Location: Mexico City

Problems creating a Google Earth interface

Post by itzjac »

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. :D [/url]
Robert Y.
Posts: 212
Joined: Sun Jan 28, 2007 11:23 pm

Post by Robert Y. »

What you are describing is Gimbal Lock, which occurs when you try to rotate with Euler angles.

Search the net for Gimbal Lock, Trackball Rotation and Quaternions to find a solution.
LLDD
Posts: 43
Joined: Fri May 11, 2007 9:50 am

Post by LLDD »

This basic quaternion tutorial may help you: http://sacredsoftware.net/tutorials/Qua ... ions.xhtml
________
Gm Foods
Last edited by LLDD on Sun Feb 20, 2011 7:49 am, edited 1 time in total.
itzjac
Posts: 57
Joined: Fri Nov 17, 2006 7:41 pm
Location: Mexico City

Post by itzjac »

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

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();
}
It will be very useful to undestand quatenions with code examples, thanks :lol:
Andrey
Posts: 17
Joined: Sat Aug 05, 2006 6:53 pm
Location: Ukraine

Post by Andrey »

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...) :

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();
	}
}
I hope, it will help...
itzjac
Posts: 57
Joined: Fri Nov 17, 2006 7:41 pm
Location: Mexico City

Post by itzjac »

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

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 ));

quaternion code

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);
itzjac
Posts: 57
Joined: Fri Nov 17, 2006 7:41 pm
Location: Mexico City

Post by itzjac »

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:

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);
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!!! :D
Post Reply