static void extractKeyTimes(FbxNode* fbxChildNode, FbxAnimLayer* fbxAnimLayer, const char* channel, hkxNode* node, hkReal startTime, hkReal endTime) { HK_ASSERT(0x0, startTime <= endTime || endTime < 0.f); startTime = hkMath::max2(startTime, 0.f); FbxAnimCurve* lAnimCurve = fbxChildNode->LclTranslation.GetCurve(fbxAnimLayer, channel); if (lAnimCurve) { int lKeyCount = lAnimCurve->KeyGetCount(); hkReal lKeyTime; // Store keyframe times in seconds(from [0, endTime]) for(int lCount = 0; lCount < lKeyCount; lCount++) { lKeyTime = hkMath::max2((hkReal)lAnimCurve->KeyGetTime(lCount).GetSecondDouble(), 0.f); if (lKeyTime >= startTime && (lKeyTime <= endTime || endTime < 0.f)) { if (node->m_linearKeyFrameHints.indexOf(lKeyTime) < 0) { node->m_linearKeyFrameHints.pushBack(lKeyTime - startTime); } } else // handle case of [EXP-2436], where no keys in the range but range is affected by keys outside, so have to mark at start and end { if ((lKeyTime < startTime) &&(node->m_linearKeyFrameHints.indexOf(0.f) < 0)) { node->m_linearKeyFrameHints.pushBack(0.f); } else if (endTime >= 0.f &&(lKeyTime - startTime > endTime) &&(node->m_linearKeyFrameHints.indexOf(endTime - startTime) < 0)) { node->m_linearKeyFrameHints.pushBack(endTime - startTime); } } } } }
void ofxFBXScene::parseRotationCurve(ofxFBXNode & node, FbxAnimLayer * pAnimLayer, FbxNode* fbxNode, FbxPropertyT<FbxDouble3> &rotation){ node.originalRotation = ofQuaternion(rotation.Get().mData[0], ofVec3f(1, 0, 0), rotation.Get().mData[1], ofVec3f(0, 1, 0), rotation.Get().mData[2], ofVec3f(0, 0, 1)); node.getNode().setOrientation(node.originalRotation); ofLogVerbose("ofxFBXScene") << "original rotation " << endl << node.originalRotation << endl; if(!rotation.GetCurve(pAnimLayer)) return; FbxAnimCurve* lAnimCurveX = rotation.GetCurve(pAnimLayer,"X"); FbxAnimCurve* lAnimCurveY = rotation.GetCurve(pAnimLayer,"Y"); FbxAnimCurve* lAnimCurveZ = rotation.GetCurve(pAnimLayer,"Z"); int xKeyCount = lAnimCurveX ? lAnimCurveX->KeyGetCount() : 0; int yKeyCount = lAnimCurveY ? lAnimCurveY->KeyGetCount() : 0; int zKeyCount = lAnimCurveZ ? lAnimCurveZ->KeyGetCount() : 0; FbxTime lKeyTime; int lCount; FbxTime lXKeyTime,lYKeyTime,lZKeyTime; for(lCount = 0; lCount < max(max(xKeyCount,yKeyCount),zKeyCount); lCount++) { if(lCount<xKeyCount){ lXKeyTime = lAnimCurveX->KeyGetTime(lCount); } if(lCount<yKeyCount){ lYKeyTime = lAnimCurveY->KeyGetTime(lCount); } if(lCount<zKeyCount){ lZKeyTime = lAnimCurveZ->KeyGetTime(lCount); } lKeyTime = min(min(lXKeyTime,lYKeyTime),lZKeyTime); lKeyTime = lXKeyTime; FbxAMatrix & matrix = fbxNode->EvaluateLocalTransform(lKeyTime); ofxFBXKey<ofQuaternion> key; ofVec3f t,s; ofQuaternion so; ofMatrix4x4 m = toOf(matrix); m.decompose(t,key.value,s,so); key.timeMillis = lKeyTime.GetMilliSeconds(); node.rotationKeys.push_back(key); } }
void ofxFBXScene::parsePositionCurve(ofxFBXNode & node, FbxAnimLayer * pAnimLayer, FbxPropertyT<FbxDouble3> &position){ node.originalPosition = toOf(position.Get()); node.getNode().setPosition(node.originalPosition); ofLogVerbose("ofxFBXScene") << "original position " << node.originalPosition << endl; if(!position.GetCurve(pAnimLayer)) return; FbxAnimCurve* lAnimCurveX = position.GetCurve(pAnimLayer,"X"); FbxAnimCurve* lAnimCurveY = position.GetCurve(pAnimLayer,"Y"); FbxAnimCurve* lAnimCurveZ = position.GetCurve(pAnimLayer,"Z"); FbxTime lKeyTime; int lCount; int xKeyCount = lAnimCurveX? lAnimCurveX->KeyGetCount() : 0; int yKeyCount = lAnimCurveY? lAnimCurveY->KeyGetCount() : 0; int zKeyCount = lAnimCurveZ? lAnimCurveZ->KeyGetCount() : 0; ofxFBXKey<float> key; for(lCount = 0; lCount < xKeyCount; lCount++) { key.value = lAnimCurveX->KeyGetValue(lCount); lKeyTime = lAnimCurveX->KeyGetTime(lCount); key.timeMillis = lKeyTime.GetMilliSeconds(); node.xKeys.push_back(key); } for(lCount = 0; lCount < yKeyCount; lCount++) { key.value = lAnimCurveY->KeyGetValue(lCount); lKeyTime = lAnimCurveY->KeyGetTime(lCount); key.timeMillis = lKeyTime.GetMilliSeconds(); node.yKeys.push_back(key); } for(lCount = 0; lCount < zKeyCount; lCount++) { key.value = lAnimCurveZ->KeyGetValue(lCount); lKeyTime = lAnimCurveZ->KeyGetTime(lCount); key.timeMillis = lKeyTime.GetMilliSeconds(); node.zKeys.push_back(key); } }
void readKeys(FbxAnimCurve* curveX, FbxAnimCurve* curveY, FbxAnimCurve* curveZ, const FbxDouble3& defaultValue, std::vector<osgAnimation::Vec3CubicBezierKeyframe>& keyFrameCntr, float scalar = 1.0f) { FbxAnimCurve* curves[3] = {curveX, curveY, curveZ}; typedef std::set<double> TimeSet; typedef std::map<double, osgAnimation::FloatCubicBezier> TimeValueMap; TimeSet times; TimeValueMap curveTimeMap[3]; for (int nCurve = 0; nCurve < 3; ++nCurve) { FbxAnimCurve* pCurve = curves[nCurve]; int nKeys = pCurve ? pCurve->KeyGetCount() : 0; if (!nKeys) { times.insert(0.0); curveTimeMap[nCurve][0.0] = osgAnimation::FloatCubicBezier(defaultValue[nCurve] * scalar); } for (int i = 0; i < nKeys; ++i) { double fTime = pCurve->KeyGetTime(i).GetSecondDouble(); float val = pCurve->KeyGetValue(i); times.insert(fTime); FbxAnimCurveTangentInfo leftTangent = pCurve->KeyGetLeftDerivativeInfo(i); FbxAnimCurveTangentInfo rightTangent = pCurve->KeyGetRightDerivativeInfo(i); if (i > 0) { leftTangent.mDerivative *= fTime - pCurve->KeyGetTime(i - 1).GetSecondDouble(); } if (i + 1 < pCurve->KeyGetCount()) { rightTangent.mDerivative *= pCurve->KeyGetTime(i + 1).GetSecondDouble() - fTime; } osgAnimation::FloatCubicBezier key( val * scalar, (val - leftTangent.mDerivative / 3.0) * scalar, (val + rightTangent.mDerivative / 3.0) * scalar); curveTimeMap[nCurve][fTime] = key; } } for (TimeSet::iterator it = times.begin(); it != times.end(); ++it) { double fTime = *it; osg::Vec3 val, cpIn, cpOut; for (int i = 0; i < 3; ++i) { if (curveTimeMap[i].empty()) continue; TimeValueMap::iterator lb = curveTimeMap[i].lower_bound(fTime); if (lb == curveTimeMap[i].end()) --lb; val[i] = lb->second.getPosition(); cpIn[i] = lb->second.getControlPointIn(); cpOut[i] = lb->second.getControlPointOut(); } keyFrameCntr.push_back(osgAnimation::Vec3CubicBezierKeyframe(fTime, osgAnimation::Vec3CubicBezier(val, cpIn, cpOut))); } }
void readFbxRotationAnimation(osgAnimation::Channel* channels[3], FbxNode* pNode, FbxAnimLayer* pAnimLayer, const char* targetName) { if (!pNode->LclRotation.IsValid()) { return; } EFbxRotationOrder rotOrder = pNode->RotationOrder.IsValid() ? pNode->RotationOrder.Get() : eEulerXYZ; if (pNode->QuaternionInterpolate.IsValid() && pNode->QuaternionInterpolate.Get()) { channels[0] = readFbxChannelsQuat( pNode->LclRotation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_X), pNode->LclRotation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y), pNode->LclRotation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z), pNode->LclRotation.Get(), targetName, rotOrder); } else { const char* curveNames[3] = {FBXSDK_CURVENODE_COMPONENT_X, FBXSDK_CURVENODE_COMPONENT_Y, FBXSDK_CURVENODE_COMPONENT_Z}; FbxDouble3 fbxPropValue = pNode->LclRotation.Get(); fbxPropValue[0] = osg::DegreesToRadians(fbxPropValue[0]); fbxPropValue[1] = osg::DegreesToRadians(fbxPropValue[1]); fbxPropValue[2] = osg::DegreesToRadians(fbxPropValue[2]); for (int i = 0; i < 3; ++i) { FbxAnimCurve* curve = pNode->LclRotation.GetCurve(pAnimLayer, curveNames[i]); if (!curve) { continue; } FbxAnimCurveDef::EInterpolationType interpolationType = FbxAnimCurveDef::eInterpolationConstant; if (curve && curve->KeyGetCount()) interpolationType = curve->KeyGetInterpolation(0); if (interpolationType == FbxAnimCurveDef::eInterpolationCubic) { osgAnimation::FloatCubicBezierKeyframeContainer* pKeyFrameCntr = new osgAnimation::FloatCubicBezierKeyframeContainer; for (int j = 0; j < curve->KeyGetCount(); ++j) { double fTime = curve->KeyGetTime(j).GetSecondDouble(); float angle = curve->KeyGetValue(j); //FbxAnimCurveDef::EWeightedMode tangentWeightMode = curve->KeyGet(j).GetTangentWeightMode(); FbxAnimCurveTangentInfo leftTangent = curve->KeyGetLeftDerivativeInfo(j); FbxAnimCurveTangentInfo rightTangent = curve->KeyGetRightDerivativeInfo(j); if (j > 0) { leftTangent.mDerivative *= fTime - curve->KeyGetTime(j - 1).GetSecondDouble(); } if (j + 1 < curve->KeyGetCount()) { rightTangent.mDerivative *= curve->KeyGetTime(j + 1).GetSecondDouble() - fTime; } osgAnimation::FloatCubicBezier key( osg::DegreesToRadians(angle), osg::DegreesToRadians(angle - leftTangent.mDerivative / 3.0), osg::DegreesToRadians(angle + rightTangent.mDerivative / 3.0)); pKeyFrameCntr->push_back(osgAnimation::FloatCubicBezierKeyframe( fTime, key)); } reorderControlPoints(*pKeyFrameCntr); osgAnimation::FloatCubicBezierChannel* pCubicChannel = new osgAnimation::FloatCubicBezierChannel; pCubicChannel->getOrCreateSampler()->setKeyframeContainer(pKeyFrameCntr); channels[i] = pCubicChannel; } else { osgAnimation::FloatKeyframeContainer* keys = new osgAnimation::FloatKeyframeContainer; for (int j = 0; j < curve->KeyGetCount(); ++j) { FbxAnimCurveKey key = curve->KeyGet(j); keys->push_back(osgAnimation::FloatKeyframe( key.GetTime().GetSecondDouble(), static_cast<float>(osg::DegreesToRadians(key.GetValue())))); } if (interpolationType == FbxAnimCurveDef::eInterpolationConstant) { osgAnimation::FloatStepChannel* pStepChannel = new osgAnimation::FloatStepChannel(); pStepChannel->getOrCreateSampler()->setKeyframeContainer(keys); channels[i] = pStepChannel; } else { osgAnimation::FloatLinearChannel* pLinearChannel = new osgAnimation::FloatLinearChannel(); pLinearChannel->getOrCreateSampler()->setKeyframeContainer(keys); channels[i] = pLinearChannel; } } channels[i]->setTargetName(targetName); channels[i]->setName(std::string("rotate") + curveNames[i]); } } }