Change animation of Animated model

Feb 27, 2010 at 2:50 PM

Hello,

 

My problem is :

I have put an animatedmodel in my game. It compile, my model animate himself !! But I can only move him with Component class.

I can rotate him too, but I don't know how to change his animation in game. I can only put an initial animation in ox editor.

Do you know how to proceed?

 

thank you for all!!!

 

PPS: sorry for my bad english =)

Feb 27, 2010 at 7:12 PM

Component.AnimationController.CrossFade(
                    Component.SkinnedModel.AnimationClips.Values[2], // <- Replace 2 with whatever clip you want
                    TimeSpan.FromSeconds(0.3f)); // <- Replace 0.3 with whatever fade time you want

Coordinator
Mar 1, 2010 at 1:20 AM
Edited Mar 1, 2010 at 1:22 AM

More simply, if you just want to set the animation and let it run, use Component.AnimationController.PlayClip(Component.SkinnedModel.AnimationClips["clipName"]).

The interface sucks, but that's XNAnimation's fault :D

Cheers!

 

Mar 1, 2010 at 1:37 PM

Hello!!!

 

Thanks for reply !!!

 

Visual Studio said me that he doesn't found the namespace underlined below :

 

Component.AnimationController.PlayClip(Component.SkinnedModel.AnimationClips["clipName"]).

 

I think a using is missing. Do you know wich using is missing??? =)

Coordinator
Mar 1, 2010 at 1:47 PM

Did you read the 'Scripting a SceneComponent' documentation? It tells you how to specify the correct component type for the script. It looks like you skipped that step.

Cheers!

- bryan

Mar 1, 2010 at 1:48 PM

yes I had read the doc but I haven't found any informations about control of animatedmodel "in game" =)

Editor
Mar 1, 2010 at 11:22 PM
Edited Mar 1, 2010 at 11:39 PM

Its not that you control an animated model as such, its just incidental that the model you are using is animated, the important thing here is that you are controlling a scene component.  there is currently no available documentation for this. what bryan means here i think is that your default script class header

   public class OxScript1
        // TODO: If your script needs to talk with its component through a more specific type
        // than OxComponent, change ComponentsScript's generic type specifier.
        : ComponentScript<OxComponent>

 

should read something like

   public class OxScript1
        // TODO: If your script needs to talk with its component through a more specific type
        // than OxComponent, change ComponentsScript's generic type specifier.
        : ComponentScript<AnimatedModel>

 

after which you can use the functions that are specific to an animated model. i haven't tried doing this yet, got more important logic to do. but this seems to be the way to do it. you must also remember to include the

#using Ox.Scene.Component;

just to make the AnimatedModel Type Available.

 

cheers < edit : damnit ive started writing cheers.........

bubzy

Coordinator
Mar 2, 2010 at 2:20 AM

Thanks bubzy, that's what I meant to say ;)

cheers!

hehe...

Mar 6, 2010 at 1:27 PM

Thanks a lot dudes, I will try it !!!

Mar 6, 2010 at 2:17 PM

it works thx!!!

May 11, 2010 at 8:01 PM
Edited May 11, 2010 at 8:06 PM
Ive been trying to do what was discussed above, using a script. Ive linked the script to my model in the scene loader, however when I run the program i get a "Cannot find script type" exception. Any thoughts on what's gone wrong? Also quick question, I tried posting the script code here, but there's no option to edit the appearance of the code.
Editor
May 11, 2010 at 9:01 PM

there is a little button on the post window, next to the "html" button that allows you to paste code into it and change the language.

as to your problem, without seeing the code, i could only guess that you have a case issue. as the scene editor's case will have to be consistent with the case in the script.

post some code up. if you cant format it, its no problem, we can still read it :)

bubzy.

