Exemple #1
0
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;
}