void ExportAnimSequenceToFbx(AnimSequence AnimSeq, ref List <FbxNode> BoneNodes, FbxAnimLayer InAnimLayer, float AnimStartOffset, float AnimEndOffset, float AnimPlayRate, float StartTime) { if (AnimSeq.SequenceLength == 0) { return; } FbxTime ExportedStartTime = new FbxTime(); FbxTime ExportedStopTime = new FbxTime(); if (IsNearlyEqual(AnimSeq.FrameRate, DEFAULT_SAMPLERATE, 1.0f)) { FbxTime.SetGlobalTimeMode(FbxTime.EMode.eFrames30); //FbxTime.SetGlobalTimeMode(FbxTime.EMode.eFrames30); } else { FbxTime.SetGlobalTimeMode(FbxTime.EMode.eCustom, AnimSeq.FrameRate); //ExportedStopTime.SetGlobalTimeMode(FbxTime::eCustom, FrameRate); } ExportedStartTime.SetSecondDouble(0.0f); ExportedStopTime.SetSecondDouble(AnimSeq.SequenceLength); FbxTimeSpan ExportedTimeSpan = new FbxTimeSpan(); ExportedTimeSpan.Set(ExportedStartTime, ExportedStopTime); AnimStack.SetLocalTimeSpan(ExportedTimeSpan); // Add the animation data to the bone nodes for (int BoneIndex = 0; BoneIndex < BoneNodes.Count; ++BoneIndex) { FbxNode CurrentBoneNode = BoneNodes[BoneIndex]; // Create the AnimCurves int NumberOfCurves = 9; FbxAnimCurve[] Curves = new FbxAnimCurve[NumberOfCurves]; Curves[0] = CurrentBoneNode.LclTranslation.GetCurve(InAnimLayer, "X", true); Curves[1] = CurrentBoneNode.LclTranslation.GetCurve(InAnimLayer, "Y", true); Curves[2] = CurrentBoneNode.LclTranslation.GetCurve(InAnimLayer, "Z", true); Curves[3] = CurrentBoneNode.LclRotation.GetCurve(InAnimLayer, "X", true); Curves[4] = CurrentBoneNode.LclRotation.GetCurve(InAnimLayer, "Y", true); Curves[5] = CurrentBoneNode.LclRotation.GetCurve(InAnimLayer, "Z", true); Curves[6] = CurrentBoneNode.LclScaling.GetCurve(InAnimLayer, "X", true); Curves[7] = CurrentBoneNode.LclScaling.GetCurve(InAnimLayer, "Y", true); Curves[8] = CurrentBoneNode.LclScaling.GetCurve(InAnimLayer, "Z", true); float AnimTime = AnimStartOffset; float AnimEndTime = (AnimSeq.SequenceLength - AnimEndOffset); // Subtracts 1 because NumFrames includes an initial pose for 0.0 second float TimePerKey = AnimSeq.StepFrame; float AnimTimeIncrement = TimePerKey * AnimPlayRate; FbxTime ExportTime = new FbxTime(); ExportTime.SetSecondDouble(StartTime); FbxTime ExportTimeIncrement = new FbxTime(); ExportTimeIncrement.SetSecondDouble(TimePerKey); //int BoneTreeIndex = Skeleton.GetSkeletonBoneIndexFromMeshBoneIndex(SkelMesh, BoneIndex); //int BoneTrackIndex = Skeleton.GetAnimationTrackIndex(BoneTreeIndex, AnimSeq, true); //if (BoneTrackIndex == INDEX_NONE) //{ // // If this sequence does not have a track for the current bone, then skip it // continue; //} foreach (FbxAnimCurve Curve in Curves) { Curve.KeyModifyBegin(); } bool bLastKey = false; int FrameIndex = 0; foreach (var v in AnimSeq.animationFames) { int lKeyIndex; FrameIndex++; if (FrameIndex == AnimSeq.animationFames.Count) { bLastKey = true; } BoneTransformInfo BoneAtom = v[BoneIndex].BoneTransform; FbxDouble3 Translation = FbxDataConverter.ConvertToFbxPos(BoneAtom.position); FbxDouble3 Rotation = FbxDataConverter.ConvertToFbxRot(BoneAtom.rotation); FbxDouble3 Scale = FbxDataConverter.ConvertToFbxScale(BoneAtom.scale); FbxDouble3 [] Vectors = new FbxDouble3[3] { Translation, Rotation, Scale }; // Loop over each curve and channel to set correct values for (int CurveIndex = 0; CurveIndex < 3; ++CurveIndex) { for (int ChannelIndex = 0; ChannelIndex < 3; ++ChannelIndex) { int OffsetCurveIndex = (CurveIndex * 3) + ChannelIndex; lKeyIndex = Curves[OffsetCurveIndex].KeyAdd(ExportTime); Curves[OffsetCurveIndex].KeySetValue(lKeyIndex, (float)Vectors[CurveIndex].getDataValue(ChannelIndex)); Curves[OffsetCurveIndex].KeySetInterpolation(lKeyIndex, bLastKey ? FbxAnimCurveDef.EInterpolationType.eInterpolationConstant : FbxAnimCurveDef.EInterpolationType.eInterpolationCubic); if (bLastKey) { Curves[OffsetCurveIndex].KeySetConstantMode(lKeyIndex, FbxAnimCurveDef.EConstantMode.eConstantStandard); } } } ExportTime = ExportTime.add(ExportTimeIncrement); } while (!bLastKey) { //FTransform BoneAtom; //AnimSeq.GetBoneTransform(BoneAtom, BoneTrackIndex, AnimTime, true); //FbxVector4 Translation = Converter.ConvertToFbxPos(BoneAtom.GetTranslation()); //FbxVector4 Rotation = Converter.ConvertToFbxRot(BoneAtom.GetRotation().Euler()); //FbxVector4 Scale = Converter.ConvertToFbxScale(BoneAtom.GetScale3D()); //FbxVector4 Vectors[3] = { Translation, Rotation, Scale }; //int lKeyIndex; //bLastKey = AnimTime >= AnimEndTime; //// Loop over each curve and channel to set correct values //for (uint CurveIndex = 0; CurveIndex < 3; ++CurveIndex) //{ // for (uint ChannelIndex = 0; ChannelIndex < 3; ++ChannelIndex) // { // uint OffsetCurveIndex = (CurveIndex * 3) + ChannelIndex; // lKeyIndex = Curves[OffsetCurveIndex].KeyAdd(ExportTime); // Curves[OffsetCurveIndex].KeySetValue(lKeyIndex, Vectors[CurveIndex][ChannelIndex]); // Curves[OffsetCurveIndex].KeySetInterpolation(lKeyIndex, bLastKey ? FbxAnimCurveDef::eInterpolationConstant : FbxAnimCurveDef::eInterpolationCubic); // if (bLastKey) // { // Curves[OffsetCurveIndex].KeySetConstantMode(lKeyIndex, FbxAnimCurveDef::eConstantStandard); // } // } //} //ExportTime += ExportTimeIncrement; //AnimTime += AnimTimeIncrement; } foreach (FbxAnimCurve Curve in Curves) { Curve.KeyModifyEnd(); } } }