Model visible twice

Topics: User Forum
Apr 11, 2008 at 2:05 PM
Hi
Im using the dll's that came with the viking tutorial. Im trying to create my own game, with a free-flying camera. Im able to export a .x file with kw xporter from autodesk, and view it in my scene. I have however a problem, because my model is displayed twice. One unscaled , unpositioned and unrotated and one scaled, positioned and rotated (both animated). If I changes position the first model is not affected. However, it is if im changing animation.

I have build two classes to represent the animation, ModelObject only contains position, scale and rotation. My Animated Class looks like this:
using System;
using System.Collections.Generic;
using System.Text;


public class AnimatedModelObject : ModelObject
{
private ModelAnimator _animator;
private AnimationController _aniController = null;
private Model _model;
private Game _game;

public AnimatedModelObject(Game g, Model m, String startAnimation)
: base(m)
{
_model = m;
_game = g;

animator = new ModelAnimator(game, _model);
aniController = new AnimationController(game, _animator.AnimationsstartAnimation);
}
public void SetAnimation(String animationName)
{
aniController = new AnimationController(game, _animator.AnimationsanimationName);
}

//Called everytime the games does "draw"
public override void Draw(Matrix viewMatrix, Matrix projectionMatrix)
{
Matrix worldMatrix = Matrix.CreateScale(base.Scale) * Matrix.CreateFromYawPitchRoll(base.Rotation.Y, base.Rotation.X, base.Rotation.Z) * Matrix.CreateTranslation(base.Position);

foreach (ModelMesh mesh in _animator.Model.Meshes)
{
foreach (Effect effect in mesh.Effects)
{
if (effect is BasicEffect)
{
BasicEffect basic = (BasicEffect)effect;

basic.World = worldMatrix;
basic.View = viewMatrix;

basic.Projection = projectionMatrix;
}
else if (effect is BasicPaletteEffect)
{
BasicPaletteEffect palette = (BasicPaletteEffect)effect;
palette.World = worldMatrix;
palette.View = viewMatrix;

palette.Projection = projectionMatrix;
}
}
mesh.Draw();
}

Run();

}
private void Run()
{
foreach (BonePose p in _animator.BonePoses)
{
p.CurrentController = _aniController;
p.CurrentBlendController = null;
}
}
}


Im using it as:

AnimatedModelObject simpleModel;
void LoadContent()
{
simpleModel = new AnimatedModelObject(
this,
Content.Load<Model>("Models/TwoLeg"),
"Idle");
}
void Draw(GameTime gameTime)
{
simpleGnome.Draw(viewMatrix,pMatrix) ; //The matrices are generated by the game

}

It works fine with my camera and the position, scaling and rotation of the model, but do you know why I have two models?

Apr 11, 2008 at 6:34 PM
I am having a little trouble following the intent of this code due to the fact that there is signifigant parts of the logic missing, but heres a few questions for you.

"simpleGnome" isnt declared here- what is this exactly? Is it related to this program at all?

When exactly is "anicontroller" set? You seem to have two different functions that set this, though neither is called here- shouldnt you have a separate animation controller for each animation like in the tutorial?

This is just a wild stab in the dark here, but one thing you might be an issue is that this package will automatically draw the model unless you stop it from doing so. If simpleGnome is supposed to be the character then you dont want to call a draw function on it unless you first stop the library from doing so. That might potentially create two copies like you are seeing.
Apr 11, 2008 at 10:01 PM
Hi, Sorry about "simpleGnome", that should be "simpleModel" which is an instance of the AnimatedModelObject class.

The forum has done some strange things to the text, so the places that only reads "anicontroller" should be "_anicontroller". The same thing with "animator" which should be "_animator".

The model is needed to be able to move freely (together with the free-moving camera), and its projection therefore needs to be updated constantly. Therefore I would like it to be drawn together with the Draw method of the game. How do i tell the package, that it should not draw the model automatically?

I have tried:
http://www.codeplex.com/animationcomponents/Wiki/View.aspx?title=Drawing%20Code&referringTitle=Creating%20a%20ModelAnimator
where I added the following lines to the constructor, after the _animator object had been created.

_animator.Visibility = false; //in the constructor of the class
_animator.Enabled = false;

here after, my draw method looked like this:

