Walking around a sphere

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
freezzo
Posts: 27
Joined: Thu Mar 08, 2007 6:36 pm
Contact:

Walking around a sphere

Post by freezzo »

Hello All. I am trying to place a character on a sphere and walk around it. I am pretty close, except I have two issues:

1. When I get to the pole, i rotate really fast when moving forward (Gimbal lock?)
2. When I move forward, I am following travel the sphere at the same latitude, as opposed to moving in the true forward direction. (Same with strafing)

Here is the code I have. Any help would be greatly appreciated!

Code: Select all

 
core::vector3df masterUp = player->getPosition() - planet->getPosition();
core::vector3df dir(0, 1, 0);
core::vector3df masterDirection = dir.crossProduct(masterUp);
 
masterDirection.normalize();
masterUp.normalize();
 
core::vector3df realUp = masterDirection.crossProduct(masterUp).normalize();
realUp = realUp.crossProduct(masterDirection);
 
core::quaternion quatDirection;
quatDirection.rotationFromTo(core::vector3df(0, 0, 1), masterDirection);
 
core::vector3df worldUp(0, 1, 0);
core::matrix4 mat;
mat = quatDirection.getMatrix();
mat.rotateVect(worldUp);
 
core::quaternion quatUp;
quatUp.rotationFromTo(worldUp, realUp);
 
core::quaternion quat = quatDirection * quatUp;
 
core::vector3df eulers;
quat.toEuler(eulers);
eulers *= core::RADTODEG;
 
player->setRotation(eulers);
player->updateAbsolutePosition();
mat = player->getAbsoluteTransformation();
 
core::vector3df slaveDirection(0, 0, 1);
mat.rotateVect(slaveDirection);
 
core::vector3df slaveUp(0, 1, 0);
mat.rotateVect(slaveUp);
 
 
// move player relative to the direction they are aligned.
core::vector3df pmove(0, 0, 0);
if (receiver.IsKeyDown(irr::KEY_KEY_W))
        pmove.Z += 1.f;
 
if (receiver.IsKeyDown(irr::KEY_KEY_S))
        pmove.Z -= 1.f;
 
if (receiver.IsKeyDown(irr::KEY_KEY_A))
        pmove.X += 1.f;
 
if (receiver.IsKeyDown(irr::KEY_KEY_D))
        pmove.X -= 1.f;
 
// move the player
core::vector3df playerPosition( player->getPosition() );
 
// rotate the movement vector into parent coordinate system
player->getRelativeTransformation().rotateVect(pmove);
 
const core::vector3df velocity(10.f, 10.f, 10.f); // we can move faster forward than sideways
 
// apply movement over elapsed time at provided velocity
playerPosition += (pmove * (velocity * frameDeltaTime));
 
// update the final position
player->setPosition(playerPosition);
 
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: Walking around a sphere

Post by Mel »

1.- Yeah, it is a gimbal lock
2.- you seem to be moving in 2D over the sphere, not really "in 3D", thus, you move along the "latitude and the longitude" not over the surface.

The simplest approach is to constraint your position to be at a constant distance from the center of the sphere, and update your new position and local orientation with regard to the last local orientation, not the world orientation, this is a way to avoid the gimbal lock and to move freely all at once.

To do so, You keep 3 vectors, namely "Up, "Front" and "Right". Moving is just a mater of composing these front and right vectors with your current position, and then updating this new position so it sticks to the surface of the sphere, then, update UP, RIGHT and FRONT accordingly. Up is picked up from the sphere, and front/right can be recalculated using the last frame Up and Right vectors (for instance, if you move forward, the right vector remains the same, so you can update Front crossing it with UP, and so on). If you want to rotate your character, you can do so by rotating around the "up" vector FRONT and RIGHT, and that should do it.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Virion
Competition winner
Posts: 2148
Joined: Mon Dec 18, 2006 5:04 am

Re: Walking around a sphere

Post by Virion »

Use quaternion instead of vector3d to avoid gimbal lock issue
Post Reply