Game Development Community

Loading animations

by Derrick Lau · in Torque X 3D · 05/03/2010 (12:10 pm) · 15 replies

I have the following code in my Game.BeginRun() method:

TorqueObject objAdam = TorqueObjectDatabase.Instance.FindObject<TorqueObject>("AdamTorqueObject");

T3DAnimationComponent adamAnimations = new T3DAnimationComponent();
objAdam.Components.AddComponent(adamAnimations);

adamAnimations.Name = "AdamAnimations";
adamAnimations.SceneGroupName = "AdamTorqueObjects";

TSAnimation adamBack = new TSAnimation();
adamBack.SequenceFilename = @"dataModelsAdamplayer_back.dsq";
adamBack.SequenceName = "Back";
adamBack.Name = "Back";
adamAnimations.AddAnimation(adamBack); //failing here


However, I always crash on the T3DAnimationComponent.AddAnimation() call, when it calls the Setup() method, on this line:

TorqueInterfaceWrap<IRenderable3D> render = manager.Owner.Components.GetInterface<TorqueInterfaceWrap<IRenderable3D>>("render", manager.SceneGroupName);

Specifically, my program thinks the T3DAnimationComponent.Owner property is a NULL pointer.

How do I initialize the Owner property correctly?

#1
05/03/2010 (2:50 pm)
I think you need a thread name. I have this and it works well:

//Forward Animation
TSAnimation animationForward = new TSAnimation();
animationForward.ThreadName = "ActionThread";
animationForward.SequenceName = "run";
animationForward.SequenceFilename = @"data\anim\player_forward.dsq";
animationForward.Name = "Forward";
componentAnimation.AddAnimation(animationForward);
#2
05/03/2010 (4:45 pm)
Added the thread name but it still fails with the same exception.

How do you add the T3DAnimationComponent to your TorqueObject? I assume the animation there is for a TorqueObject; is that a correct assumption?

And what is the value of your componentAnimation.Owner property? And how did you set that Owner property?
#3
05/03/2010 (7:21 pm)
using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

using GarageGames.Torque.Core;
using GarageGames.Torque.Util;
using GarageGames.Torque.Sim;
using GarageGames.Torque.T3D;
using GarageGames.Torque.Platform;
using GarageGames.Torque.SceneGraph;
using GarageGames.Torque.MathUtil;


namespace StarterGame3D
{
    [TorqueXmlSchemaType]
    public class MovementComponent3D : T3DInputComponent, IAnimatedObject
    {
        //======================================================
        #region Static methods, fields, constructors
        #endregion

        //======================================================
        #region Constructors
        #endregion

        //======================================================
        #region Public properties, operators, constants, and enums

        public float MoveSpeed
        {
            get { return _moveSpeed; }
            set { _moveSpeed = value; }
        }


        public float TurnSpeed
        {
            get { return _turnSpeed; }
            set { _turnSpeed = value; }
        }

        public bool InvertedCamera
        {
            get { return _invertedCamera; }
            set { _invertedCamera = value; }
        }


        public InputMap InputMap
        {
            get { return _inputMap; }
        }

        #endregion

        //======================================================
        #region Public methods

        public virtual void ProcessTick(Move move, float dt)
        {
        }


        public virtual void InterpolateTick(float k)
        {
        }


        public override void CopyTo(TorqueComponent obj)
        {
            base.CopyTo(obj);

            MovementComponent3D obj2 = (MovementComponent3D)obj;
            obj2.InvertedCamera = InvertedCamera;
            obj2.PlayerIndex = PlayerIndex;
            obj2.MoveSpeed = MoveSpeed;
            obj2.TurnSpeed = TurnSpeed;
        }


