bool keepTestHorizon( FbxAnimCurve* curve, FbxAnimCurveKey prevkey, FbxAnimCurveKey currkey, FbxAnimCurveKey nextkey) { FbxTime prevt = prevkey.GetTime(); FbxTime currt = currkey.GetTime(); FbxTime nextt = nextkey.GetTime(); bool needit = false; float prevEv; FbxLongLong tmpll = (currt - prevt).GetMilliSeconds() / 3; FbxTime termt; float tmpfs[6] = { -1, }; FbxTime times[6]; for (int termi = 0; termi < 3; termi++) { termt.SetMilliSeconds(tmpll*termi); times[termi] = prevt + termt; } tmpll = (nextt - currt).GetMilliSeconds() / 3; for (int termi = 0; termi < 3; termi++) { termt.SetMilliSeconds(tmpll*termi); times[3 + termi] = currt + termt; } output2 << setw(20 + output2.rdbuf()->in_avail() - 4096) << "timee : "; for (int i = 0; i < 6; i++) { output2 << setw(10) << setiosflags(ios::fixed) << setprecision(3) << (times[i]).GetSecondDouble() << "\t"; tmpfs[i] = curve->Evaluate(times[i]); } output2 << endl << setw(20) << "value : "; for (int i = 0; i < 6; i++) { output2 << setw(10) << setiosflags(ios::fixed) << setprecision(3) << tmpfs[i] << "\t"; } for (int i = 1; i<6;i++) if (abs(tmpfs[i] - tmpfs[i-1]) > comp_level_horizon) { output2 << "keepinHorizon at : " << i << endl; return true; } output2 << endl; return false; }
void readKeys(FbxAnimCurve* curveX, FbxAnimCurve* curveY, FbxAnimCurve* curveZ, const FbxDouble3& defaultValue, std::vector<osgAnimation::TemplateKeyframe<osg::Vec3> >& keyFrameCntr, float scalar = 1.0f) { FbxAnimCurve* curves[3] = {curveX, curveY, curveZ}; typedef std::set<double> TimeSet; typedef std::map<double, float> TimeFloatMap; TimeSet times; TimeFloatMap 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] = defaultValue[nCurve] * scalar; } for (int i = 0; i < nKeys; ++i) { FbxAnimCurveKey key = pCurve->KeyGet(i); double fTime = key.GetTime().GetSecondDouble(); times.insert(fTime); curveTimeMap[nCurve][fTime] = static_cast<float>(key.GetValue()) * scalar; } } for (TimeSet::iterator it = times.begin(); it != times.end(); ++it) { double fTime = *it; osg::Vec3 val; for (int i = 0; i < 3; ++i) { if (curveTimeMap[i].empty()) continue; TimeFloatMap::iterator lb = curveTimeMap[i].lower_bound(fTime); if (lb == curveTimeMap[i].end()) --lb; val[i] = lb->second; } keyFrameCntr.push_back(osgAnimation::Vec3Keyframe(fTime, val)); } }
bool slopkeepTest(FbxAnimCurve* curve, FbxAnimCurveKey prevkey, FbxAnimCurveKey currkey, FbxAnimCurveKey nextkey) { FbxTime prevt = prevkey.GetTime(); FbxTime currt = currkey.GetTime(); FbxTime nextt = nextkey.GetTime(); float slope1 = (currkey.GetValue() - prevkey.GetValue()) / (currt.GetSecondDouble() - prevt.GetSecondDouble()); float slope2 = (nextkey.GetValue() - currkey.GetValue()) / (nextt.GetSecondDouble() - currt.GetSecondDouble()); output2 << setw(20) << "slope : " << setw(10) << setprecision(3) << slope1 << "," << setw(10) << slope2; if (abs(slope1 - slope2) > 0.005) { output2 << " keepinSlope" << endl; return true; } output2 << endl; float deriv1, deriv2, deriv3, deriv4; deriv1 = prevkey.GetDataFloat(FbxAnimCurveDef::EDataIndex::eRightSlope); deriv2 = prevkey.GetDataFloat(FbxAnimCurveDef::EDataIndex::eNextLeftSlope); deriv3 = currkey.GetDataFloat(FbxAnimCurveDef::EDataIndex::eRightSlope); deriv4 = currkey.GetDataFloat(FbxAnimCurveDef::EDataIndex::eNextLeftSlope); FbxTime mili; mili.SetMilliSeconds(1); output3 << "deriv1 : " << deriv1 << ", val : " << prevkey.GetValue() << ", +1mili value : " << curve->EvaluateRightDerivative(prevt + mili) << endl; float derivl11, derivl12, derivl21, derivl22; float derivr11, derivr12, derivr21, derivr22; FbxTime term1, term2; term1.SetSecondDouble((currt.GetSecondDouble() - prevt.GetSecondDouble()) / 3); term2.SetSecondDouble((nextt.GetSecondDouble() - currt.GetSecondDouble()) / 3); derivl11 = curve->EvaluateLeftDerivative(prevt + term1); derivl12 = curve->EvaluateLeftDerivative(prevt + term1 + term1); derivl21 = curve->EvaluateLeftDerivative(currt + term2); derivl22 = curve->EvaluateLeftDerivative(currt + term2 + term2); derivr11 = curve->EvaluateRightDerivative(prevt + term1); derivr12 = curve->EvaluateRightDerivative(prevt + term1 + term1); derivr21 = curve->EvaluateRightDerivative(currt + term2); derivr22 = curve->EvaluateRightDerivative(currt + term2 + term2); output2 << setw(20) << "deriv : " << setprecision(3) << deriv1 <<"," << deriv2 <<"," << deriv3 <<"," << deriv4 <<"," << derivl11<<"," << derivl12<<"," << derivl21<<"," << derivl22<<"," << derivr11<<"," << derivr12<<"," << derivr21<<"," << derivr22<<"," ; if ( prevkey.GetInterpolation() == FbxAnimCurveDef::eInterpolationConstant && currkey.GetInterpolation() == FbxAnimCurveDef::eInterpolationConstant && nextkey.GetInterpolation() == FbxAnimCurveDef::eInterpolationConstant ) { if ( abs(prevkey.GetValue() - currkey.GetValue()) < comp_level_horizon && abs(currkey.GetValue() - nextkey.GetValue()) < comp_level_horizon ) return false; } else if ( prevkey.GetInterpolation() == FbxAnimCurveDef::eInterpolationCubic && currkey.GetInterpolation() == FbxAnimCurveDef::eInterpolationCubic && nextkey.GetInterpolation() == FbxAnimCurveDef::eInterpolationCubic ) { if ( abs(deriv1 - deriv2) < comp_level_deriv && abs(deriv2 - deriv3) < comp_level_deriv && abs(deriv3 - deriv4) < comp_level_deriv ) { float nearCurr = (deriv1*(currt.GetMilliSeconds() - prevt.GetMilliSeconds())) + prevkey.GetValue(); float nearNext = (deriv3*(nextt.GetMilliSeconds() - currt.GetMilliSeconds())) + currkey.GetValue(); if ( abs(nearCurr - currkey.GetValue()) < comp_level_integError && abs(nearNext - nextkey.GetValue()) < comp_level_integError ) return false; } } return true; /* if ( abs(deriv1 - deriv2) < 0.005 && abs(deriv2 - deriv3) < 0.005 && abs(deriv3 - deriv4) < 0.005 && abs(deriv4 - derivl11) < 0.005 && abs(derivl11 - derivr11) < 0.005 && abs(derivr11 - derivl12) < 0.005 && abs(derivl12 - derivr12) < 0.005 && abs(derivr12 - derivl21) < 0.005 && abs(derivl21 - derivr21) < 0.005 && abs(derivr21 - derivl22) < 0.005 && abs(derivl22 - derivr22) < 0.005 ) { } else { output2 << "keepinDeriv" << endl; return true; } output2 << "removable key" << endl; */ return false; }
bool UnFbx::FFbxImporter::ImportCurve(const FbxAnimCurve* FbxCurve, FFloatCurve * Curve, const FbxTimeSpan &AnimTimeSpan, const float ValueScale/*=1.f*/) const { static float DefaultCurveWeight = FbxAnimCurveDef::sDEFAULT_WEIGHT; if ( FbxCurve && Curve ) { for ( int32 KeyIndex=0; KeyIndex<FbxCurve->KeyGetCount(); ++KeyIndex ) { FbxAnimCurveKey Key = FbxCurve->KeyGet(KeyIndex); FbxTime KeyTime = Key.GetTime() - AnimTimeSpan.GetStart(); float Value = Key.GetValue() * ValueScale; FKeyHandle NewKeyHandle = Curve->FloatCurve.AddKey(KeyTime.GetSecondDouble(), Value, true); FbxAnimCurveDef::ETangentMode KeyTangentMode = Key.GetTangentMode(); FbxAnimCurveDef::EInterpolationType KeyInterpMode = Key.GetInterpolation(); FbxAnimCurveDef::EWeightedMode KeyTangentWeightMode = Key.GetTangentWeightMode(); ERichCurveInterpMode NewInterpMode = RCIM_Linear; ERichCurveTangentMode NewTangentMode = RCTM_Auto; ERichCurveTangentWeightMode NewTangentWeightMode = RCTWM_WeightedNone; float LeaveTangent = 0.f; float ArriveTangent = 0.f; float LeaveTangentWeight = 0.f; float ArriveTangentWeight = 0.f; switch (KeyInterpMode) { case FbxAnimCurveDef::eInterpolationConstant://! Constant value until next key. NewInterpMode = RCIM_Constant; break; case FbxAnimCurveDef::eInterpolationLinear://! Linear progression to next key. NewInterpMode = RCIM_Linear; break; case FbxAnimCurveDef::eInterpolationCubic://! Cubic progression to next key. NewInterpMode = RCIM_Cubic; // get tangents { LeaveTangent = Key.GetDataFloat(FbxAnimCurveDef::eRightSlope); if ( KeyIndex > 0 ) { FbxAnimCurveKey PrevKey = FbxCurve->KeyGet(KeyIndex-1); ArriveTangent = PrevKey.GetDataFloat(FbxAnimCurveDef::eNextLeftSlope); } else { ArriveTangent = 0.f; } } break; } // when we import tangent, we only support break or user // since it's modified by DCC and we only assume these two are valid // auto does our own stuff, which doesn't work with what you see in DCC if (KeyTangentMode & FbxAnimCurveDef::eTangentBreak) { NewTangentMode = RCTM_Break; } else { NewTangentMode = RCTM_User; } // @fix me : weight of tangent is not used, but we'll just save this for future where we might use it. switch (KeyTangentWeightMode) { case FbxAnimCurveDef::eWeightedNone://! Tangent has default weights of 0.333; we define this state as not weighted. LeaveTangentWeight = ArriveTangentWeight = DefaultCurveWeight; NewTangentWeightMode = RCTWM_WeightedNone; break; case FbxAnimCurveDef::eWeightedRight: //! Right tangent is weighted. NewTangentWeightMode = RCTWM_WeightedLeave; LeaveTangentWeight = Key.GetDataFloat(FbxAnimCurveDef::eRightWeight); ArriveTangentWeight = DefaultCurveWeight; break; case FbxAnimCurveDef::eWeightedNextLeft://! Left tangent is weighted. NewTangentWeightMode = RCTWM_WeightedArrive; LeaveTangentWeight = DefaultCurveWeight; if ( KeyIndex > 0 ) { FbxAnimCurveKey PrevKey = FbxCurve->KeyGet(KeyIndex-1); ArriveTangentWeight = PrevKey.GetDataFloat(FbxAnimCurveDef::eNextLeftWeight); } else { ArriveTangentWeight = 0.f; } break; case FbxAnimCurveDef::eWeightedAll://! Both left and right tangents are weighted. NewTangentWeightMode = RCTWM_WeightedBoth; LeaveTangentWeight = Key.GetDataFloat(FbxAnimCurveDef::eRightWeight); if ( KeyIndex > 0 ) { FbxAnimCurveKey PrevKey = FbxCurve->KeyGet(KeyIndex-1); ArriveTangentWeight = PrevKey.GetDataFloat(FbxAnimCurveDef::eNextLeftWeight); } else { ArriveTangentWeight = 0.f; } break; } Curve->FloatCurve.SetKeyInterpMode(NewKeyHandle, NewInterpMode); Curve->FloatCurve.SetKeyTangentMode(NewKeyHandle, NewTangentMode); Curve->FloatCurve.SetKeyTangentWeightMode(NewKeyHandle, NewTangentWeightMode); FRichCurveKey& NewKey = Curve->FloatCurve.GetKey(NewKeyHandle); // apply 1/100 - that seems like the tangent unit difference with FBX NewKey.ArriveTangent = ArriveTangent * 0.01f; NewKey.LeaveTangent = LeaveTangent * 0.01f; NewKey.ArriveTangentWeight = ArriveTangentWeight; NewKey.LeaveTangentWeight = LeaveTangentWeight; } return true; } return false; }
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]); } } }