May 11, 2010 at 9:10 PM
Here's the script file using System.Collections.Generic; using JigLibX.Collision; using JigLibX.Geometry; using JigLibX.Physics; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; using Ox.Engine; using Ox.Engine.CameraNamespace; using Ox.Engine.Component; using Ox.Engine.MathNamespace; using Ox.Engine.Utility; using Ox.Scene.Component; namespace OxSceneLoader { /// <summary> /// Implements a script that controls a component. /// </summary> public class MyAnimatedModel // TODO: If your script needs to talk with its component through a more specific type // than OxComponent, change ComponentsScript's generic type specifier. : ComponentScript<AnimatedModel> { public MyAnimatedModel(OxEngine engine, Transfer<OxComponent> component) : base(engine, component) { } protected override void Dispose(bool disposing) { if (disposing) { // TODO: Put your script's disposal code here. } base.Dispose(disposing); } protected override void UpdateHook(GameTime gameTime) { base.UpdateHook(gameTime); Component.AnimationController.PlayClip(Component.SkinnedModel.AnimationClips["Stance"]); } } } And the Gamescript file using Microsoft.Xna.Framework; using Ox.Engine; using Ox.Engine.Component; using Ox.Engine.Utility; using Ox.Engine.Primitive; using Ox.Scene; using Ox.Scene.Component; using Ox.Scene.LightNamespace; namespace OxSceneLoader { /// <summary> /// GameScript implements your Ox Game Engine game. /// </summary> public class GameScript : ComponentScript<OxComponent> { private AnimatedModel myModel; public GameScript(OxEngine engine, Transfer<OxComponent> component) : base(engine, component) { // create a domain to manage the current level Engine.CreateDomain("CurrentLevel"); // load the level Engine.LoadDocument("MyScene.xml", SceneConfiguration.SceneDocumentType, DomainName); //load my own model myModel = new AnimatedModel(Engine, DomainName, true, "ox/models/FightingCharMultipleAnim", new BoxPrimitive()); myModel.Parent = Engine.Root; myModel.PositionWorld = new Vector3(100,100,100); } protected override void Dispose(bool disposing) { if (disposing) { // unload the current level Engine.DestroyDomain("CurrentLevel"); } base.Dispose(disposing); } protected override void UpdateHook(GameTime gameTime) { base.UpdateHook(gameTime); Engine.Camera.SetTransformByLookTarget(new Vector3(140, 140, -70), Vector3.Up, myModel.Position); } } } Apologies for the formatting, but I dont see the formatting button
Editor
May 12, 2010 at 6:01 AM

looks ok. any chance of posting the MyScene.xml file up too? (it would be nice if you could upload it to a site or something, as the continuous wall of text makes me sad :P)

here's your code using the formatter on the site. (yes i had to press enter on each new line)

-bubzy.

using System.Collections.Generic;
using JigLibX.Collision;
using JigLibX.Geometry; 
using JigLibX.Physics; 
using Microsoft.Xna.Framework; 
using Microsoft.Xna.Framework.Input; 
using Ox.Engine; 
using Ox.Engine.CameraNamespace; 
using Ox.Engine.Component; 
using Ox.Engine.MathNamespace;
using Ox.Engine.Utility; 
using Ox.Scene.Component;

namespace OxSceneLoader 
{
 /// <summary> /// Implements a script that controls a component. /// </summary> 

public class MyAnimatedModel : ComponentScript<AnimatedModel> { 

public MyAnimatedModel(OxEngine engine, Transfer<OxComponent> component) : base(engine, component)
{
} 
protected override void Dispose(bool disposing)
 { if (disposing) {
 // TODO: Put your script's disposal code here.
 } base.Dispose(disposing);
 }
 protected override void UpdateHook(GameTime gameTime) 
{ 
 base.UpdateHook(gameTime);
 Component.AnimationController.PlayClip(Component.SkinnedModel.AnimationClips["Stance"]); 
}
 
}
} 

// GameScript.CS
using Microsoft.Xna.Framework; 
using Ox.Engine;
using Ox.Engine.Component; 
using Ox.Engine.Utility;
using Ox.Engine.Primitive; 
using Ox.Scene; 
using Ox.Scene.Component; 
using Ox.Scene.LightNamespace; 

namespace OxSceneLoader 
{ 
    /// <summary> /// GameScript implements your Ox Game Engine game. /// </summary> 
public class GameScript : ComponentScript<OxComponent> 
{ 

private AnimatedModel myModel; 

public GameScript(OxEngine engine, Transfer<OxComponent> component) : base(engine, component) 
{ 
// create a domain to manage the current level 
Engine.CreateDomain("CurrentLevel"); 
// load the level 
Engine.LoadDocument("MyScene.xml", SceneConfiguration.SceneDocumentType, DomainName); 
//load my own model 
myModel = new AnimatedModel(Engine, DomainName, true, "ox/models/FightingCharMultipleAnim", new BoxPrimitive()); 
myModel.Parent = Engine.Root; 
myModel.PositionWorld = new Vector3(100,100,100); } 
protected override void Dispose(bool disposing) 
{ 
if (disposing) { 
// unload the current level 
Engine.DestroyDomain("CurrentLevel"); 
} 
base.Dispose(disposing); 
} 
protected override void UpdateHook(GameTime gameTime) 
{ 
base.UpdateHook(gameTime); 
Engine.Camera.SetTransformByLookTarget(new Vector3(140, 140, -70), Vector3.Up, myModel.Position); 
} 
} 
} 
May 13, 2010 at 2:24 AM
Here's the xml code. The formatting option are there now when I hit reply, odd.

<?xml version="1.0" encoding="utf-8" ?> - <SceneDocumentToken xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> - <Components> - <ComponentToken xsi:type="AmbientLightToken"> <ParentGuid xsi:nil="true" /> <Guid>032b647f-63eb-4954-a2b7-4f105955b66d</Guid> <Name>AmbientLight:032b647f-63eb-4954-a2b7-4f105955b66d</Name> - <Position> <X>0</X> <Y>0</Y> <Z>0</Z> </Position> - <Scale> <X>1</X> <Y>1</Y> <Z>1</Z> </Scale> - <Orientation> <X>0</X> <Y>0</Y> <Z>0</Z> </Orientation> <OrientationPlayTime xsi:nil="true" /> - <Box> - <Center> <X>0</X> <Y>0</Y> <Z>0</Z> </Center> - <Extent> <X>0.5</X> <Y>0.5</Y> <Z>0.5</Z> </Extent> </Box> - <Color> <R>128</R> <G>128</G> <B>128</B> <A>255</A> <PackedValue>4286611584</PackedValue> </Color> </ComponentToken> - <ComponentToken xsi:type="PointLightToken"> <ParentGuid xsi:nil="true" /> <Guid>0f4798db-db56-4373-8f3f-13f715f73fb2</Guid> <Name>PointLight:0f4798db-db56-4373-8f3f-13f715f73fb2</Name> - <Position> <X>17</X> <Y>184</Y> <Z>-17</Z> </Position> - <Scale> <X>1</X> <Y>1</Y> <Z>1</Z> </Scale> - <Orientation> <X>0</X> <Y>0</Y> <Z>0</Z> </Orientation> <OrientationPlayTime xsi:nil="true" /> - <Box> - <Center> <X>0</X> <Y>0</Y> <Z>0</Z> </Center> - <Extent> <X>0.5</X> <Y>0.5</Y> <Z>0.5</Z> </Extent> </Box> - <DiffuseColor> <R>128</R> <G>128</G> <B>128</B> <A>255</A> <PackedValue>4286611584</PackedValue> </DiffuseColor> - <SpecularColor> <R>128</R> <G>128</G> <B>128</B> <A>255</A> <PackedValue>4286611584</PackedValue> </SpecularColor> </ComponentToken> - <ComponentToken xsi:type="AnimatedModelToken"> <ParentGuid xsi:nil="true" /> <Guid>b120ab43-1f72-4a35-afb2-aa6d849458a9</Guid> <Name>AnimatedModel:b120ab43-1f72-4a35-afb2-aa6d849458a9</Name> <ScriptClass>MyAnimatedModel.cs</ScriptClass> - <Position> <X>29</X> <Y>179</Y> <Z>-37</Z> </Position> - <Scale> <X>1</X> <Y>1</Y> <Z>1</Z> </Scale> - <Orientation> <X>90</X> <Y>0</Y> <Z>0</Z> </Orientation> <OrientationPlayTime xsi:nil="true" /> - <Box> - <Center> <X>0</X> <Y>0</Y> <Z>0</Z> </Center> - <Extent> <X>0.5</X> <Y>0.5</Y> <Z>0.5</Z> </Extent> </Box> - <DiffuseColor> <R>255</R> <G>255</G> <B>255</B> <A>255</A> <PackedValue>4294967295</PackedValue> </DiffuseColor> - <SpecularColor> <R>128</R> <G>128</G> <B>128</B> <A>255</A> <PackedValue>4286611584</PackedValue> </SpecularColor> <EffectFileName /> <SkinnedModelFileName>Ox\Models\FightingCharMultipleAnim</SkinnedModelFileName> - <EmissiveColor> <R>0</R> <G>0</G> <B>0</B> <A>0</A> <PackedValue>0</PackedValue> </EmissiveColor> </ComponentToken> </Components> <Groups /> - <CameraPosition> <X>-82.82293</X> <Y>174.730652</Y> <Z>-9.731873</Z> </CameraPosition> - <CameraOrientation> <X>0</X> <Y>-70.90135</Y> <Z>0</Z> </CameraOrientation> <PositionSnap>1</PositionSnap> <ScaleSnap>0.125</ScaleSnap> <OrientationSnap>15</OrientationSnap> <CreationDepth>100</CreationDepth> </SceneDocumentToken>

 

Editor
May 13, 2010 at 6:18 AM
Edited May 13, 2010 at 6:26 AM

change the class name in scene editor to OxSceneLoader.MyAnimatedModel

try that

bubzy.

May 13, 2010 at 12:46 PM

Thanks Bubzy, the script is now being found, although the animation isn't running. The script class is unchanged from what you see above. I looked at the .fbx file, and the animation name is definitely right.
Shouldn't the animation play as soon as it starts up?

May 16, 2010 at 9:10 PM
Edited May 16, 2010 at 11:15 PM

I've messed around with the camera, I'm pretty sure the model is using the script, but it's coordinates are out of view. How do I set the camera to look at a model whose position is contained in my scene .xml file?

Editor
May 17, 2010 at 6:01 AM
Edited May 17, 2010 at 6:02 AM

you can use something like

 

AnimatedModel lookAtMe = Engine.GetScript<AnimatedModel>("YourScriptedModelHere"); // you will have to name the model in the script editor :D this is case sensitive

Engine.Camera.SetViewByLookTarget(cameraposition, cameraupvector, lookAtMe.Position);

 

obviously replace cameraposition and cameraupvector with your variables.

its better to call the getscript inside an override of DocumentLoadedHook() it avoids any errors with you calling the getscript before Ox has acutally loaded that particular script.

 

-bubzy :P

May 17, 2010 at 1:08 PM

This is what I placed in the Gamescript file,


  protected override void DocumentLoadedHook()
{
AnimatedModel lookAtMe = Engine.GetScript<AnimatedModel>("myModel");
Engine.Camera.SetTransformByLookTarget(new Vector3(140, 140, -70), Vector3.Up, lookAtMe.Position);
base.DocumentLoadedHook();
}

It returns the exception, "Cannot cast item myModel to type AnimatedModel."

I renamed the model to 'myModel' in the scene editor, but it still has the type, AnimatedModel.

Editor
May 17, 2010 at 4:58 PM

possibly a little error by me.

you need to make sure that "myModel" is an "AnimatedModel" object, if its not (StandardModel/PointLight etc.....) then you will have to change the code to

Engine.GetScript<ObjectTypeHere>("MyModel");

and bear in mind that documentloadedhook is only loaded once, so if you want to use this as a look target more than once, you are going to have to define lookAtMe in the programs variable declarations and call getscript in the normal manner.

 

hope this helps....

bubzy.

May 17, 2010 at 5:18 PM

The model is and "Animated Model" object. When I open the scene xml file, it says type  "<ComponentToken xsi:type="AnimatedModelToken">", so for good measure, I tried using both types in declaring the lookAtMe varable. No joy there. I removed the model in the scene editor, then added a new version,  naming it myModel, and checking that the type is AnimatedModel. I'm a little confused as to why it's trying to cast an item of the same type.

Editor
May 17, 2010 at 9:12 PM

zip your project up and send it over mate. rich@greymatterscomic.com ill see if i can see what it is, i could theorise all day :D

May 17, 2010 at 9:43 PM
Thanks, i've sent it
Editor
May 17, 2010 at 10:24 PM

bit rusty on this :D made a load of mistakes with my previous advice.

ok what you need to do is make a "getter" in your script.

so in MyAnimatedModel.cs add the following function

public Vector3 myPosition
{ 
get { return Component.Position;}
}

and in your DocumentLoadedHook() in GameScript.cs use this :

	   MyAnimatedModel lookAtMe = Engine.GetScript<MyAnimatedModel>("myModel");
            Engine.Camera.SetTransformByLookTarget(new Vector3(140, 140, -70), Vector3.Up, lookAtMe.myPosition);

if you need explanation of how this works let me know :D

-bubzy

p.s : sorry for the wild goose chase

May 17, 2010 at 11:27 PM
The camera is focusing on the model, but it doesn't behave predictably. When I try to copy the position and orientation from the scene editor, I get weird results. What coordinate system does the scene editor use? I get a reasonable result using Vector3.Backward, and experimenting with the orientation of my model. The model itself was made in Bender, with a custom exporter, which may explain the orientation quirks.
Editor
May 18, 2010 at 6:12 AM

you're probably better off creating a rotation matrix to control your camera, than using the vector3.up etc. ive always had some dubious results using vector3.up/down/forward.......

also try creating a terrain to give yourself a bit of perspective. remember that in the program you have written, the camera is looking at the model. so its orientation and suchlike is set by the engine.

-bubzy

May 18, 2010 at 5:38 PM
Edited May 18, 2010 at 5:43 PM
Ive been trying to use code from a XNAnimation project to change the animation during runtime. The first animation is playing ok, but it doesn't switch. I'd also like to combine this with code to move the model , to give the appearance of walking. I'm just not sure how to implement this with the code Ive been using from this thread. Should I implement these function in the main Gamescript or MyAnimatedModel script attached to the model? Also how do i alter the position of the model, can I add a set Component.Position to complement the getter in the myPosition method you gave me? (Once again, the options to format code have disappeared on me. So i removed what I posted. Has anyone else had this trouble? It seems completely intermittent)
Editor
May 18, 2010 at 6:26 PM

yeah you can make a setter, inside the same function add

set { Component.Position = value; }
May 18, 2010 at 6:45 PM
Edited May 18, 2010 at 6:48 PM

I added the setter, and tried modifying it with 

protected override void DocumentLoadedHook()
        {
            MyAnimatedModel lookAtMe = Engine.GetScript<MyAnimatedModel>("myModel");
            Engine.Camera.SetTransformByLookTarget(new Vector3(0,-200,0), Vector3.Backward, lookAtMe.myPosition);
           
            if(keyboardState.IsKeyDown(Keys.A))
            {
                lookAtMe.myPosition += new Vector3(10, 10, 10);                
            }
            lastKeyboardState = keyboardState;
 
            base.DocumentLoadedHook();
        }
 

no effect. Is this the right approach?

Editor
May 18, 2010 at 7:21 PM
Edited May 18, 2010 at 7:24 PM

 

using Microsoft.Xna.Framework;
using Ox.Engine;
using Ox.Engine.Component;
using Ox.Engine.Utility;
using Ox.Engine.Primitive;
using Ox.Scene;
using Ox.Scene.Component;
using Ox.Scene.LightNamespace;

namespace OxSceneLoader
{
    /// <summary>
    /// GameScript implements your Ox Game Engine game.
    /// </summary>
    public class GameScript : ComponentScript<OxComponent>
    {

        float move; // this is just for test purposes
        MyAnimatedModel lookAtMe; // this one too.
        public GameScript(OxEngine engine, Transfer<OxComponent> component)
            : base(engine, component)
        {
            // create a domain to manage the current level
            Engine.CreateDomain("CurrentLevel");
            // load the level
            Engine.LoadDocument("MyScene.xml", SceneConfiguration.SceneDocumentType, DomainName);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                // unload the current level
                Engine.DestroyDomain("CurrentLevel");
            }
            base.Dispose(disposing);
        }

        protected override void DocumentLoadedHook()
        {
            lookAtMe = Engine.GetScript<MyAnimatedModel>("myModel");
            Engine.Camera.SetTransformByLookTarget(new Vector3(140, 140, -70), Vector3.Up, lookAtMe.position);
            base.DocumentLoadedHook();
            
        }
        protected override void UpdateHook(GameTime gameTime)
        {
            move += 0.1f;
            lookAtMe.position = new Vector3(lookAtMe.position.X, lookAtMe.position.Y, move);
                
            base.UpdateHook(gameTime);            
        }
    }
}

// if "bobthebox" was in this code before i edited it, please excuse that :D was an earlier test.

as you can see the changing parameter is within the UpdateHook() method and not in the DocumentLoadedHook() method. this is because DocumentLoadedHook is only called once, while UpdateHook is called every time the program updates(of course :D)

-bubzy

May 18, 2010 at 8:25 PM
Thanks Bubzy, I added keyboard controls, it works fine. Even got the camera to keep tracking the model. I have an Ox cube there too, so I can see the movement. I even managed to get the camera to track with the model as it moves :D That's great work for today, You're a star>
Editor
May 18, 2010 at 9:14 PM

anytime. thats what the forums are for.

glad you're enjoying using the engine :)

-bubzy

May 27, 2010 at 6:48 PM
How do I change the orientation of the model? I created animations to turn left and right, but I also need to change the model's facing in code so it stays facing the direction I want after the animation ends.
Editor
May 30, 2010 at 8:07 AM

in your script file for MyAnimatedModel you need to add a getter/setter

 

public Matrix orientation
        {
            get { return Component.Orientation; }
            set { Component.Orientation = value; }
        }

 

 

:) bubzy

May 30, 2010 at 2:28 PM

I tried that getter/setter before, but I wasn't sure what kind of values to use in the orientation matrix. How do I construct it?

Editor
May 30, 2010 at 5:08 PM

its just a matrix, that conforms to the same values as anything in a 3d world. it has x,y, and z values to make a model turn you would just rotate it along one of these axes.

so something like

Matrix myAnimatedModelMatrix = Matrix.CreateRotationY(90);

myAnimatedModel.orientation = myAnimatedModelMatrix;

would rotate your model by 90 degrees.

-bubzy

May 30, 2010 at 6:05 PM

Thanks, I got it working. Although the blender rotation issues required me to take an unusual solution.

  Matrix leftMatrix = Matrix.CreateRotationZ(0);
  Matrix rightMatrix = Matrix.CreateRotationZ(3);

if (keyboardState.IsKeyDown(Keys.A))
            {
               lookAtMe.myOrientation = leftMatrix;
               //lookatMe is the model
                move += 0.5f;                
                Component.AnimationController.PlayClip(Component.SkinnedModel.AnimationClips["Walk"]);
            }

            else if (keyboardState.IsKeyDown(Keys.D))
            {               
               lookAtMe.myOrientation = rightMatrix;
               move -= 0.5f;
               Component.AnimationController.PlayClip(Component.SkinnedModel.AnimationClips["Walk"]);                   
            }


As you can see, 0 and 3 seem like odd values. My model is rotated 90 around the Z axis before the game starts, in order to compensate for the rotation it has from Blender.
I got 3 through trial and error, but it looks O.K. for the time being.

Editor
May 31, 2010 at 6:52 AM

great, glad it works, as an aside however i really would suggest sorting out your axes. this will save you a lot of brain crushing trouble in the future.

but of course, if you like the challenge you can leave it as it is. (the normal axis to move a character through for left/right turning is the 'y' axis)

-bubzy