        public void UpdateAnimation(float dt)
        {
            if (_currentAnimation != null)
            {
                _currentAnimation.Thread.AdvanceTime(dt);
            }
        }
#4
05/03/2010 (7:23 pm)
public void SetupAnimations()
        {
            //Idle Animation
            TSAnimation animationIdle = new TSAnimation();
            animationIdle.ThreadName = "ActionThread";
            animationIdle.SequenceName = "root";
            animationIdle.SequenceFilename = @"dataanimplayer_root.dsq";
            animationIdle.Name = "Idle";
            componentAnimation.AddAnimation(animationIdle);

            //Forward Animation
            TSAnimation animationForward = new TSAnimation();
            animationForward.ThreadName = "ActionThread";
            animationForward.SequenceName = "run";
            animationForward.SequenceFilename = @"dataanimplayer_forward.dsq";
            animationForward.Name = "Forward";
            componentAnimation.AddAnimation(animationForward);

            //Fall Animation
            TSAnimation animationFall = new TSAnimation();
            animationFall.ThreadName = "ActionThread";
            animationFall.SequenceName = "fall";
            animationFall.SequenceFilename = @"dataanimplayer_fall.dsq";
            animationFall.Name = "Fall";
            componentAnimation.AddAnimation(animationFall);

            //Back Animation
            TSAnimation animationBack = new TSAnimation();
            animationBack.ThreadName = "ActionThread";
            animationBack.SequenceName = "back";
            animationBack.SequenceFilename = @"dataanimplayer_back.dsq";
            animationBack.Name = "Back";
            componentAnimation.AddAnimation(animationBack);

            //Left Animation
            TSAnimation animationLeft = new TSAnimation();
            animationLeft.ThreadName = "ActionThread";
            animationLeft.SequenceName = "side";
            animationLeft.SequenceFilename = @"dataanimplayer_side.dsq";
            animationLeft.Name = "Left";
            animationLeft.TimeScale = -1.0F;
            componentAnimation.AddAnimation(animationLeft);

            //Right Animation
            TSAnimation animationRight = new TSAnimation();
            animationRight.ThreadName = "ActionThread";
            animationRight.SequenceName = "side";
            animationRight.SequenceFilename = @"dataanimplayer_side.dsq";
            animationRight.Name = "Right";
            componentAnimation.AddAnimation(animationRight);

            //Land Animation
            TSAnimation animationLand = new TSAnimation();
            animationLand.ThreadName = "ActionThread";
            animationLand.SequenceName = "land";
            animationLand.SequenceFilename = @"dataanimplayer_land.dsq";
            animationLand.Name = "Land";
            componentAnimation.AddAnimation(animationLand);

            //Dead Animation
            TSAnimation animationDead = new TSAnimation();
            animationDead.ThreadName = "ActionThread";
            animationDead.SequenceName = "dead";
            animationDead.SequenceFilename = @"dataanimplayer_diechest.dsq";
            animationDead.Name = "Dead";
            componentAnimation.AddAnimation(animationDead);
            _currentAnimation = animationIdle;
        }

        #endregion
#5
05/03/2010 (7:26 pm)
#region Private, protected, internal methods

        protected override bool _OnRegister(TorqueObject owner)
        {
            if (!base._OnRegister(owner))
                return false;

            _rigidComponent = this.Owner.Components.FindComponent<T3DRigidComponent>();

            _playerSceneComponent = this.Owner.Components.FindComponent<T3DSceneComponent>();
            _camera = TorqueObjectDatabase.Instance.FindObject<T3DCameraComponent>("CameraComponent");

            return true;
        }

        protected override void _OnUnregister()
        {
            base._OnUnregister();
            PlayerManager.Instance.GetPlayer(_playerIndex).ControlObject = null;
        }


        protected override void _RegisterInterfaces(TorqueObject owner)
        {
            base._RegisterInterfaces(owner);

            // todo: register interfaces to be accessed by other components
            // E.g.,
            // Owner.RegisterCachedInterface("float", "interface name", this, _ourInterface);
        }


