XNA Creators Club Online
Page 1 of 1 (7 items)
Sort Posts: Previous Next

Custom Model Importer -- what to do with bone data?

Last post 7/24/2009 2:29 PM by N E D Gold. 6 replies.
  • 7/2/2009 10:13 PM

    Custom Model Importer -- what to do with bone data?

    I use MilkShape for my modeling needs, but the FBX exporter doesn't want to play nice with Game Studio 3.1 (at least not for me anyway).  So I have decided to learn how to write a custom model importer for MS3D. 

    Using the OBJImporter example as a reference, I have successfully modified it to accept the MS3D ASCII version of a model.  It creates the meshes and applies the textures beautifully [ I'm so proud :-) ] but I'm not sure what to do with the bone structures.

    When processing the verts, tex cood, and norms, there was a reference to a bone index that I ignored because I don't know what to do with it.  This index just specifies to which bone that vertex is associated with.  At first I thought I should set up a vertex channel like I did with the tex cood and normals, but the only channel name that seemed close was Weights and that doesn't seem to be what I'm looking for (or is it?)

    Also, the MS3D file has a whole section on bones that I don't know how to process.  This section contains the following info:

    # of bones
    bone name
    parent bone name
    flags, position, and rotation
    // animation info
    # position keys
    { time, position }
    # rotation keys
    { time, rotation }

    I'm also looking at the Skinned Model example for clues.  However, that is a Content Processor and I'm working on an Importer.  (It seems to me, the Importer should be able to create the bone information first which would later be processed by the Content Processor).  I'm also not sure about this Tag thingamajig as called for in the Skinning example.

    So, what am I supposed to do with this bone information?

    -Ron
    XNA Neophyte
  • 7/2/2009 11:19 PM In reply to

    Re: Custom Model Importer -- what to do with bone data?

    The Content Pipeline object model represents skinned data as a VertexChannel<BoneWeightCollection>, with key VertexChannelNames.Weights().

    This channel holds a list of 1+ weights for the vertex, storing the bone name and weight strength for each bone that influences the vertex.
    XNA Framework Developer - blog - homepage
  • 7/3/2009 2:37 AM In reply to

    Re: Custom Model Importer -- what to do with bone data?

    Here is an example of the data I'm working with:

    Bones: 46
    "base"
    ""
    24 0.009673 -0.012660 0.000000 0.000000 0.000000 0.000000
    156
    1.000000 0.000000 0.000000 0.000000
    ...

    I have the number of bones in the model, the current bone name, parent bone name (or "" if root).

    24 is a flag that I ignore
    0.009673 -0.012660 0.000000 is the bone position
    0.000000 0.000000 0.000000 is the bone rotation
    156 is the number of position keys for animation
    1.000000 is the first frame time
    0.000000 0.000000 0.000000 is the position at that time
    ...and so forth

    Disregarding the animation data for the moment, I added these two lines:
    ...
    private int boneDataIndex;
    ...
    boneDataIndex = meshBuilder.CreateVertexChannel<BoneWeightCollection>(VertexChannelNames.Weights());
    ...

    but I receive an error (Unable to parse ms3d txt file. Exception: Object reference not set to an instance of an object. )

    Hmmm...

    well, I had initially looked at this method previously, but I failed to see how this will work given the data I have to work with.   Since I don't actually have any weights, I suppose I could just assign a weight of one, once I get that line working.  Is this right?:  Create 46 BoneWeight objects (46 = number of bones in the model) all with a weight of 1.0 and whatever the name of the bone (such as "base" in the above example).  Track these in a list so when I'm processing the vertex data I can use the SetVertexChannelData(boneDataIndex, boneList[boneNdx])???

    My concerns are that I am not specifying the hierarchy for the bones, nor the initial position or rotation.   This is why I'm lost and seek help.

    I would also like to know where I can stuff the animation data.

    TIA
    -Ron
    XNA Neophyte
  • 7/4/2009 7:32 PM In reply to

    Re: Custom Model Importer -- what to do with bone data?

    N E D Gold:

    Disregarding the animation data for the moment, I added these two lines:
    ...
    private int boneDataIndex;
    ...
    boneDataIndex = meshBuilder.CreateVertexChannel<BoneWeightCollection>(VertexChannelNames.Weights());
    ...

    but I receive an error (Unable to parse ms3d txt file. Exception: Object reference not set to an instance of an object. )



    I'm making progress!!!

    I first thought the above error was some sort of syntax error because all I did was tell the meshBuilder I was going to add some bone weights to it.  But Nooooo, in this case the error means it wants bone data now!  P.S. only use that statement and the other bone related statements if your model actually has bone data. 

    In this case, this means I need to process the bone data portion of the ms3d file before I process the vertex data.  Why?  Because I have learned that  CreateVertexChannel(weights) requires a BoneWeightCollection as input which is a collection of one or more BoneWeight objects that specify the name and weight for that vertex.  The BoneWeight.Name must match a BoneContent.Name object already in existence.  Thus, I have to build all of the BoneContent objects first.  And that's fine, as this is where you build the skeleton hierarchy that I was previously concerned with.  Unfortunately, bone data comes after vertex data in the ms3d file, so two passes are required.  (Actually, this pre-processing must also be done for building up the Materials ahead of the vertices as well, so my importer makes three passes; one for the materials, one for the bones, and lastly one for the vertex/tex cood/normals).

    Now I think I have a proper skeleton of bones so let's skip ahead to the generic model drawing fragment below:

    // Copy any parent transforms.
    Matrix[] transforms = new Matrix[model.Bones.Count];
    model.CopyAbsoluteBoneTransformsTo(transforms);

    In my test model, I have 46 bones.  But this model is kind of weird in that it had a camera attachment point (cam bone) that wasn't directly connected to the rest of the bones (it was a second root bone).  Since you can't have two root bones (as I learned the hard way) I created a master root bone and attached the main skeleton with this cam bone.  Anyway, that means I should have 46+1 bones in the model.  However, in the above code, model.Bones.Count = 52.  Huh?

    I then loaded a simple model that is only two triangles and no bones whatsoever, yet model.Bones.Count = 2.  So that got me thinking....BoneContent extends from NodeContent and NodeContent is the return value for Importers.  Each mesh you process is also a NodeContent object that is added as a child to the root node that will become the return value.  (Bones are also added as children to the root node.)  So, for the simple two triangle model, you have the main root node plus the mesh node = 2 nodes and apparently nodes also means bones.

    Back to my test model, it has 4 meshes, so let's see if it adds up:  1 root node return value + 4 mesh nodes + 46 bone nodes + 1 master root bone node = 52.  Yea!!!!  it works.

    But wait!  Won't this throw a monkey wrench in the works when it comes to animating later on?  How am I going to separate mesh nodes from bone nodes?  I guess I'll soon find out as I tackle animation next.

    - - - - - - - -
    Although my Importer builds w/o errors and draws correctly I won't know if the bones I added are actually correct until I start to move them.  After all, the model was drawn correctly before I even started adding bones to it.

    Could someone please confirm that I'm on the right track?  I'd really appreciate it.  Thanks!

    -Ron
    XNA Neophyte
  • 7/20/2009 6:29 PM In reply to

    Re: Custom Model Importer -- what to do with bone data?

    Did you do any progress on this? I'm exactly in your same situation. My model.Bones array contains not only the bones, but the meshes as well. Thanks in advance!
  • 7/20/2009 11:02 PM In reply to

    Re: Custom Model Importer -- what to do with bone data?

    Okay I think I got this. In my content processor (which takes data from my importer) now I have this: BoneContent skeleton = MeshHelper.FindSkeleton(input); IList<BoneContent> bones = MeshHelper.FlattenSkeleton(skeleton); This will give you a list of BoneContent (bones), and it will have the right number of bones. From that, just give a look at the Skinned Model XNA sample (I'm looking at it right now).
  • 7/24/2009 2:29 PM In reply to

    Re: Custom Model Importer -- what to do with bone data?

    The animation section threw me for a loop (pun intended), and I was not able to get past that.  I decided to put this project on hold and move on to something else with the intention of re-visiting it when my C#/XNA skills have improved.

    Good luck Hangman, I hope you succeed where I have failed.
    -Ron
    XNA Neophyte
Page 1 of 1 (7 items) Previous Next