Collada DOM 1.4 skinned mesh read from Maya export

Ok, hopefully I can condense this down to something sensible. I’ve got a skinned mesh exported from Maya 7 into a Collada 1.4 file using ColladaMaya 0.90, and I’m now trying to use DOM 1.4 (patch 2) to read it into my app, but I’m having a problem. I’ve removed error checking from the code I’m posting for the sake of clarity:

domInstance_controllerRef instanceController = instanceControllerArray[i];

const domInstance_controller::domSkeleton_Array &skeletonArray = instanceController->getSkeleton_array();

domInstance_controller::domSkeletonRef skeleton = skeletonArray[0];
xsAnyURI &skeletonRoot = skeleton->getValue();

daeElementRef skeletonRootElement = skeletonRoot.getElement();

“skeleton” appears valid, and if I query “skeletonRoot” for its Id, it replies “root” (which is indeed the root of the exported skeleton), but “skeletonRootElement” comes back NULL, which surprised me.

Now, if I want to get to the skin from the controller, I do:

xsAnyURI controllerURL = instanceController->getUrl();

daeElementRef controllerElement = controllerURL.getElement();

Then I type-check controllerElement, and cast it to domController, and then query it for its skin. That part seems to work.

Now, I could go ahead and search out the joint named “root” myself, but it seemed the point of having this available from the skeleton was so that wouldn’t be necessary - that I could immediately get a pointer to the appropriate root joint node from within a visual_scene.

FWIW, I can get the joint array from the skin, and iterate over that without problem.

So, is the skeleton->getValue() call only intended to provide the name of the root element, and the app is intended to search through the bound skin bones to find it?

If so, why is the getValue() call returning an xsAnyURI instead of an xsID (or some other alias of daeString)?

Anyways, assuming that I need to search for the joint, should just do a tree search through the nodes of the visual_scene that’s the grandparent of the instance_controller for a joint node that has a matching name?

Or, is there some really obvious thing I’m missing that would cut through all this? :slight_smile:

Ok, so after re-RTFS, I find:

The skeleton element is used to indicate where a skin controller is to start to search for the joint nodes it needs.

As the documentation for the skeleton node. So, I guess the intention is fairly clear. A couple of my questions remain, though:

Why is getValue() returning an xsAnyURI instead of an xsID?

Why do it this way, instead of having an xsAnyURI that actually points to the named joint? The URI “#root” seems to be uniquely pointing at the joint in question.

Thanks to anyone who can provide some insight here.

The skin joint lookup is supposed to search based on sid. Maya, I believe, outputs a single <skeleton> for every joint in the skin. But thats not necessary if they did it properly in the first place, but at the same time its not quite wrong either.

Heres a quick example (not valid COLLADA just so I can show the important points)

<controller id="character_skin">
  <skin>
    <source id="joints">
      <Name_array> hip spine1 spine2 head </Name_array>
  ...
</controller>

<library_nodes>
  <node id="character_skeleton" sid="hip">
    <node sid="spine1">
      <node sid="spine2">
        <node sid="head"/>
      </node>
    </node>
  </node>
</library_nodes>

<visual_scene>
  <node id="char1_skel">
    <instance_node url="#character_skeleton"/>
  </node>
  <node id="char1">
    <instance_controller url="#character_skin">
      <skeleton>#char1_skel</skeleton>
    </instance_controller>
  </node>
  <node id="char2_skel">
    <instance_node url="#character_skeleton"/>
  </node>
  <node id="char2">
    <instance_controller url="#character_skin">
      <skeleton>#char2_skel</skeleton>
    </instance_controller>
  </node>
</visual_scene>

First I’d like to point out that there are no nodes with id’s defined in the joint list in skin. You need to do an SID search for the nodes to use.
Second, I did something a little different than the DCC tools do to show a specific reason it was designed the way it is. I instance the skeleton heirarchy. This allows me to instance two copies of the skin and have the skeletons animated independently without having to duplicate the skeleton data for each instance.
Third, I only have one child even though I have 4 joints needed in the skin. As you noted in the spec, the node specified is just where to start your sid search, not the node you need. The reason that we allow multiple children is not necessarily to point at every node but to allow disjoint skeletons, or skinning against multiple skeletons.

We did that on purpose so you can reference skeletons from other documents. I think we might not have documented this aspect very well but if your document did this

<instance_controller url="#character_skin">
      <skeleton>file:///C:/someFile.dae#character_skeleton</skeleton>
    </instance_controller>

You can instance the skeleton defined in another document. Maybe you or your company keep a separate document conatining only a skin and skeleton library. When something like this occurs you should instance the skeleton in place there. But unlike the example shown earlier you would not be able to target it directly for animations. In the first example you can animate “char2_skel/head.rotateY.ANGLE” since the sid lookup should follow through the instance_node but it doesn’t follow through <skeleton> (or at least we never said it should).

Hopefully I have clarified this for you. I am not sure if anyone besides those of us who created this system truely understand why it is the way it is. None of the DCC tools expose the ability to instance multiple skeletons the way we do but we wrote COLLADA with the future in mind.

-Andy

PS. The latest COLLADA DOM on sourceForge in svn has an SID resolver you can use to do the joint lookup for you. You need to specify the target path (in this case the joint sid) and the container (where to start the search). But writing this response made me realize that the SID resolver does not follow through instance_node like I said sid resolution should. I will add that asap. But for the mean time you can use what the instance_node url points to as the container, not that you will ever get that case since the DCC tools don’t export data like that. But if they did…

Great - thanks for taking the time to explain that, that definitely clarifies things. I’m sure that my current tree-level view is missing a lot of forest topology. :slight_smile:

FWIW, the exported file I have does only have one skeleton node inside the instance_controller, and it does point at “root” (which is correct), with the heirarchy the way I expect. This is for a straightforward bipedal rig.

I ended up, for now anyways, simply writing a FindJoint() function that accepts the node array from visualScene->getNode_array() (where visualScene is the one where the instance_controller lives), and does a recursive search for the appropriate joint within that set of nodes. I’ll add a comment to indicate that doing a proper sid search for the skeleton root would be the preferred solution for the future.

I did get the import working yesterday, so two days total for coding isn’t too bad for getting a skinned mesh in and functional - despite some of the difficulties of dealing with something as large as Collada, there are definitely some big advantages.

Thanks again for your insight,
Jason