Jump to content

  • Log In with Google      Sign In   
  • Create Account


#ActualNick Joseph

Posted 14 February 2013 - 08:38 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


#5Nick Joseph

Posted 14 February 2013 - 01:29 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;
        }

 

 

....however if I replace...

 

                _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


#4Nick Joseph

Posted 14 February 2013 - 12:30 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 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;
        }

 

 

....however if I replace...

 

                _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


#3Nick Joseph

Posted 14 February 2013 - 12:28 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 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;
        }

 

 

....however if I replace the SLERP code above with...

 

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


#2Nick Joseph

Posted 14 February 2013 - 11:25 AM

Hey guys, I'm once again stuck in what appears to be an obvious mess that should be easy to solve but after ~16 hours I've become desperate and am turning to you all for your expert advice.

 

Before I throw a ton of code out there, the gist of my engine is that actors have a bunch of components (animation, physics, transform, etc) and the following is the code that runs in my "RotationAnimationComponent" on every tick.  It's job is to rotate the actor until it's facing a specified direction (target) using SLERP to animate the rotation over multiple frames.

 

The issue is that if the actor isn't facing the negative Z axis, it starts rotating on some arbitrary axis.

 

(Quick side note, I'm rounding the DOT value because otherwise it takes the SLERP too long to get there...)

 

Here's the code that runs on the animation component's update, if anyone sees anything out of the ordinary or has suggestions on how I can make it better please let me know...

 

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 curios, 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;
        }

 

 

....thanks to anyone who even takes the time to look at this.  It's appreciated!

 

- Bullgoose311


#1Nick Joseph

Posted 13 February 2013 - 09:44 PM

Hey guys, I'm once again stuck in what appears to be an obvious mess that should be easy to solve but after ~16 hours I've become desperate and am turning to you all for your expert advice.

 

Before I throw a ton of code out there, the gist of my engine is that actors have a bunch of components (animation, physics, transform, etc) and the following is the code that runs in my "RotationAnimationComponent" on every tick.  It's job is to rotate the actor until it's facing a specified direction (target) using SLERP to animate the rotation over multiple frames.

 

The issue is that if the actor isn't facing the negative Z axis, it starts rotating on some arbitrary axis.

 

(Quick side note, I'm rounding the DOT value because otherwise it takes the SLERP too long to get there...)

 

Here's the code that runs on the animation component's update, hopefully it's not too long or messy...

 

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 curios, 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;
        }

 

 

....thanks to anyone who even takes the time to look at this.  It's appreciated!

 

- Bullgoose311


PARTNERS