Original Post
Hello everyone. I'm working on a bot for a first person shooter. In order to give the bot a smoother and controllable aiming system I'm using the quaternion class from the Wildmagic Math library along with the following aiming function. Here's the function that handles all my aiming. The line m_Facing = (quat * 0.65f) * m_Facing; is what I did in order to make the rotation happen over time. If I do m_Facing = quat* m_Facing; it does the entire rotation all in the same frame. There seems to be a pretty rare bug where the bot stops rotating. It appears that it happens when the desired facing vector faces opposite the current facing. Anyone know anything about this? For reference, here is the GetRotationTo function that I actually found within the Ogre3d engine. Could it be that the dot == 1.0 in this, so no quaternion is generated, and hence the bot does not rotate? The wierd thing is that when the bot stops rotating, he stops rotating until he dies, meaning, once he is broke, even as he runs around the level he keeps facing the direction he became "broke" in, even when newer facing vectors are not the opposite of current facing, which leads me to think possibly his facing gets screwed up initially and results in every further check to generate no rotation. When he dies and respawns, or acquires a target he works fine and starts rotating toward the target or waypoints. Any ideas?
bool Client::TurnTowardPosition(const Vector3f &_pos)
{
Vector3f newFacing = (_pos - m_Position);
newFacing.Normalize();
// See how close we are to
float fDot = m_Facing.Dot(newFacing);
// Determine the angle between the heading vector and the target
float fAngle = Wml::Mathf::ACos(fDot);
// Just snap the facing if it's very close.
const double WeaponAimTolerance = 3.0f*Mathf::DEG_TO_RAD;
if(fAngle < WeaponAimTolerance)
{
m_Facing = newFacing;
return true;
}
int iSign = m_Facing.Sign(newFacing);
Wml::Quaternionf quat;
quat.GetRotationTo(m_Facing, newFacing);
m_Facing = (quat * 0.65f) * m_Facing;
m_Facing.Normalize();
return false;
}
void Quaternion<Real>::GetRotationTo(const Vector3<Real>& _from, const Vector3<Real>& _to)
{
// Based on Stan Melax's article in Game Programming Gems
Vector3<Real> c = _from.Cross(_to);
// NB if the crossProduct approaches zero, we get unstable because ANY axis will do
// when v0 == -v1
Real d = _from.Dot(_to);
// If dot == 1, vectors are the same
if (d >= 1.0f)
{
*this = Quaternion<Real>::IDENTITY;
}
Real s = Math<Real>::Sqrt( (1+d)*2 );
Real invs = 1 / s;
X() = c.X() * invs;
Y() = c.Y() * invs;
Z() = c.Z() * invs;
W() = s * (Real)0.5;
}