3
\$\begingroup\$

I have a little problem with my 3D model (.fbx) rendered in XNA, look at screenshot.

Screenshot:

Doesn't look quite right...

It should be a lego brick, which was modelated in Blender, then exported to .fbx and added to XNA project. My problem is transparency, I tried so much with depthbuffer, z-buffer etc., but nothing helped. Here's my code:

namespace Using3DModels
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;


    float myModelRotation;
    Vector3 myModelPosition;
    /// <summary>
    /// Stores the model that we are going to draw.
    /// </summary>
    private Model model;

    /// <summary>
    /// Stores the world matrix for the model, which transforms the 
    /// model to be in the correct position, scale, and rotation
    /// in the game world.
    /// </summary>
    private Matrix world = Matrix.CreateTranslation(new Vector3(6, 4, 0));

    /// <summary>
    /// Stores the view matrix for the model, which gets the model
    /// in the right place, relative to the camera.
    /// </summary>
    private Matrix view = Matrix.CreateLookAt(new Vector3(30, 25, -10), new Vector3(5, 5, 0), Vector3.UnitY);

    /// <summary>
    /// Stores the projection matrix, which gets the model projected
    /// onto the screen in the correct way.  Essentially, this defines the
    /// properties of the camera you are using.
    /// </summary>
    private Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), 800f / 480f, 0.1f, 100f);


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

    /// <summary>
    /// Allows the game to perform any initialization it needs to before starting to run.
    /// This is where it can query for any required services and load any non-graphic
    /// related content.  Calling base.Initialize will enumerate through any components
    /// and initialize them as well.
    /// </summary>
    protected override void Initialize()
    {
        base.Initialize();
    }

    /// <summary>
    /// LoadContent will be called once per game and is the place to load
    /// all of your content.
    /// </summary>
    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);

        model = Content.Load<Model>("lego6");

        myModelPosition = Vector3.Zero;
        myModelRotation = MathHelper.ToRadians(45f);
    }

    /// <summary>
    /// UnloadContent will be called once per game and is the place to unload
    /// all content.
    /// </summary>
    protected override void UnloadContent()
    {
    }

    /// <summary>
    /// Allows the game to run logic such as updating the world,
    /// checking for collisions, gathering input, and playing audio.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Update(GameTime gameTime)
    {
        // Allows the game to exit
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();

        myModelRotation += MathHelper.ToRadians(1f);

        base.Update(gameTime);
    }

    /// <summary>
    /// This is called when the game should draw itself.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.BlendState = BlendState.Opaque;
        GraphicsDevice.DepthStencilState = DepthStencilState.Default;
        GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;



        GraphicsDevice.Clear(Color.DarkGray);

        DrawModel(model, world, view, projection);

        base.Draw(gameTime);
    }

    /// <summary>
    /// Does the work of drawing a model, given specific world, view, and projection
    /// matrices.
    /// </summary>
    /// <param name="model">The model to draw</param>
    /// <param name="world">The transformation matrix to get the model in the right place in the world.</param>
    /// <param name="view">The transformation matrix to get the model in the right place, relative to the camera.</param>
    /// <param name="projection">The transformation matrix to project the model's points onto the screen correctly.</param>
    private void DrawModel(Model model, Matrix world, Matrix view, Matrix projection)
    {
        GraphicsDevice.DepthStencilState = DepthStencilState.Default;

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


        foreach (ModelMesh mesh in model.Meshes)
        {
            foreach (BasicEffect effect in mesh.Effects)
            {
                effect.World = transforms[mesh.ParentBone.Index] * Matrix.CreateRotationY(myModelRotation) * Matrix.CreateTranslation(myModelPosition);
                effect.View = view;
                effect.Projection = projection;

            }

            mesh.Draw();
        }
    }

}
}
\$\endgroup\$
3
  • \$\begingroup\$ From a quick glance at the screenshot, it looks like your backface culling is backward; you're rendering the backs of surfaces, but not the fronts. \$\endgroup\$ Commented Dec 25, 2012 at 22:45
  • \$\begingroup\$ thanks for help, but I'm only beginner at XNA, so I have no idea how to fix it :/ do you have any suggestions? \$\endgroup\$
    – MADA
    Commented Dec 25, 2012 at 22:50
  • \$\begingroup\$ I don't know XNA. Just chiming in with an initial diagnosis, in the hopes that somebody with XNA experience will be able to advise on the next step. Simple fix (assuming I'm right about what's happening) would be to invert the normals on the model before exporting it. \$\endgroup\$ Commented Dec 26, 2012 at 0:42

1 Answer 1

4
\$\begingroup\$

This looks like a culling issue, like Trevor Powell pointed out. A simple way to test if it really is a problem related to culling is to turn it off like this:

RasterizerState rasterizerState = new RasterizerState();
rasterizerState.CullMode = CullMode.None;
GraphicsDevice.RasterizerState = rasterizerState;

Please note that disabling culling is not the best idea (except for some corner cases where you want to achieve some special effect) for a shipping product, because it also draws triangles not facing the camera and thus slowing down the drawing.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I'd say (like both the above) that that is the problem, however this means that your video card is drawing twice as many polys as needed. XNA does culling backwards from a lot of other software, I can never remember whether it's Clockwise or CounterCW (CCW and CW from now on) but XNA is backwards. You have two options: 1: Tell XNA to set the rasterizerState to the opposite cullmode 2: Tell blender to export using the opposite winding order. Winding order is the order around a polygon that the vertices are exported or drawn, and this order is supposed to be synonymous with forwards or... \$\endgroup\$
    – Phil
    Commented Dec 31, 2012 at 0:16
  • \$\begingroup\$ ...backwards facing. This picture: arcsynthesis.org/gltut/Positioning/WindingOrder.svg shows clockwise winding order on the left, and counter on the right. Each cull mode will stop one of these tris from being drawn from the front. \$\endgroup\$
    – Phil
    Commented Dec 31, 2012 at 0:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .