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.

I'm trying to manually create a ModelContent instance that includes custom Bone data in a custom ContentProcessor in the XNA Content Pipeline. I can't seem to create or assign manually created bone data due to either private constructors or read-only collections (at every turn).

The code I have right now that creates a single triangle ModelContent that I'd like to create a bone for is:

MeshContent mc = new MeshContent();
mc.Positions.Add(new Vector3(-10, 0, 0));
mc.Positions.Add(new Vector3(0, 10, 0));
mc.Positions.Add(new Vector3(10, 0, 0));

GeometryContent gc = new GeometryContent();
gc.Indices.AddRange(new int[] { 0, 1, 2 });
gc.Vertices.AddRange(new int[] { 0, 1, 2 });
mc.Geometry.Add(gc);

// Create normals
MeshHelper.CalculateNormals(mc, true);

// finally, convert it to a model
ModelContent model = context.Convert<MeshContent, ModelContent>(mc, "ModelProcessor");

The documentation on XNA is amazingly sparse. I've been referencing the class diagrams created by DigitalRune and Sean Hargreaves blog, but I haven't found anything on creating bone content.

Once the ModelContent is created, it's not possible to add bones because the Bones collection is read-only. And it seems the only way to create the ModelContent instance is to call the standard ModelProcessor via ContentProcessorContext.Convert. So it's a bit of a catch-22.

The BoneContent class has a constructor but no methods except those inherited from NodeContent... though now (true to form) maybe I've realized the solution by asking the question. Should I create a root NodeContent with two children: one MeshContent and one BoneContent as the root of my skeleton; then pass the root NodeContent to ContentProcessorContext.Convert?

Off to try that now...

share|improve this question
    
Solved. Answer to be posted after 9pm tonight due to new account reputation. In an nutshell, every design-time NodeContent instance gets a unique ModelBone at run-time. Details to come. –  cod3monk3y Apr 2 '12 at 20:06

1 Answer 1

up vote 4 down vote accepted

Solved!

A bone will be created for each NodeContent whether it is a BoneContent or a MeshContent. In the former case, it appears the intention of the BoneContent class is simply to indicate that the node is a bone only. The bone hierarchy at runtime will match this build time NodeContent hierarchy.

In my simple case, the solution was simply

MeshContent mc = new MeshContent();
... create mesh ...

mc.Transform = Matrix.CreateTranslation(0,10.0f,0);

// NOTE: type parameter has changed from MeshContent to NodeContent
ModelContent model = context.Convert<NodeContent, ModelContent>(mc, "ModelProcessor");

which creates a single bone at runtime. For a more complicated hierarchy I could do something like:

BoneContent turtle = new BoneContent();
MeshContent body = new MeshContent();
MeshContent head = new MeshContent();
MeshContent eye = new MeshContent();

turtle.Children.Add(body)
body.Children.Add(head);
head.Children.Add(eye);

head.Transform = ...;
body.Transform = ...;
eye.Transform = ...;

// create the one-eyed turtle
ModelContent model = context.Convert<NodeContent, ModelContent>(turtle, "ModelProcessor");

which would have 4 bones at runtime arranged in the chain: turtle->body->head->eye.

To assist in debugging, I found it useful to set the Name property (from ContentItem) at build time, then check Model.Root.Index and Model.Root.Name against the Model.Bones list.

share|improve this answer
    
Great work. Please mark this answer as correct when you get the chance. –  Jonathan Hobbs Apr 4 '12 at 2:01
    
Will do. Stackexchange is enforcing the 24-hour delay on marking my own answer as correct. One hour to go. –  cod3monk3y Apr 4 '12 at 17:14

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.