public void Draw(Matrix viewMatrix, Matrix projectionMatrix, GameTime gameTime)
{
Matrix worldMatrix = Matrix.CreateScale(base.Scale) * Matrix.CreateFromYawPitchRoll(base.Rotation.Y, base.Rotation.X, base.Rotation.Z) * Matrix.CreateTranslation(base.Position);

foreach (ModelMesh mesh in _animator.Model.Meshes)
{
foreach (Effect effect in mesh.Effects)
{
if (effect is BasicEffect)
{
BasicEffect basic = (BasicEffect)effect;

basic.World = worldMatrix;
basic.View = viewMatrix;

basic.Projection = projectionMatrix;
}
else if (effect is BasicPaletteEffect)
{
BasicPaletteEffect palette = (BasicPaletteEffect)effect;
palette.World = worldMatrix;
palette.View = viewMatrix;

palette.Projection = projectionMatrix;
}
}
mesh.Draw();
}

_animator.Draw(gameTime);
Run();

}

private void Run()
{
foreach (BonePose p in _animator.BonePoses)
{
p.CurrentController = _aniController;
p.CurrentBlendController = null;
}
}

but without success... if i did not call Run() my animation didnt move, and, its elements was scattered around the scene. Ive tried to remove mesh.draw(), and to replace mesh.Draw() with _animator.Draw(...) but with no success...

Hereafter I found:
http://www.codeplex.com/animationcomponents/Thread/View.aspx?ThreadId=8881 (reply Apr 6 2007 at 8:23 AM)

Which left me with a new constructor :
public AnimatedModelObject(Game g, Model m, String startAnimation)
: base(m)
{
_model = m;
_game = g;

_animator = new ModelAnimator(_game, _model);
_aniController = new AnimationController(_game, _animator.Animations[startAnimation]);

_game.Components.Remove(_animator);
}


And my draw method, changed to:
public void Draw(GameTime gameTime)
{
_animator.Draw(gameTime);
}

Which showed nothing.
I have trouble to see how it should work, as Ive removed _animator, and then im using it. Theres something I have totally misunderstood. When drawing/updating manually, how does I apply scale, position ect, and do I still apply bonepose? I think Ive tried about just any combination of the above.

Thanks for your help
Apr 12, 2008 at 9:45 PM
Edited Apr 12, 2008 at 9:47 PM
ok... I think I got it to work... You were right about drawing it twice because the use of mesh.Draw(), this is clear to me now. Thanks
I ended up with doing:

_animator.Visible = false //in the constructor

and ended up with a draw method that looks like:

public void Draw(Matrix viewMatrix, Matrix projectionMatrix, GameTime gameTime)
{
Matrix worldMatrix = Matrix.CreateScale(base.Scale) * Matrix.CreateFromYawPitchRoll(base.Rotation.Y, base.Rotation.X, base.Rotation.Z) * Matrix.CreateTranslation(base.Position);

foreach (ModelMesh mesh in _animator.Model.Meshes)
{
foreach (Effect effect in mesh.Effects)
{
if (effect is BasicEffect)
{
BasicEffect basic = (BasicEffect)effect;

basic.World = worldMatrix;
basic.View = viewMatrix;

basic.Projection = projectionMatrix;
}
else if (effect is BasicPaletteEffect)
{
BasicPaletteEffect palette = (BasicPaletteEffect)effect;
palette.World = worldMatrix;
palette.View = viewMatrix;

palette.Projection = projectionMatrix;
}
}
}
_animator.World = worldMatrix;
_animator.Draw(gameTime);
Run();
}

private void Run()
{
foreach (BonePose p in _animator.BonePoses)
{
p.CurrentController = _aniController;
p.CurrentBlendController = null;
}
}

Do anyone have any comments regarding this approach?
Apr 15, 2008 at 8:57 PM
Im happy to hear it helped.

I hate reading code on this forum lol.. the lack of formatting really sucks... but anyways...

Im not sure you need to run the Run() method every draw loop. Im pretty sure you should only need to run that once while loading -unless- you are switching between animations like in the dwarf tutorial. However you only seem to have one animation so you should be fine running it once. Even if you do switch animations however, I think that it should be handled in the update structure instead.
Mar 1, 2010 at 3:35 AM

Yes, Talusryn is right;
if you run the animation controller on every update / draw pass your game will initially run fine, but after some seconds / minutes (depending on your computer) it will start stuttering until it becomes unplayable. I run through this problem & it was very hard to find the cause. But it definatelly eats the memory!

So run the animation only when you change it!
I know I'm more than 2 years late, but smth is smth :D