• Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

We're also offering banner ads on our site from just \$5! 1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.

# Nick Joseph

Member Since 05 Jan 2012
Offline Last Active Mar 15 2013 09:05 AM

### Rotation Animation - Slerping the Kool-Aid Part 2

13 February 2013 - 09:44 PM

Hey guys, I'm having some SLERP issues and was hoping one of you guys' could help me with your expertise...

(The following code is the Update method of a component whose responsibility is to rotates it's actor towards a given target using SLERP over the course of multiple frames...)

The problem I'm having is that the following causes the actor to rotate on some arbitrary axis when it is facing any direction other than the negative Z axis...

```public override void Update(GameTime gameTime)
{
if (this.Status == AnimationStatus.Running)
{
TransformComponent transformComponent = this.Owner.GetComponent<TransformComponent>();

Vector3 position = transformComponent.Transform.Translation;

Vector3 forwardVector = Vector3.Normalize(transformComponent.Transform.Forward);

float dot = (float)Math.Round(
Vector3.Dot(
forwardVector,
Vector3.Normalize(_targetVector)),
4);

if (dot == 1)
{
this.Status = AnimationStatus.Finished;

return;
}

_targetVector.Normalize();

Vector3 rotationAxis =
Vector3.Normalize(
Vector3.Cross(
_targetVector,
forwardVector));

float rotationAngle = MathUtilities.GetSignedAngle(
forwardVector,
_targetVector);

_slerpAmount += (float)gameTime.ElapsedGameTime.Milliseconds / 20000f;

Quaternion qStart = Quaternion.CreateFromRotationMatrix(transformComponent.Transform);

Quaternion qEnd = Quaternion.CreateFromAxisAngle(rotationAxis, rotationAngle);

Quaternion qSlerp = Quaternion.Slerp(
qStart,
qStart * qEnd,
_slerpAmount);

Matrix rotation = Matrix.CreateFromQuaternion(qSlerp);

rotation.Translation = position;

PhysicsComponent physicsComponent = this.Owner.GetComponent<PhysicsComponent>();

physicsComponent.KinematicMove(rotation);
}
}
```

...and if anyone's curious, here's the GetSignedAngle()  method...

```public static float GetSignedAngle(
Vector3 a,
Vector3 b)
{
a.Normalize();

b.Normalize();

float theta = (float)Math.Acos(
Vector3.Dot(
a,
b));

Vector3 normal = Vector3.Normalize(
Vector3.Cross(
b,
a));

Vector3 v3 = Vector3.Normalize(
Vector3.Cross(
a,
normal));

if (Vector3.Dot(
v3,
b) > 0)
{
theta *= -1;
}

return theta;
}
```

....the really odd thing (and proof that SLERP isn't working as I'd expect it to), is that if I replace the code that performs the SLERP...

```                _slerpAmount += (float)gameTime.ElapsedGameTime.Milliseconds / 20000f;

Quaternion qStart = Quaternion.CreateFromRotationMatrix(transformComponent.Transform);

Quaternion qEnd = Quaternion.CreateFromAxisAngle(rotationAxis, rotationAngle);

Quaternion qSlerp = Quaternion.Slerp(
qStart,
qStart * qEnd,
_slerpAmount);

Matrix rotation = Matrix.CreateFromQuaternion(qSlerp);
```

...with a regular old rotation transformation like so...

```Matrix rotation = transformComponent.Transform *
Matrix.CreateFromAxisAngle(
rotationAxis, rotationAngle);
```

...then the object is rotated correctly (hoever it is instant and so I lose the rotation "animation").

If anyone has any ideas as to how this could be happening or just a suggestion on how I can make this code better please let me know.

Thanks!

- Bullgoose311

### Slerping the Kool Aid - Help!

25 January 2013 - 08:13 PM

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!

### Suggestions - .NET Developer to Game Developer

05 January 2012 - 02:43 PM

Hello all, I'm a fairly experienced .NET web architect looking to move to game development (preferably still within the land of .NET). Anyone have any recommendations on packages, technologies or reading material that can get me started?

I was hoping for a well known and respected book that can take an experienced programmer and teach them the methodologies / techniques behind game development without the beginner's guide to programming if that makes sense...

Thanks!

Nick

PARTNERS