Basic Body rotation question

deshan

11-01-2010 03:59:28

Hi
I am writing a code to rotate(actuall yaw) the body A to direction of the bodyB. Code works but sometimes it rotates to unexpected direction. What happen is body rotate upside down(pitch).
Ogre::Quaternion EnemyCharacter::playerFoundRotationCalculation()
{
Vector3 enemyPosition = enemyBody->getGlobalPosition().as<Ogre::Vector3>();
Vector3 playerPosition = playerBody->getGlobalPosition().as<Ogre::Vector3>();

enmPosition.y = 0;
playerPosition.y = 0;

Vector3 directionToPlayer = (playerPosition - enemyPosition);
directionToPlayer.normalise();

Ogre::Quaternion enemyOrientation = enemyBody->getGlobalOrientationQuat().as<Ogre::Quaternion>();
Vector3 src = enemyOrientation * Ogre::Vector3::UNIT_X;

Ogre::Quaternion quat = src.getRotationTo(directionToPlayer);
return quat * enemyOrientation;
}}


calling to rotate
enemyBody->setGlobalOrientationQuat(playerFoundRotationCalculation());
If you can see this is wrong please tell me. I have noticed that this happens when player position is exactly same or very close enemy position.

LucaMoller

01-02-2010 21:25:11

I took a look at your code, I think it is right.
About the strange things that happen when the player and the enemy are too close, imagine the player and the enemy switching places, the enemy rolling upside down would be an expected thing to happen (he could turn 180ยบ in many different ways, going upside down is one of them).

Take a look at the positions the getGlobalPosition() is giving you (maybe your physic shapes are centered on it).

Imagine the dots as the position returned by getGlobalPosition() and P and E the not centered shapes of the player and the enemy. If they are disposed this way, what I said before can easily happen: (think of the undelines as spaces)
P_.____._E ---> (they get more closer and...) P..E (mad rotation! :o )

The dots can exchange place without P and E exchanging places...

If this upside down stuff never happen when the player and the enemy are far away from each other, then I would assume the code is right, and you have that uncentered shape stuff I said, or you need a better aproach when player and enemy are too close, or you shouldn't let them get too close! :wink:

deshan

02-02-2010 03:08:43

Hi
thanks for answering. Perhaps you may right! I think I found a solution. I have included this
src.y = 0.0f;
src.normalise();

just after this line
Vector3 src = enemyOrientation * Ogre::Vector3::UNIT_X;
Now it seems to be works fine, wired thing not yet happen after adding above. But still can't guarantee and testing is not possible because this not happens always.
How ever let me post a code thhat you can try. This code let you rotate the enemy body to player body. This works fine for me now. Glad if some one can test. I am using slerp(spherical linear interpolation) for smooth rotation
Ogre::Quaternion enemyOrientation_rotNext;
Ogre::Quaternion rotateBy;
Ogre::Real mRotProgress = 0;
Ogre::Real mRotFactor = 1.0f / 50;

void EnemyCharacter::playerFoundRotationCalculation()
{
Vector3 enmPosition = enemyBody->getGlobalPosition().as<Ogre::Vector3>();
Vector3 playerPosition = playerBody->getGlobalPosition().as<Ogre::Vector3>();

enemyOrientation_rotNext = enemyBody->getGlobalOrientationQuat().as<Ogre::Quaternion>();

enmPosition.y = 0;
playerPosition.y = 0;

Vector3 src = enemyOrientation_rotNext*Ogre::Vector3::UNIT_X;
src.y = 0.0f;
src.normalise();

Vector3 flatdirectionToPlayer = (playerPosition - enmPosition);
flatdirectionToPlayer.normalise();

Ogre::Quaternion quat = src.getRotationTo(flatdirectionToPlayer);
rotateBy = quat*enemyOrientation_rotNext;

// if you need direction to player (to shoot) here no need of changing the y as 0
// directionToPlayer = playerBody->getGlobalPosition().as<Ogre::Vector3>()- enemyBody->getGlobalPosition().as<Ogre::Vector3>();
// directionToPlayer.normalise();
}

playerFoundRotationCalculation()
while(true)
{
mRotProgress += mRotFactor;
if(mRotProgress>1)
{
break;
}
else
{
Quaternion delta = Quaternion::Slerp(mRotProgress, enemyOrientation_rotNext, rotateBy, true);
enemyBody->setGlobalOrientationQuat(delta);
}
}