Problems with Effects

Apr 10, 2009 at 1:33 PM
Hi everyone,

I'm pretty new to Xna Animation and from what I've seen it's a very powerful tool for anyone wanting to create animations in XNA Game studio. I've had a few problems with getting my own content into the pipeline... I get this error:

Error    7    Building content threw XmlException: Root element is missing.
   at System.Xml.XmlTextReaderImpl.Throw(Exception e)
   at System.Xml.XmlTextReaderImpl.ThrowWithoutLineInfo(String res)
   at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
   at System.Xml.XmlTextReaderImpl.Read()
   at System.Xml.XmlLoader.LoadNode(Boolean skipOverWhitespace)
   at System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc)
   at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
   at System.Xml.XmlDocument.Load(XmlReader reader)
   at System.Xml.XmlDocument.Load(String filename)
   at Xclna.Xna.Animation.Content.AnimatedModelProcessor.ReadAnimationXML(NodeContent root)
   at Xclna.Xna.Animation.Content.AnimatedModelProcessor.Process(NodeContent input, ContentProcessorContext context)
   at Microsoft.Xna.Framework.Content.Pipeline.ContentProcessor`2.Microsoft.Xna.Framework.Content.Pipeline.IContentProcessor.Process(Object input, ContentProcessorContext context)
   at Microsoft.Xna.Framework.Content.Pipeline.BuildCoordinator.BuildAssetWorker(BuildItem item)
   at Microsoft.Xna.Framework.Content.Pipeline.BuildCoordinator.BuildAsset(BuildItem item)
   at Microsoft.Xna.Framework.Content.Pipeline.BuildCoordinator.RunTheBuild()
   at Microsoft.Xna.Framework.Content.Pipeline.Tasks.BuildContent.RemoteProxy.RunTheBuild(BuildCoordinatorSettings settings, TimestampCache timestampCache, ITaskItem[] sourceAssets, String[]& outputContent, String[]& rebuiltContent, String[]& intermediates, Dictionary`2& dependencyTimestamps, KeyValuePair`2[]& warnings)   


I have no idea what to do from here...
I can get my model to draw with no animation using the code from the tutorial, but as soon as I try to put the code that runs the animation along-side the XML, it dies :-( resulting with the above error. I created the model in 3D studio max 2009; Used Motionbuilder to get animation from motion capture on the model. also using VS C# 2008 with XNA GS 3.0

any help would be much appreciated,
Portico


Apr 10, 2009 at 2:07 PM
*Update*

i managed to get the project to run with the XML but it doesn't want to Animate the model... no errors... just wont animate... :-s

Any insights?
Portico
Apr 14, 2009 at 10:42 PM
Hi,

Have you checked the tutorials page?

Have you created a ModelAnimator? AnimationController? Set the Bone Poses' CurrentController properties?

You haven't given us too many details. It would be helpful if you could post some code.

YellPika
Apr 15, 2009 at 11:52 AM
Edited Apr 15, 2009 at 11:52 AM
Hi,


Yeah sorry about that it is a bit ambiguous, I’ve encountered a different problem now, it's to do with the effects:


            foreach (ModelMesh mesh in marine_model.Meshes)
            {
                foreach (ModelMeshPart part in mesh.MeshParts)
                {

                    BasicPaletteEffect oldEffect = (BasicPaletteEffect)part.Effect;                             <------------------ here it flags an error *
                    Effect newEffect = my_effect.Clone(graphics.GraphicsDevice);
                    newEffect.Parameters["BasicTexture"].SetValue(oldEffect.Texture);
                    newEffect.Parameters["View"].SetValue(view);
                    newEffect.Parameters["Projection"].SetValue(projection);
                    part.Effect = newEffect;
                    oldEffect.Dispose();
                }
            }

InvalidCastException
Unable to cast object of type 'Microsoft.Xna.Framework.Graphics.BasicEffect' to type 'Xclna.Xna.Animation.BasicPaletteEffect'.


and I can't quite understand why it's not working because when I did the dwarf tutorial it worked fine, but as soon as I get my own content in there it dies.... :-(

appreciate any insights,
Portico

Apr 16, 2009 at 1:42 AM
I've run into this problem before. I don't know why it happens, but you have to test whether it's a BasicEffect or BasicPalleteEffect, and set parameters accordingly

if (effect is BasicEffect)
    // Do BasicEffect parameters here.
if (effect is BasicPalleteEffect)
    // Do BasicPalleteEffect parameters here.

Also, if you're accessing the parameter values from Effect.Parameters, you don't really need to cast the effect to a BasicPalleteEffect.

YellPika
Apr 16, 2009 at 2:20 AM
Edited Apr 16, 2009 at 2:21 AM
Hi i also got that error that i could not cast from basic effect to basicpalleteffect so i did a if statement like this

if (part.Effect is BasicPaletteEffect)
                        {
                            BasicPaletteEffect oldEffect = (BasicPaletteEffect)part.Effect;
                            Effect newEffect = myEffect.Clone(graphics.GraphicsDevice);
                            newEffect.Parameters["World"].SetValue(World);
                            newEffect.Parameters["BasicTexture"].SetValue(oldEffect.Texture);
                            newEffect.Parameters["View"].SetValue(view);
                            newEffect.Parameters["Projection"].SetValue(myCamera.ProjectionMatrix);
                            part.Effect = newEffect.Clone(graphics.GraphicsDevice);
                            oldEffect.Dispose();
                        }
                        else if (part.Effect is BasicEffect)
                        {
                            BasicEffect oldEffect = (BasicEffect)part.Effect;
                            Effect newEffect = myEffect.Clone(graphics.GraphicsDevice);
                            newEffect.Parameters["World"].SetValue(World);
                            newEffect.Parameters["BasicTexture"].SetValue(oldEffect.Texture);
                            newEffect.Parameters["View"].SetValue(view);
                            newEffect.Parameters["Projection"].SetValue(myCamera.ProjectionMatrix);
                            part.Effect = newEffect.Clone(graphics.GraphicsDevice);
                            oldEffect.Dispose();
                        }

but they gave stoped at the base.draw() and gave me this error

"The effects on the model for a ModelAnimator were changed without calling ModelAnimator.InitializeEffectParams()."


Apr 16, 2009 at 10:19 AM
Thanks for the advice YellPika,

i'm not getting that error any more :-)
but now it flags at the end of draw() with the same error as LivingAngel....

InvaildOperationException was unhandled
The effects on the model for a ModelAnimator were changed without calling ModelAnimator.InitializeEffectParams().


i've tried calling the modelanimator.InitializeEffectParams() but it still flags....:-(

appreciate any insights,
Portico
Apr 16, 2009 at 9:54 PM
Could you post your code (all of it)? I've never seen this problem before.

YellPika
Apr 17, 2009 at 4:02 AM
public void LoadModel(string fileName)
        {
            if (!loadedModel)
            {
                base.loadModel(fileName); // this is just content.load<model> which loads into a variable called currentModel
                port = graphics.GraphicsDevice.Viewport;

                Effects myEffects = content.Load<Effect>("Model\\skinFX");

                Matrix[] transforms = new Matrix[currentModel.Bones.Count];
                currentModel.CopyAbsoluteBoneTransformsTo(transforms);

                foreach (ModelMesh mesh in currentModel.Meshes)
                {
                    Matrix World = transforms[mesh.ParentBone.Index]
                    * Matrix.CreateRotationY(MathHelper.ToRadians(modelRotation))
                    * Matrix.CreateTranslation(modelPosition)
                    * Matrix.CreateScale(scale);

                    foreach (ModelMeshPart part in mesh.MeshParts)
                    {
                        if (part.Effect is BasicPaletteEffect)
                        {
                            BasicPaletteEffect oldEffect = (BasicPaletteEffect)part.Effect;
                            Effect newEffect =myEffect.Clone(graphics.GraphicsDevice);
                            newEffect.Parameters["World"].SetValue(World);
                            newEffect.Parameters["BasicTexture"].SetValue(oldEffect.Texture);
                            newEffect.Parameters["View"].SetValue(view);
                            newEffect.Parameters["Projection"].SetValue(myCamera.ProjectionMatrix);
                            part.Effect = newEffect.Clone(graphics.GraphicsDevice);
                            oldEffect.Dispose();
                        }
                        else if (part.Effect is BasicEffect)
                        {
                            BasicEffect oldEffect = (BasicEffect)part.Effect;
                            Effect newEffect = myEffect.Clone(graphics.GraphicsDevice);
                            newEffect.Parameters["World"].SetValue(World);
                            newEffect.Parameters["BasicTexture"].SetValue(oldEffect.Texture);

                            newEffect.Parameters["View"].SetValue(view);
                            newEffect.Parameters["Projection"].SetValue(myCamera.ProjectionMatrix);
                            part.Effect = newEffect.Clone(graphics.GraphicsDevice);
                            oldEffect.Dispose();
                        }
                    }
                }

                // this is the default for animation control


                foreach (ModelMesh mesh in currentModel.Meshes)
                {
                    foreach (Effect effect in mesh.Effects)
                    {
                        if (effect is BasicEffect)
                        {
                            BasicEffect basic = (BasicEffect)effect;
                            basic.View = view;
                            basic.Projection = myCamera.ProjectionMatrix;
                            break;
                        }
                        if (effect is BasicPaletteEffect)
                        {
                            BasicPaletteEffect palette = (BasicPaletteEffect)effect;
                            palette.View = view;
                            palette.Projection = myCamera.ProjectionMatrix;
                            // enable some lighting
                            palette.EnableDefaultLighting();
                            palette.DirectionalLight0.Direction = new Vector3(0, 0, 1);
                            break;
                        }
                        else
                        {
                            effect.Parameters["View"].SetValue(myCamera.ViewMatrix);
                            effect.Parameters["AIntensity"].SetValue(0.4f);
                            effect.Parameters["DIntensity"].SetValue(1.0f);
                            effect.Parameters["SColor"].SetValue(new Vector4(1, 1, 1, 1));
                            effect.Parameters["SpecPower"].SetValue(5f);
                            effect.Parameters["LightDir"].SetValue(lightDirection);
                            effect.Parameters["EyePos"].SetValue(myCamera.Position);
                        }
                    }
                }
                animatedModel = new ModelAnimator(theGame, currentModel);
                theController.Add("idle0", new AnimationController(theGame, animatedModel.Animations["idle0"]));
                animationBool.Add("idle0", true);//this is just my own fuunction nothing much
                RunController(animatedModel, theController["idle0"]);
                rotation = Matrix.CreateFromAxisAngle(Vector3.Up, 1.5f);

                if (ID == 0) animatedModel.Visible = true;
            }
            Console.WriteLine("Complete Load");
        }
Apr 17, 2009 at 12:03 PM
my code isnt as complicated as LivingAngel; i'm just trying to load one of my models, so heres my code:

 protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            Viewport port = graphics.GraphicsDevice.Viewport;
            view = Matrix.CreateLookAt(
                new Vector3(0, 400, 450),new Vector3(0,300,0), Vector3.Up);
            Matrix projection = Matrix.CreatePerspectiveFieldOfView(
                MathHelper.PiOver4, (float)port.Width / port.Height, .1f, 100000f);

            marine_model = Content.Load<Model>("Models\\Main_base");
            

            //effects

            my_effect = Content.Load<Effect>("skinFX");

            foreach (ModelMesh mesh in marine_model.Meshes)
            {
                foreach (ModelMeshPart part in mesh.MeshParts)
                {
                    if(part.Effect is BasicPaletteEffect)
                    {
                        BasicPaletteEffect oldEffect = (BasicPaletteEffect)part.Effect;
                        Effect newEffect = my_effect.Clone(graphics.GraphicsDevice);
                        newEffect.Parameters["BasicTexture"].SetValue(oldEffect.Texture);
                        newEffect.Parameters["View"].SetValue(view);
                        newEffect.Parameters["Projection"].SetValue(projection);
                        part.Effect = newEffect;
                        oldEffect.Dispose();
                        
                    }
                    else if(part.Effect is BasicEffect)
                    {
                        BasicEffect oldEffect = (BasicEffect)part.Effect;
                        Effect newEffect = my_effect.Clone(graphics.GraphicsDevice);
                        newEffect.Parameters["BasicTexture"].SetValue(oldEffect.Texture);
                        newEffect.Parameters["View"].SetValue(view);
                        newEffect.Parameters["Projection"].SetValue(projection);
                        part.Effect = newEffect;
                        oldEffect.Dispose();
                    }
                }
            }



            foreach (ModelMesh mesh in marine_model.Meshes)
            {
                foreach (Effect effect in mesh.Effects)
                {
                    if (effect is BasicEffect)
                    {
                        BasicEffect basic = (BasicEffect)effect;
                        basic.View = view;
                        basic.Projection = projection;
                    }
                    else if (effect is BasicPaletteEffect)
                    {
                        BasicPaletteEffect palette = (BasicPaletteEffect)effect;
                        palette.View = view;
                        palette.Projection = projection;

                        // enable some lighting
                        palette.EnableDefaultLighting();
                        palette.DirectionalLight0.Direction = new Vector3(0, 0, 1);
                    }
                }

            }

            marine_animator = new ModelAnimator(this, marine_model);

           // idle = new AnimationController(this, marine_animator.Animations["Idle"]);
            //Run = new AnimationController(this, marine_animator.Animations["Run"]);
           // Aim = new AnimationController(this, marine_animator.Animations["Aim"]);
            //Shoot = new AnimationController(this, marine_animator.Animations["Shoot"]);

           // RunController(marine_animator, Aim);

        }

you don't think it could be the model it's self that causing the problem?

appreciate any insights,
Portico

Apr 17, 2009 at 11:38 PM
OK, there are a couple things here I don't understand...
1. I don't see why you are looping over the model's effects twice - the effect has already been set, and there is no reason for any of the effects to be a BasicPalleteEffect or BasicEffect.
2. (This is specifically for Portico) What's with the extremely large range in depth for the perspective matrix (.1f, 100000)? This is not really related to the animation, but it could cause a lot of Z-Fighting.

Anyway, I don't know if this makes a difference, but I usually initialize the ModelAnimator before I set the effects.

Lastly, I think you're supposed to set the effects in the ModelAnimator, not the actual model itself (ModelAnimator.Effects).

Hope this helps.

YellPika
Apr 18, 2009 at 12:33 AM
By the way, I have a (slightly) modified version of the library incorporated into my own project. It fixes that problem that forces you to load you're own effect. Unless you're purposefully trying to load a custom effect, I recommend you use my version.
Apr 18, 2009 at 11:45 AM
Edited Apr 18, 2009 at 1:45 PM
Thanks for that YellPika,

i was just following the examples on the tutorial page thats probably why its in there twice (because i got a bit confused :-S), the high number  in the perspective matrix is for the far clipping plane, i set it quite large just incase, i suppose it could be a bit smaller.....
i can get a basic model drawn now :-) but as soon as i try to bring in something that has an animation on it it complains about:

InvalidOperationException was unhandled
Both a valid vertex shader and pixel shader (or valid effect) must be set on the device before any draw operations may be performed.


if you have a version of the library that can bypass this problem i would love to have the chance to use it. could you post a link or something? and is it the same principles as XNA animation? or do i have to do something different?

Thanks again,
Portico
Apr 18, 2009 at 4:00 PM
The library is located at http://www.codeplex.com/applenet

Just download the installer, run it, open up your project, and add a reference to APPLENET.RenderXNA (it should show up under the .NET tab).
The namespaces are a little different. Just replace the main namespace(Xclna.Xna) with APPLENET.RenderXNA.Animation.

If your using the XBOX, you might run into some errors (I don't have one, so I don't know), but for Windows, it should run fine.

Also, check out the samples section. There's an Animation Sample, which shows the bare minumum for doing animation.

YellPika
Apr 18, 2009 at 6:33 PM
Thanks for that YellPika, i don't seem to be getting that error any more when i try to put an animated model in...:-)
 but for some reason it appears all black which is strange... would you know how to get around this problem?
and is your version similar this Xna animtion library in that you can uses XML to spilt the animations?

Thanks alot for all your help,
Portico


Apr 19, 2009 at 1:13 AM
'...but for some reason it appears all black and strange...'

I've had this happen before. I don't know why this happens, but you should first try calling EnableDefaultLighting() for each effect. If that doesn't work, set the Diffuse parameter to Vector3.One.

Yes, it does use XML to split animations.

YellPika
Apr 20, 2009 at 7:27 AM
for me i am actually trying to load my own custom effects into the game.

in fact the funny thing is that when i load in the dwarf model that comes with the demo it works perfectly fine
But when i use my own models the error will appear.

I will try the lastest library later on

And thanks YellPika for all the help.