Exported FBX to Monogame doesn't translate all meshes

I’m taking a crack at a minecraft clone in Monogame, and I am trying to get my model to render as it’s shown in Blender 2.9.1. When I look at the model in Blender, it looks great. When displaying in Monogame, the head is distinct but the body, arms, and legs are all mashed together. When I inspect the ParentBone for each ModelMesh, all except for the head have the same ModelTransform and Transform (but ModelTransform != Transform).

This is what I made in Blender:

But this is how it renders in Monogame:
image

I then tried creating an armature and adding bones, but did not seem to change anything other than the model in Monogame had a lot more bones in it. I thought it had something to do with how I exported, but I tried both FBX All and Local All for scaling with no change. I’ve also tried exporting as DAE instead of FBX (still need to use the FBX Importer for this to work) and no change there either.

My content file for completeness:

Where I am missing a step that is causing what looks to be a translation issue? Minimally reproduceable code is below. I did find something on this site about storing the transforms for the bones, but when I tried to use that all I could see was the top of the head and couldn’t rotate it? Or maybe I’m holding it wrong, I left it the code below commented out.

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

namespace test
{
    public class Game1 : Game
    {
        private GraphicsDeviceManager _graphics;
        private Model model;
        private Texture2D texture;
        private Vector3 position;
        private Matrix world = Matrix.CreateTranslation(new Vector3(0, 0, 0));
        private Matrix view = Matrix.CreateLookAt(new Vector3(0, 0, 10), new Vector3(0, 0, 0), Vector3.UnitY);
        private Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), 800/480f, 0.1f, 100f);

        public Game1()
        {
            _graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            IsMouseVisible = true;
        }

        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            base.Initialize();
        }

        protected override void LoadContent()
        {
            model = Content.Load<Model>("human");
            texture = Content.Load<Texture2D>("human_texture");;
            position = new Vector3(0, 0, 0);
            world = Matrix.CreateRotationX(-0.5f) * Matrix.CreateRotationY(0.5f) * Matrix.CreateRotationZ(0.1f)  * Matrix.CreateTranslation(position);

            // TODO: use this.Content to load your game content here
        }

        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();
                world = Matrix.CreateRotationX(-0.5f) * Matrix.CreateRotationY(0.5f) * Matrix.CreateRotationZ(0.1f)  * Matrix.CreateTranslation(position);
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            // pixelate textures
            GraphicsDevice.SamplerStates[0] = SamplerState.PointWrap;

            // lifted this from somewhere on the internet, but all I see is the top of the head and can't rotate when I use it?
            Matrix[] transforms = new Matrix[model.Bones.Count];
            model.CopyAbsoluteBoneTransformsTo(transforms);

            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.World = world;//transforms[mesh.ParentBone.Index];
                    effect.View = view;
                    effect.Projection = projection;
                    effect.Texture = texture;
                }
                mesh.Draw();
            }

            base.Draw(gameTime);
        }
    }
}

I’ve also uploaded my full .blend file, the generated FBX, and the texture here.

Change to:

effect.World = transforms[mesh.ParentBone.Index] * world; // (don’t forget - order is important)

That should work. :wink:

1 Like

OMFG IT WORKED! Thank you so much!

1 Like