        protected override void _SetupInput(InputMap inputMap, int gamepad, int keyboard)
        {

            // move
            inputMap.BindMove(gamepad, (int)XGamePadDevice.GamePadObjects.LeftThumbX, MoveMapTypes.StickAnalogHorizontal, 0);
            inputMap.BindMove(gamepad, (int)XGamePadDevice.GamePadObjects.LeftThumbY, MoveMapTypes.StickAnalogVertical, 0);

            // look
            inputMap.BindMove(gamepad, (int)XGamePadDevice.GamePadObjects.RightThumbX, MoveMapTypes.StickAnalogHorizontal, 1);
            inputMap.BindMove(gamepad, (int)XGamePadDevice.GamePadObjects.RightThumbY, MoveMapTypes.StickAnalogVertical, 1);

            //get the player object and his animation component
            TorqueObject player = TorqueObjectDatabase.Instance.FindObject<TorqueObject>("PlayerObject");

            componentAnimation = player.Components.FindComponent<T3DAnimationComponent>();
            SetupAnimations();

            ProcessList.Instance.AddAnimationCallback(Owner, this);
        }
#6
05/03/2010 (7:27 pm)
protected override void _UpdateInput(Move move, float dt)
        {
            //Game.Instance.HealthLevel = (int)(10000f * dt);

            if (move.Sticks.Count < 2)
                return;

            //
            // Move the player object within the scene
            //
            //process rotations

            float rotX = move.Sticks[1].X;
            float rotY = _invertedCamera ? -move.Sticks[0].Y : move.Sticks[0].Y;

            rotX = (float)Math.Pow(Math.Abs(rotX), Math.E) * (rotX > 0.0f ? 1.0f : -1.0f);
            rotY = (float)Math.Pow(Math.Abs(rotY), Math.E) * (rotY > 0.0f ? 1.0f : -1.0f);

            _playerAngle = (_playerAngle - (_turnSpeed * dt * rotX)) % (2.0f * (float)Math.PI);
            _playerPitchAngle = (_playerPitchAngle - (_turnSpeed * dt * rotY)) % (2.0f * (float)Math.PI);
            SceneGroup.Rotation = Quaternion.CreateFromYawPitchRoll(0.0f, 0.0f, _playerAngle);

            //process movement
            Matrix playerTranslationMatrix = _playerSceneComponent.Transform;
            Vector3 right = MatrixUtil.MatrixGetRow(0, ref playerTranslationMatrix);
            Vector3 forward = MatrixUtil.MatrixGetRow(1, ref playerTranslationMatrix);
            Vector3 vel = ((forward * move.Sticks[0].Y) + (right * move.Sticks[0].X)) * _moveSpeed;
            _rigidComponent.Velocity = vel;

            //Set camera's location behind us
            if (_camera != null)
            {
                Vector3 cameraPosition = Vector3.Zero;
                cameraPosition = Vector3.Transform(_cameraOffset, Matrix.CreateFromQuaternion(SceneGroup.Rotation));
                cameraPosition += _rigidComponent.RigidBody.Position;
                _camera.SetTransform(Matrix.CreateRotationZ(_playerAngle) * Matrix.CreateTranslation(cameraPosition), false);
            }

            if (move != null)
            {
                //side stepping
                if (move.Sticks[0].X > 0.75f)
                {
                    if (_currentAnimationPlaying != CurrentAnimationPlaying.Left)
                    {
                        _currentAnimationPlaying = CurrentAnimationPlaying.Left;
                        _currentAnimation = (TSAnimation)componentAnimation.GetAnimation("Left");
                        _currentAnimation.Play();
                    }
                    return;
                }
                else if (move.Sticks[0].X < -0.75f)
                {
                    if (_currentAnimationPlaying != CurrentAnimationPlaying.Right)
                    {
                        _currentAnimationPlaying = CurrentAnimationPlaying.Right;
                        _currentAnimation = (TSAnimation)componentAnimation.GetAnimation("Right");
                        _currentAnimation.Play();
                    }
                    return;
                }
                //forward/backward
                if (move.Sticks[0].Y > 0)
                {
                    if (_currentAnimationPlaying != CurrentAnimationPlaying.Forward)
                    {
                        _currentAnimationPlaying = CurrentAnimationPlaying.Forward;
                        _currentAnimation = (TSAnimation)componentAnimation.GetAnimation("Forward");
                        _currentAnimation.Play();
                    }
                    return;
                }
                else if (move.Sticks[0].Y < 0)
                {
                    if (_currentAnimationPlaying != CurrentAnimationPlaying.Back)
                    {
                        _currentAnimationPlaying = CurrentAnimationPlaying.Back;
                        _currentAnimation = (TSAnimation)componentAnimation.GetAnimation("Back");
                        _currentAnimation.Play();
                    }
                    return;
                }
                if (_currentAnimationPlaying != CurrentAnimationPlaying.Idle)
                {
                    _currentAnimationPlaying = CurrentAnimationPlaying.Idle;
                    _currentAnimation = (TSAnimation)componentAnimation.GetAnimation("Idle");
                    _currentAnimation.Play();
                }
            }
        }

