|
Tell us what you think of the site.
|
Autodesk Media & Entertainment User Community
|
Autodesk® 3ds Max®
|
|
Autodesk® Maya®
|
|
Autodesk® Softimage®
|
|
Autodesk® MotionBuilder®
|
|
Autodesk® Mudbox™
|
|
Autodesk® ImageModeler™
|
|
Autodesk® Sketchbook® Pro
|
|
Autodesk® Smoke on Mac®
|
| How to find out if an object is animated?
|
|
|
Howdy,
Is there a way to find out if an object is animated in the imported fbx file, so that if it isn’t, I can skip allocating animation tracks for that object?
Adios,
Cactus Dan
|
|
|
|
If this is zero, then there are no animations present
pScene->GetSrcObjectCount(FBX_TYPE(KFbxAnimStack))
|
|
|
|
Howdy,
Thanks for the info, but what about for individual objects?
For example, suppose the file to import has skeletal animation, camera animation but no light animation in the take. What I’d want to do is set animation keys in my application for the imported skeleton and camera but skip the light.
Adios,
Cactus Dan
|
|
|
|
|
You will have to do a pass over animation layers and check each node, I think.
Author: Doug Rogers
|
| Replied: 28 November 2010 02:13 AM
|
|
|
|
|
Howdy,
What do you mean “animation layer”?
Doing a search for “animation layer” doesn’t seem to get me very far. The only thing that I found in the docs was:
HKFCurveNode mLayer; // Ctrl Curve (Animation layering)
... from the kfcurvenode.h
Adios,
Cactus Dan
|
|
|
|
|
Something like this:
void FBXLoader::AddAnimation(KFbxScene* pScene) {
KFbxNode* rootNode = pScene->GetRootNode();
for (int i = 0; i < pScene->GetSrcObjectCount(FBX_TYPE(KFbxAnimStack)); i++)
{
KFbxAnimStack* lAnimStack = KFbxCast<KFbxAnimStack>(pScene->GetSrcObject(FBX_TYPE(KFbxAnimStack), i));
pScene->GetEvaluator()->SetContext(lAnimStack);
std::string name = lAnimStack->GetName();
m_animationStackMap[name] = lAnimStack;
AddAnimationRecursive(lAnimStack, rootNode, m_pRootFrame);
}
}
void FBXLoader::AddAnimationRecursive(KFbxAnimStack* pAnimStack, KFbxNode* pNode, FBXFrame * pFrame) {
int nbAnimLayers = pAnimStack->GetMemberCount(FBX_TYPE(KFbxAnimLayer));
std::string takeName = pAnimStack->GetName();
assert(m_takeNameToAnimationSetMap.find(takeName) != m_takeNameToAnimationSetMap.end());
FBXAnimationSet *pAnimationSet = m_takeNameToAnimationSetMap.find(takeName)->second.get();
for (int layerNo = 0; layerNo < nbAnimLayers; layerNo++)
{
KFbxAnimLayer* lAnimLayer = pAnimStack->GetMember(FBX_TYPE(KFbxAnimLayer), layerNo);
AddAnimationRecursive(lAnimLayer, pNode, takeName, pAnimationSet, pFrame);
}
}
void FBXLoader::AddAnimationRecursive(KFbxAnimLayer* pAnimLayer, KFbxNode* pNode, std::string &takeName,
FBXAnimationSet *pAnimationSet,
FBXFrame * pFrame) {
//AddAnimation(pAnimLayer, pNode, takeName, pAnimationSet, pFrame);
bool bNodeHasAnimation = HasSomeFCurves(pNode, pAnimLayer); // <<---------- check if this node has animation
int childCount = pNode->GetChildCount();
FBXFrame * pChildFrame = (FBXFrame *)pFrame->pFrameFirstChild;
for (int i = 0; i < childCount; i++)
{
assert(pChildFrame);
AddAnimationRecursive(pAnimLayer, pNode->GetChild(i), takeName, pAnimationSet, pChildFrame);
pChildFrame = (FBXFrame *)pChildFrame->pFrameSibling;
}
}
bool HasSomeFCurves(KFbxObject* pNode, KFbxAnimLayer* pAnimLayer) {
// return true as soon as one property on the object (or it's attributes)
// has an fcurve with one or more keys.
if (!pNode)
return false;
bool hasKeys = false;
pNode->RootProperty.BeginCreateOrFindProperty();
KFbxProperty prop = pNode->GetFirstProperty();
while (prop.IsValid() && hasKeys == false)
{
KFbxAnimCurveNode* fcn = prop.GetCurveNode(pAnimLayer, false);
hasKeys = HasKeysOnFCurves(fcn);
if (hasKeys)
{
const char * name = fcn->GetName();
KFbxAnimCurve* curve = fcn->GetCurve(0);
}
prop = pNode->GetNextProperty(prop);
}
pNode->RootProperty.EndCreateOrFindProperty();
return hasKeys; }
Author: Doug Rogers
|
| Replied: 28 November 2010 04:32 AM
|
|
|
|
|
Howdy,
Thanks for the code example.
Unfortunately, I’m using the 2010 sdk at the moment, and a few of the classes in your example aren’t available.
Right now I’m on Mac OS, using FBX2010 with Xcode 2.5, to stay compatible with the host application that I’m writing the import/export plugin for, so I’m a little hesitant to move to 2011. :(
Are there any known major incompatibilities if I move to 2011?
Adios,
Cactus Dan
|
|
|
|
|
>Are there any known major incompatibilities if I move to 2011?
The animation system is the biggest difference, and IMHO, much better.
You can still do the same thing in the older SDK, though.
void FBXLoader::AddAnimationRecursive(KFbxNode* pNode, AnimationFrame * pFrame) {
AddAnimation(pNode, pFrame);
int childCount = pNode->GetChildCount();
AnimationFrame * pChildFrame = (AnimationFrame *)pFrame->pFrameFirstChild;
for (int i = 0; i < childCount; i++)
{
assert(pChildFrame);
AddAnimationRecursive(pNode->GetChild(i), pChildFrame);
pChildFrame = (AnimationFrame *)pChildFrame->pFrameSibling;
}
}
void FBXLoader::AddAnimation(KFbxScene* pScene) {
HRESULT hr;
KFbxNode* rootNode = pScene->GetRootNode();
AddAnimationRecursive(rootNode, m_pRootFrame);
}
void FBXLoader::AddAnimation(KFbxNode* pNode, AnimationFrame *pFrame) {
int takeNodeCount = pNode->GetTakeNodeCount();
for(int i = 0; i < takeNodeCount; i++)
{
KFbxTakeNode* pTakeNode = pNode->GetTakeNode(i);
// check for default take or take with no entries
}
}
Author: Doug Rogers
|
| Replied: 28 November 2010 09:29 AM
|
|
|
|
|
Howdy,
Thanks for pointing me in the right direction. I managed to get something working in FBX2010.
Here’s what I did:
bool HasFBXAnimation(KFbxNode *pNode) {
Bool hasKeys = FALSE;
KFbxProperty prop = pNode->GetFirstProperty();
while(prop.IsValid())
{
KFCurveNode *fcn = prop.GetKFCurveNode();
if(fcn && fcn->KeyGetCount() > 0)
{
hasKeys = TRUE;
}
prop = pNode->GetNextProperty(prop);
}
return hasKeys; }
That seems to work fine. Does that look OK to you?
Adios,
Cactus Dan
|
|
|
|
|
You might have to bracket it with:
pNode->RootProperty.BeginCreateOrFindProperty();
pNode->RootProperty.EndCreateOrFindProperty();
Not sure, though.
Also, there is no point continuing to scan once hasKeys is true.
Author: Doug Rogers
|
| Replied: 28 November 2010 12:09 PM
|
|
|
|
|
Howdy,
Well, I was going to add a check for which properties have keys, for example if a joint only has rotation keys, then I don’t want to allocate translation and scale tracks in my application and fill them with keys.
But I’m having a strange thing happen. I have a “BuildJointSkeleton()” function which converts the skeleton nodes to my joints, and if I run the check for animation keys in that function, it only works for the first imported take. For all other imported takes or files it then returns false. Even if I close and open a new document, it still returns false. The only way for it to return true again is to quit and restart the application.
Have you ever encountered that kind of behavior?
If I only do the check for animation keys in my “LoadTake()” function, then it returns true for each take that is loaded and also each file that is merged into the document. But doing the check there, really slows down loading the animation take.
I may need to re-examine how I’m loading the take. Right now the loops are setup where it loops through the objects inside the loop through the frames. Maybe I should loop through the frames inside of looping through the objects so that the check for animation keys is only called once per object. Right now it’s calling the check function the same number of times as there are frames, for each object. :O
Adios,
Cactus Dan
|
|
|
|
Howdy,
Well, I think I’ve found an easier more efficient way to do what I wanted to do:
char* takeName = pNode->GetCurrentTakeNodeName(); KFCurveNode *fcn = pNode->LclTranslation.GetKFCurveNode(false, takeName);
if(fcn && fcn->KeyGetCount() > 0) {
// import the animation }
... and then do the same for scale and rotation, or any other property my import plugin will support.
This way it won’t have to cycle through all of the properties to check for the properties that my import plugin will support. It will go directly to the supported property to check for animation keys.
Adios,
Cactus Dan
|
|
|
|
In FBX 2011.3, the API KFbxNode::GetAnimationInterval() can tell you if there is animation for this FBX node, whick do the same thing as your above code. This API also check the node’s children recursively.
Please check FBX 2010, I remember it also has the same API.
Nian Wu
AutoDesk FBX Team
|
|
|
|