After 16 hours I have nowhere to turn and have become desperate to so I'm going to be posting quite a bit of code here, just warning ya. I can't seem to wrap my head around slerping an object...
The following code allows me to immediately rotate my AI actor to face his next patrol point...
TransformComponent transformComponent = _actor.GetComponent<TransformComponent>();
Vector3 position = transformComponent.Transform.Translation;
Vector3 currentPatrolPoint = _patrolPoints.ElementAt(_currentPatrolPoint);
Vector3 difference = (currentPatrolPoint - position);
if (_hasFinishedRotating == false)
{
Vector3 lookAtDirection = Vector3.Normalize(difference);
Vector3 forward = Vector3.Normalize(transformComponent.Transform.Forward);
float forwardDot = (float)Math.Round(
Vector3.Dot(
forward,
lookAtDirection),
DOT_PRECISION);
if (forwardDot != 1)
{
Vector3 rotationAxis = Vector3.Cross(lookAtDirection, forward);
float rotationAngle = MathUtilities.GetUnsignedAngle(
forward,
lookAtDirection);
Vector3 right = Vector3.Normalize(transformComponent.Transform.Right);
float rightDot = (float)Math.Round(
Vector3.Dot(
right,
lookAtDirection),
DOT_PRECISION);
if (rightDot > 0)
{
rotationAngle *= -1;
}
Matrix rotation = transformComponent.Transform;
rotation *= Matrix.CreateFromAxisAngle(
rotationAxis,
rotationAngle);
rotation.Translation = position;
PhysicsComponent physicsComponent = _actor.GetComponent<PhysicsComponent>();
physicsComponent.KinematicMove(rotation);
}
else
{
_hasFinishedRotating = true;
}
}
...but now I want him to SLERP his rotation to make it more realistic. I'm definitely not an expert but from what I understand and read the following should get me there (NOTE: I do know that SLERP won't get me 100% there so I need some type of threshold but even after trying that I still see whacky results so the piece I'm not understanding has to be here somewhere...)
TransformComponent transformComponent = _actor.GetComponent<TransformComponent>();
Vector3 position = transformComponent.Transform.Translation;
Vector3 currentPatrolPoint = _patrolPoints.ElementAt(_currentPatrolPoint);
Vector3 difference = (currentPatrolPoint - position);
if (_hasFinishedRotating == false)
{
Vector3 lookAtDirection = Vector3.Normalize(difference);
Vector3 forward = Vector3.Normalize(transformComponent.Transform.Forward);
float forwardDot = (float)Math.Round(
Vector3.Dot(
forward,
lookAtDirection),
DOT_PRECISION);
if (forwardDot != 1)
{
Vector3 rotationAxis = Vector3.Cross(lookAtDirection, forward);
float rotationAngle = MathUtilities.GetUnsignedAngle(
forward,
lookAtDirection);
Vector3 right = Vector3.Normalize(transformComponent.Transform.Right);
float rightDot = (float)Math.Round(
Vector3.Dot(
right,
lookAtDirection),
DOT_PRECISION);
if (rightDot > 0)
{
rotationAngle *= -1;
}
Quaternion qStart = Quaternion.CreateFromRotationMatrix(transformComponent.Transform);
Quaternion qEnd = Quaternion.CreateFromAxisAngle(rotationAxis, rotationAngle);
Quaternion qSlerp = Quaternion.Slerp(
qStart,
qEnd,
(float)gameTime.ElapsedGameTime.Milliseconds / 1000f);
Matrix rotation = Matrix.CreateFromQuaternion(qSlerp);
rotation.Translation = position;
PhysicsComponent physicsComponent = _actor.GetComponent<PhysicsComponent>();
physicsComponent.KinematicMove(rotation);
}
else
{
_hasFinishedRotating = true;
}
}
...but it looks like my actor only rotates maybe a little more than half way than hangs. If anyone has any ideas, suggestions, etc on how I can make this code better or if you happen to spot the problem (gold star!) I'd really appreciate it.
Thanks!