I have a simple Maya 2013 example. It’s a box with two joints. Joints are connected, one is the root joint, the other is its child. Working scene units are meters.
Here’s the problem.
I export this example in Maya 2013 to FBX, and specify meters as export unit (the same as the working scene unit). The FBX dialog, under Units options, shows Scale Factor 1 (makes sense, meters to meters, no scale needed).
When reading the file via FBX SDK, the root joint’s translation data from FbxAnimCurve::KeyGetValue() is indeed in meters (I get exact values as shown in the Maya 2013 animation graph editor), but the translation data for the child joint (joint’s FbxNode > LclTranslation.GetCurve > KeyGetValue) is a hundred times larger than the values displayed in the Maya graph editor. As if the child joint’s values were exported in centimeters.
Get this! If I change the Maya working units to centimeters, and export to FBX in centimeters, (again, Scale Factor 1) then both, root joint’s and child joint’s data is in centimeters (just as you would expect). Now both joints are exported in the same units.
Maya 2013 imports this FBX file just fine. Even though values from FbxAnimCurve::KeyGetValue() are a hundred times larger, Maya 2013 somehow detects these are in centimeters, not meters like for the root joint.
How can I detect units for animation translations (translation data from FbxAnimCurve::KeyGetValue)? Until now, I used the FbxScene->GetGlobalSettings().GetSystemUnit() to detect the scene system unit but this is not enough. With this FBX example, I get scene units in meters, keyframe data for the root joint’s translation in meters, yet the child joint’s translation in centimeters.
(edited: added problematic FBX export and the Maya Binary source)
The FBX SDK converts the objects TRS and animation curves in the appropriate units only for the first level objects of the scene. All the animation curves of children hold values relative to the parent so they do not need to be converted. In Maya, even if you change the units to meters, all the internal data is always defined in centimeters. Based on this explanation, the answer to your question would be:
For all the objects that have no parent you simply cll KeyGetValue() and you’ll get it expressed in the “GetSystemUnit()”
And for all the other objects animation curves you will need to apply the conversion factor from centimeters to “GetSystemUnits()”. In your case : 0.01
Again, be aware that if your system is hierarchical, you will apply a double conversion since the parent already has the “GetSystemUnit()” factor in its scaling property.
The way I understand it now, there are three types of units client must handle when loading an fbx file:
1. File’s export units: the units selected during export, stored in the first level nodes (below the scene root).
2. File’s native units: stored in subsequent children nodes (cm for Maya, inch for 3ds Max).
3. Client’s import units: units the file must be converted to during import.
As an example, I have a 3ds Max export with following units:
1. File’s export units: centimeters (fbx first level nodes).
2. File’s native units: inches (fbx children nodes).
3. My application’s units: meters.
So the animation data from the first level nodes have to be converted from centimeters to meters, while the animation data from children nodes must be converted from inches to meters. I tested this strategy with various exports from Maya and 3ds Max, and it seems to work, at least for our examples.