        #endregion
#7
05/03/2010 (7:29 pm)
//======================================================
        #region Private, protected, internal fields

        //input control
        int _playerIndex = 0;

        //player motion properties
        float _turnSpeed = 2.5f;
        float _moveSpeed = 4.5f;
        float _playerAngle = 0.0f;
        float _playerPitchAngle = 0.0f;
        float _theta = 0;
        float _phi = 0;

        //camera properties
        bool _invertedCamera = false;
        Vector3 _cameraEuler = Vector3.Zero;
        T3DCameraComponent _camera;
        Vector3 _cameraOffset = new Vector3(0.0f, -5.0f, 2.250f);

        //player components
        T3DRigidComponent _rigidComponent;
        T3DAnimationComponent componentAnimation;
        T3DSceneComponent _playerSceneComponent;

        //animation properties
        TSAnimation _currentAnimation;
        CurrentAnimationPlaying _currentAnimationPlaying;

        enum CurrentAnimationPlaying
        {
            Idle,
            Forward,
            Back,
            Fall,
            Left,
            Right,
            Land,
            Dead
        }

        #endregion
    }
}

This is how I did it. I have not really gone deeper yet, but am working on a 3D project right now.

www.torquepowered.com/community/forums/viewthread/114577

This is my simple character.
#8
05/04/2010 (7:38 am)
When do you call MovementComponent3D.SetupAnimations()? In the TorqueGame.BeginRun() method? Or should it be called someplace else?
#9
05/05/2010 (9:32 am)
MovementComponent3D.SetupAnimations() when the componenet is initialized. It happens automatically. I build the char in BeginRun, right after loading the scene etc.

SceneLoader.Load(@"data\levels\levelData.txscene");
CreatePlayer();

That's it. If you look at the charcter creation code I attach the movementComponent, in the movement component::_setupInput it also sets up the animations, and connects them with the AnimationComponent created with the player.
#10
05/06/2010 (12:26 pm)
The error I get when I try this approach is that I cannot add a new component to a component that is already registered...interesting...
#11
05/07/2010 (2:01 pm)
So are you trying to add this ti something already in the scene? Is the player or whatever being loaded in the XML?

#12
05/07/2010 (6:46 pm)
I am creating this strictly in the code. It does not exist already in the scene, nor is it in the XML. I am calling the create code right after the XML scene file is loaded.
#13
05/12/2010 (7:37 pm)
Have you made any progress on this? I started messing with TX3D some this weekend, I think I have to totally redo how I do things. My approach was based on John's book, I think that taking apart and reworking the FPS example is the way to go.

I believe all the parts have to be separated out.
#14
05/13/2010 (7:19 am)
No luck. I'll take your advice and go with the FPS example too.
#15
05/20/2010 (12:08 pm)
Yeah...I think the FPS example is easier to play with. Did some modifications of it and it's pretty straight forward.