|
|
@@ -182,6 +182,7 @@ float defaultTicksPerSecond_ = 4800.0f;
|
|
|
float importStartTime_ = 0.0f;
|
|
|
float importEndTime_ = 0.0f;
|
|
|
bool suppressFbxPivotNodes_ = true;
|
|
|
+OutModel sceneFbxModel_;
|
|
|
|
|
|
int main(int argc, char** argv);
|
|
|
void Run(const Vector<String>& arguments);
|
|
|
@@ -246,6 +247,7 @@ String SanitateAssetName(const String& name);
|
|
|
|
|
|
unsigned GetPivotlessBoneIndex(OutModel& model, const String& boneName);
|
|
|
void ExtrapolatePivotlessAnimation(OutModel* model);
|
|
|
+void CollectSceneNodesAsBones(aiNode* rootNode);
|
|
|
|
|
|
int main(int argc, char** argv)
|
|
|
{
|
|
|
@@ -687,6 +689,17 @@ void ExportAnimation(const String& outName, bool animationOnly)
|
|
|
|
|
|
// Save scene-global animations
|
|
|
CollectAnimations();
|
|
|
+
|
|
|
+ // Most fbx animation files contain only skeleton and no model skinned mesh.
|
|
|
+ // -create model's bone struct and assign scene animation
|
|
|
+ if (suppressFbxPivotNodes_ && model.bones_.Size() == 0)
|
|
|
+ {
|
|
|
+ sceneFbxModel_.animations_ = sceneAnimations_;
|
|
|
+ sceneFbxModel_.bones_.Clear();
|
|
|
+
|
|
|
+ CollectSceneNodesAsBones(rootNode_);
|
|
|
+ }
|
|
|
+
|
|
|
BuildAndSaveAnimations();
|
|
|
}
|
|
|
}
|
|
|
@@ -1337,12 +1350,36 @@ void BuildAndSaveAnimations(OutModel* model)
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- boneNode = GetNode(channelName, scene_->mRootNode);
|
|
|
- if (!boneNode)
|
|
|
+ unsigned pos = channelName.Find("_$AssimpFbx$");
|
|
|
+
|
|
|
+ if (!suppressFbxPivotNodes_ || pos == String::NPOS || sceneFbxModel_.bones_.Size() == 0)
|
|
|
{
|
|
|
- PrintLine("Warning: skipping animation track " + channelName + " whose scene node was not found");
|
|
|
- outAnim->RemoveTrack(channelName);
|
|
|
- continue;
|
|
|
+ boneNode = GetNode(channelName, scene_->mRootNode);
|
|
|
+ if (!boneNode)
|
|
|
+ {
|
|
|
+ PrintLine("Warning: skipping animation track " + channelName + " whose scene node was not found");
|
|
|
+ outAnim->RemoveTrack(channelName);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ channelName = channelName.Substring(0, pos);
|
|
|
+
|
|
|
+ // every first $fbx animation channel for a bone will consolidate other $fbx animation to a single channel
|
|
|
+ // skip subsequent $fbx animation channel for the same bone
|
|
|
+ if (outAnim->GetTrack(channelName) != NULL)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ unsigned boneIndex = GetPivotlessBoneIndex(sceneFbxModel_, channelName);
|
|
|
+ if (boneIndex == M_MAX_UNSIGNED)
|
|
|
+ {
|
|
|
+ PrintLine("Warning: skipping animation track " + channelName + " whose scene node was not found");
|
|
|
+ outAnim->RemoveTrack(channelName);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ boneNode = sceneFbxModel_.pivotlessBones_[boneIndex];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -2775,6 +2812,12 @@ void CreatePivotlessFbxBoneStruct(OutModel &model)
|
|
|
|
|
|
void ExtrapolatePivotlessAnimation(OutModel* model)
|
|
|
{
|
|
|
+ // If there was no model present in the scene, use sceneFbxModel_
|
|
|
+ if ( suppressFbxPivotNodes_ && model == NULL && sceneFbxModel_.bones_.Size() > 0)
|
|
|
+ {
|
|
|
+ model = &sceneFbxModel_;
|
|
|
+ }
|
|
|
+
|
|
|
if (suppressFbxPivotNodes_ && model)
|
|
|
{
|
|
|
PrintLine("Suppressing $fbx nodes");
|
|
|
@@ -2896,3 +2939,16 @@ void ExtrapolatePivotlessAnimation(OutModel* model)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void CollectSceneNodesAsBones(aiNode* rootNode)
|
|
|
+{
|
|
|
+ if (!rootNode)
|
|
|
+ return;
|
|
|
+
|
|
|
+ sceneFbxModel_.bones_.Push(rootNode);
|
|
|
+
|
|
|
+ for (unsigned i = 0; i < rootNode->mNumChildren; ++i)
|
|
|
+ {
|
|
|
+ CollectSceneNodesAsBones(rootNode->mChildren[i]);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|