Beispiel #1
0
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);
    }
}
// The curve code doesn't differentiate between angles and other data, so an interpolation from 179 to -179
// will cause the bone to rotate all the way around through 0 degrees.  So here we make a second pass over the 
// rotation tracks to convert the angles into a more interpolation-friendly format.  
void FFbxExporter::CorrectAnimTrackInterpolation( TArray<FbxNode*>& BoneNodes, FbxAnimLayer* InAnimLayer )
{
	// Add the animation data to the bone nodes
	for(int32 BoneIndex = 0; BoneIndex < BoneNodes.Num(); ++BoneIndex)
	{
		FbxNode* CurrentBoneNode = BoneNodes[BoneIndex];

		// Fetch the AnimCurves
		FbxAnimCurve* Curves[3];
		Curves[0] = CurrentBoneNode->LclRotation.GetCurve(InAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
		Curves[1] = CurrentBoneNode->LclRotation.GetCurve(InAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
		Curves[2] = CurrentBoneNode->LclRotation.GetCurve(InAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);

		for(int32 CurveIndex = 0; CurveIndex < 3; ++CurveIndex)
		{
			FbxAnimCurve* CurrentCurve = Curves[CurveIndex];

			float CurrentAngleOffset = 0.f;
			for(int32 KeyIndex = 1; KeyIndex < CurrentCurve->KeyGetCount(); ++KeyIndex)
			{
				float PreviousOutVal	= CurrentCurve->KeyGetValue( KeyIndex-1 );
				float CurrentOutVal		= CurrentCurve->KeyGetValue( KeyIndex );

				float DeltaAngle = (CurrentOutVal + CurrentAngleOffset) - PreviousOutVal;

				if(DeltaAngle >= 180)
				{
					CurrentAngleOffset -= 360;
				}
				else if(DeltaAngle <= -180)
				{
					CurrentAngleOffset += 360;
				}

				CurrentOutVal += CurrentAngleOffset;

				CurrentCurve->KeySetValue(KeyIndex, CurrentOutVal);
			}
		}
	}
}
Beispiel #3
0
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)));
    }
}
Beispiel #4
0
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]);
        }
    }
}