- fbx: take care not to drop transformation chain nodes that have node animations assigned, even if they specify identity transform in bind pose.

pull/14/head
Alexander Gessler 2012-07-27 16:18:47 +02:00
parent 80e7e18e28
commit bead86a830
1 changed files with 40 additions and 9 deletions

View File

@ -75,8 +75,11 @@ public:
: out(out)
, doc(doc)
{
ConvertRootNode();
// animations need to be converted first since this will
// populate the node_anim_chain_bits map, which is needed
// to determine which nodes need to be generated.
ConvertAnimations();
ConvertRootNode();
if(doc.Settings().readAllMaterials) {
// unfortunately this means we have to evaluate all objects
@ -439,16 +442,24 @@ private:
if(is_complex && doc.Settings().preservePivots) {
FBXImporter::LogInfo("generating full transformation chain for node: " + name);
for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
// XXX this may cause trouble with animations
if (chain[i].IsIdentity()) {
// query the anim_chain_bits dictionary to find out which chain elements
// have associated node animation channels. These can not be dropped
// even if they have identity transform in bind pose.
NodeAnimBitMap::const_iterator it = node_anim_chain_bits.find(name);
const unsigned int anim_chain_bitmask = (it == node_anim_chain_bits.end() ? 0 : (*it).second);
unsigned int bit = 0x1;
for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i, bit <<= 1) {
const TransformationComp comp = static_cast<TransformationComp>(i);
if (chain[i].IsIdentity() && (anim_chain_bitmask & bit) == 0) {
continue;
}
aiNode* nd = new aiNode();
output_nodes.push_back(nd);
nd->mName.Set(NameTransformationChainNode(name, static_cast<TransformationComp>(i)));
nd->mName.Set(NameTransformationChainNode(name, comp));
nd->mTransformation = chain[i];
}
@ -1489,7 +1500,7 @@ private:
if (comp != TransformationComp_Rotation && comp != TransformationComp_Scaling &&
comp != TransformationComp_Translation) {
has_complex = true;
has_complex = true;
}
}
}
@ -1521,11 +1532,19 @@ private:
}
// otherwise, things get gruesome and we need separate animation channels
// for each part of the transformation chain.
for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
// for each part of the transformation chain. Remember which channels
// we generated and pass this information to the node conversion
// code to avoid nodes that have identity transform, but non-identity
// animations, being dropped.
unsigned int flags = 0, bit = 0x1;
for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i, bit <<= 1) {
const TransformationComp comp = static_cast<TransformationComp>(i);
if (chain[i] != node_property_map.end()) {
flags |= bit;
ai_assert(comp != TransformationComp_RotationPivotInverse);
ai_assert(comp != TransformationComp_ScalingPivotInverse);
const std::string& chain_name = NameTransformationChainNode(fixed_name, comp);
@ -1556,7 +1575,7 @@ private:
max_time,
min_time);
// pivoting requires us to generate an inverse channel to undo the pivot translation
// pivoting requires us to generate an implicit inverse channel to undo the pivot translation
if (comp == TransformationComp_RotationPivot) {
const std::string& invName = NameTransformationChainNode(fixed_name, TransformationComp_RotationPivotInverse);
aiNodeAnim* const inv = GenerateTranslationNodeAnim(invName,
@ -1569,6 +1588,9 @@ private:
ai_assert(inv);
node_anims.push_back(inv);
ai_assert(TransformationComp_RotationPivotInverse > i);
flags |= bit << (TransformationComp_RotationPivotInverse - i);
}
else if (comp == TransformationComp_ScalingPivot) {
const std::string& invName = NameTransformationChainNode(fixed_name, TransformationComp_ScalingPivotInverse);
@ -1582,6 +1604,9 @@ private:
ai_assert(inv);
node_anims.push_back(inv);
ai_assert(TransformationComp_RotationPivotInverse > i);
flags |= bit << (TransformationComp_RotationPivotInverse - i);
}
break;
@ -1605,6 +1630,8 @@ private:
continue;
}
}
node_anim_chain_bits[fixed_name] = flags;
}
@ -2078,6 +2105,10 @@ private:
typedef std::map<const Geometry*, std::vector<unsigned int> > MeshMap;
MeshMap meshes_converted;
typedef std::map<std::string, unsigned int> NodeAnimBitMap;
NodeAnimBitMap node_anim_chain_bits;
aiScene* const out;
const FBX::Document& doc;
};