0
\$\begingroup\$

Through help on this site I was able to draw the triangles of an unrotated, nonscaled nontransformed mesh created in Blender and exported to OBJ, accurately imported through Assimp and rendered in XNA Graphics. However after applying rotation on a single axis in Blender(Z) and adding materials(I wanted to test loading of materials through Assimp) the same mesh appears incomplete. Is something wrong with my view matrix or is it something else?

This is what the unrotated mesh looks like: enter image description here

Here is the rotated mesh: enter image description here

Camera, View and Projection are defined as follows:

cameraPos = new Vector3(0, 5, 9);
viewMatrix = Matrix.CreateLookAt(cameraPos, new Vector3(0, 0, 1), new Vector3(0, 1, 0));
projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, device.Viewport.AspectRatio, 1.0f, 200.0f);

Rendering is done through this code:

device.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.DarkSlateBlue, 1.0f, 0);
effect = new BasicEffect(GraphicsDevice);
effect.VertexColorEnabled = true;

effect.View = viewMatrix;
effect.Projection = projectionMatrix;
effect.World = Matrix.Identity;

foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
    pass.Apply();
    device.SetVertexBuffer(vertexBuffer);
    device.Indices = indexBuffer;
    device.DrawIndexedPrimitives(Microsoft.Xna.Framework.Graphics.PrimitiveType.TriangleList, 0, 0, oScene.Meshes[0].VertexCount, 0, mMesh.FaceCount);
}
base.Draw(gameTime);
\$\endgroup\$
1
\$\begingroup\$

Without being able to see the contents of the .OBJ file, I can't tell what the problem might be. Given only 1 face is showing I suspect the application of materials has split your model up into 6 meshes, and if the rest of your code is the same as your previous question, you are only loading the first mesh in your scene.

Try exporting 2 version of your cube, 1 with a rotation applied, and the other with materials applied. If the rotated version works properly, but the version with materials doesn't, then it may be the problem described above. In that case, try the code below (or just try it anyway)

VertexBuffer[] vertexBuffers;
IndexBuffer[] indexBuffers;

private void SetUpVertices()
{
    int count = oScene.MeshCount;
    vertexBuffers = new VertexBuffer[count]
    indexBuffers = new IndexBuffer[count]

    Mesh mMesh;
    for (int m = 0; m < count;m++)
    {
         mMesh = oScene.Meshes[m];
        vertices = new VertexPositionColor[mMesh.VertexCount];
        indices = new  short[mMesh.FaceCount*3];

        int i=0;
        foreach (Vector3D mVec in mMesh.Vertices)
        {
            vertices[i] = new VertexPositionColor(new Vector3(mVec.X, mVec.Y, mVec.Z), Color.Red);
            i++;
        }

        int f = 0;
        Face mFace;
        for (i = 0 ; i < mMesh.FaceCount*3 ; i=i+3) 
        {
            mFace = mMesh.Faces[f];
            f++;
            indices[i] = (short)mFace.Indices[0];
            indices[i + 1] = (short)mFace.Indices[1];
            indices[i + 2] = (short)mFace.Indices[2];
        }

        vertexBuffer = new VertexBuffer(device, VertexPositionColor.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
        vertexBuffer.SetData(vertices);

        indexBuffer = new IndexBuffer(device, typeof(short), indices.Length, BufferUsage.None);
        indexBuffer.SetData(indices);

        vertexBuffers[m] = vertexBuffer;
        indexBuffers[m] = indexBuffer;
    }
}


protected override void Draw(GameTime gameTime)
{
    device.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.DarkSlateBlue, 1.0f, 0);
    effect = new BasicEffect(GraphicsDevice);
    effect.VertexColorEnabled = true;

    effect.View = viewMatrix;
    effect.Projection = projectionMatrix;
    effect.World = Matrix.Identity;

    for (int i = 0; i < vertexBuffers.Length; i++)
    {
        device.SetVertexBuffer(vertexBuffers[i]);
        device.Indices = indexBuffers[i];

        foreach (EffectPass pass in effect.CurrentTechnique.Passes)
        {
            pass.Apply();
            device.DrawIndexedPrimitives(Microsoft.Xna.Framework.Graphics.PrimitiveType.TriangleList, 0, 0, vertexBuffers[i].VertexCount, 0, indexBuffers[i].IndexCount);
        }
    }
    base.Draw(gameTime);
}

With this code, you might want to define your own custom scene class that takes a Assimp Scene object, calls the SetUpVertices function, and defines a public Draw method if you plan on having multiple scenes in your game.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks, your code works. I'll mark it as the answer. Looks like Assimp only has one material per mesh. Do you know of any sites that explain how to traverse the Scene object in greater detail? I would like to learn how to load and render materials, textures and animations using only Assimp and XNA. Not for any reason other than curiousity of rendering at a low level without the Content Pipeline. Assimp's documentation is hard for me to understand. \$\endgroup\$ – user1278255 May 9 '14 at 9:12
  • \$\begingroup\$ I've updated the draw call - spotted a bug which wasn't apparent with the cube, but would potentially be with other meshes. As for sites, I just had a quick look in the Assimp.NET Scene and Mesh code files while answering this. I haven't used it myself, so I can't really offer any help. I'm relying solely on my code experience and analysis skills here. \$\endgroup\$ – Seta May 9 '14 at 9:32
  • \$\begingroup\$ Fixed another bug in the code I posted. Going to mark as answer? \$\endgroup\$ – Seta May 9 '14 at 12:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.