Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Preconditions: I have some models, that does only contain some meshes and one texture. There is no animation within the model. An example: a model of a table.

I want to draw the Model with a custom effect, so I have to swap the effect after loading the model. In order to draw them correctly, I have to apply the bone transformation manually on each draw for each mesh and effect as can be seen here. So there are two questions:

  1. Is there a option during import that allows my to apply the bone transformation on all vertices, so that during draw call I should not have to do this?
  2. Is there a option during import that merges all vertices into a Vertex- and IndexBuffer, that allows me to draw the whole model with just one call?

I'm pretty sure that the build-in "Autodesk FBX - XNA Framework" does not support this features, but maybe there is an other imported available or an other possibility I missed.

The aim is to speed up rendering a little bit especially by using instancing. So having one VertexBuffer to draw at one time would be pretty nice.

share|improve this question

1 Answer 1

up vote 1 down vote accepted

Your first question can only be solved with a custom model processor. You could use something like this:

[ContentProcessor(DisplayName = "Custom Model Processor")
public class CustomModelProcessor : ModelProcessor
{
    public override ModelContent Process(NodeContent input, ContentProcessorContext context)
    {
        Matrix transformMatrix = //Whatever transformation you like
        BakeTransform(input, transformMatrix);
        MeshContent mesh = new MeshContent();
        //Initialize the MeshContent parameters (Name, Identity, etc.) how you like
        //f.e. use the values of the root node (input)
        MergeGeometry(input, mesh);
        NodeContent node = mesh; //Create a NodeContent from the mesh with all geometries
        return base.Process(node, context); //Process the new node instead of the input node
    }

    //This method transforms all vertices with the given transformMatrix)
    static void BakeTransform(NodeContent input, Matrix transformMatrix)
    {
        foreach(NodeContent child in input.Children)
        {
            MeshHelper.TransformScene(child, transformMatrix);
            BakeTransform(child, transformMatrix);
        }
    }

    //This method merges all the GeometryContent found in the input NodeContent
    static void MergeGeometry(NodeContent input, MeshContent output)
    {
        foreach (NodeContent node in input.Children)
        {
            MeshContent mesh = node as MeshContent;
            if (mesh != null)
            {
                foreach (GeometryContent geom in mesh.Geometry)
                {
                    output.Geometry.Add(geom);
                }
            }
            //Loop
            MergeGeometry(node, output);
        }
    }
}

For every model you import through the content pipeline you need to specify this processor as the processor for this piece of content. For your second question I don't have any idea of why you need this because it doesn't really matter whether you pass many small buffers, or one big buffer to the gpu. But it also could be implemented in a model processor by recursively adding the vertex and index buffers along with the geometry and everything else you need to the parent mesh. You should remember you can't use more than one material for this single big mesh, if you combine all the data into one big buffer.

-EDIT-

Added the code for merging the geometries to the code.

share|improve this answer
    
Thanks for the answer. I will try this out. The reason for the second question lies in the API of GraphicsDevice.DrawInstancedPrimitives. I can set a VertexBuffer and IndexBuffer before and then calls this method ans it takes a Matrix[] of worlds to draw this model at different locations. This reduce CPU usage and transfers to GPU. The only way (I know) to do this at the moment, it to call this method an every ModelMesh of a Model. But it can be more efficient, if there is only one ModelMesh in a Model to draw, I think. –  user27811 Feb 14 '13 at 6:47
    
I'm not sure how to do this, but like I already said you could loop through all the meshes in the processor and add their data to the root NodeContent or to a new NodeContent and then give the chained ModelProcessor this content to process. I try to do it and give you the code if it works. –  eagle999 Feb 15 '13 at 18:00
    
@hichaeretaqua I added some sample code for merging, this works for models with two or three MeshContents, but I'm not sure for higher counts because I didn't had a model with more MeshContents. –  eagle999 Feb 15 '13 at 18:44
    
To complete: It works! Here I found another ContentProcessor that implement the merge of the buffers: quickstartengine.codeplex.com/SourceControl/latest#185510. Its written for XNA3, but it can be easily adapted. –  user27811 Jun 18 '13 at 5:35

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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