Example #1
0
        public static void ReplaceAnimation(WorkspaceAnimation wsAnimation, List <ImportedFrame> wsSkeleton, reaParser parser, int resampleCount, bool linear, ReplaceAnimationMethod replaceMethod, int insertPos, bool negateQuaternionFlips)
        {
            Report.ReportLog("Replacing animation ...");
            List <KeyValuePair <string, ImportedAnimationSampledTrack> > newTrackList = FbxUtility.CopySampledAnimation(wsAnimation, resampleCount, linear);

            reaANICsection           animationNodeList = parser.ANIC;
            ImportedSampledAnimation iAnim             = new ImportedSampledAnimation();

            iAnim.TrackList = new List <ImportedAnimationSampledTrack>(animationNodeList.Count);
            Dictionary <string, ImportedAnimationSampledTrack> animationNodeDic = null;

            if (replaceMethod != ReplaceAnimationMethod.Replace)
            {
                animationNodeDic = new Dictionary <string, ImportedAnimationSampledTrack>();
                foreach (reaAnimationTrack animationNode in animationNodeList)
                {
                    ImportedFrame boneFrame              = ImportedHelpers.FindFrame(animationNode.boneFrame, wsSkeleton[0]);
                    bool          isTopFrame             = boneFrame != null && boneFrame.Parent == wsSkeleton[0];
                    ImportedAnimationSampledTrack iTrack = Plugins.REMConverter.ConvertTrack(animationNode, isTopFrame);
                    iTrack.Name = animationNode.boneFrame;
                    animationNodeDic.Add(animationNode.boneFrame, iTrack);
                    iAnim.TrackList.Add(iTrack);
                }
            }

            FbxUtility.ReplaceAnimation(replaceMethod, insertPos, newTrackList, iAnim, animationNodeDic, negateQuaternionFlips);

            animationNodeList.ChildList.Clear();
            foreach (var newTrack in iAnim.TrackList)
            {
                ImportedFrame     boneFrame     = ImportedHelpers.FindFrame(newTrack.Name, wsSkeleton[0]);
                bool              isTopFrame    = boneFrame != null && boneFrame.Parent == wsSkeleton[0];
                reaAnimationTrack animationNode = Plugins.REMConverter.ConvertTrack(newTrack, isTopFrame);
                animationNodeList.AddChild(animationNode);
            }
        }
Example #2
0
        public static void ReplaceAnimation(WorkspaceAnimation wsAnimation, xaParser parser, int resampleCount, ReplaceAnimationMethod replaceMethod, int insertPos)
        {
            if (parser.AnimationSection == null)
            {
                Report.ReportLog("The .xa file doesn't have an animation section. Skipping this animation");
                return;
            }
            if (!(wsAnimation.importedAnimation is ImportedKeyframedAnimation))
            {
                Report.ReportLog("The animation has incompatible keyframes.");
                return;
            }

            Report.ReportLog("Replacing animation ...");
            List<ImportedAnimationKeyframedTrack> trackList = ((ImportedKeyframedAnimation)wsAnimation.importedAnimation).TrackList;
            List<KeyValuePair<string, xaAnimationKeyframe[]>> newTrackList = new List<KeyValuePair<string, xaAnimationKeyframe[]>>(trackList.Count);
            List<Tuple<ImportedAnimationTrack, xaAnimationKeyframe[]>> interpolateTracks = new List<Tuple<ImportedAnimationTrack,xaAnimationKeyframe[]>>();
            foreach (var wsTrack in trackList)
            {
                if (!wsAnimation.isTrackEnabled(wsTrack))
                    continue;
                ImportedAnimationKeyframe[] keyframes = ((ImportedAnimationKeyframedTrack)wsTrack).Keyframes;
                xaAnimationKeyframe[] newKeyframes = null;
                int wsTrackKeyframesLength = 0;
                for (int i = 0; i < keyframes.Length; i++)
                {
                    if (keyframes[i] != null)
                        wsTrackKeyframesLength++;
                }
                if (resampleCount < 0 || wsTrackKeyframesLength == resampleCount)
                {
                    newKeyframes = new xaAnimationKeyframe[wsTrackKeyframesLength];
                    int keyframeIdx = 0;
                    for (int i = 0; i < keyframes.Length; i++)
                    {
                        ImportedAnimationKeyframe keyframe = keyframes[i];
                        if (keyframe == null)
                            continue;

                        newKeyframes[keyframeIdx] = new xaAnimationKeyframe();
                        newKeyframes[keyframeIdx].Index = i;
                        newKeyframes[keyframeIdx].Rotation = keyframe.Rotation;
                        xa.CreateUnknowns(newKeyframes[keyframeIdx]);
                        newKeyframes[keyframeIdx].Translation = keyframe.Translation;
                        newKeyframes[keyframeIdx].Scaling = keyframe.Scaling;
                        keyframeIdx++;
                    }
                }
                else
                {
                    newKeyframes = new xaAnimationKeyframe[resampleCount];
                    if (wsTrackKeyframesLength < 1)
                    {
                        xaAnimationKeyframe keyframe = new xaAnimationKeyframe();
                        keyframe.Rotation = Quaternion.Identity;
                        keyframe.Scaling = new Vector3(1, 1, 1);
                        keyframe.Translation = new Vector3(0, 0, 0);
                        xa.CreateUnknowns(keyframe);

                        for (int i = 0; i < newKeyframes.Length; i++)
                        {
                            keyframe.Index = i;
                            newKeyframes[i] = keyframe;
                        }
                    }
                    else
                    {
                        interpolateTracks.Add(new Tuple<ImportedAnimationTrack, xaAnimationKeyframe[]>(wsTrack, newKeyframes));
                    }
                }

                newTrackList.Add(new KeyValuePair<string, xaAnimationKeyframe[]>(wsTrack.Name, newKeyframes));
            }
            if (interpolateTracks.Count > 0)
            {
                Fbx.InterpolateKeyframes(interpolateTracks, resampleCount);
            }

            List<xaAnimationTrack> animationNodeList = parser.AnimationSection.TrackList;
            Dictionary<string, xaAnimationTrack> animationNodeDic = null;
            if (replaceMethod != ReplaceAnimationMethod.Replace)
            {
                animationNodeDic = new Dictionary<string, xaAnimationTrack>();
                foreach (xaAnimationTrack animationNode in animationNodeList)
                {
                    animationNodeDic.Add(animationNode.Name, animationNode);
                }
            }

            if (replaceMethod == ReplaceAnimationMethod.Replace)
            {
                animationNodeList.Clear();
                foreach (var newTrack in newTrackList)
                {
                    xaAnimationTrack animationNode = new xaAnimationTrack();
                    animationNodeList.Add(animationNode);
                    animationNode.KeyframeList = new List<xaAnimationKeyframe>(newTrack.Value);
                    animationNode.Name = newTrack.Key;
                    xa.CreateUnknowns(animationNode);
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.ReplacePresent)
            {
                foreach (var newTrack in newTrackList)
                {
                    xaAnimationTrack animationNode = xa.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, animationNodeList);
                    animationNode.KeyframeList = new List<xaAnimationKeyframe>(newTrack.Value);
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.Merge)
            {
                foreach (var newTrack in newTrackList)
                {
                    xaAnimationTrack animationNode;
                    xaAnimationKeyframe[] origKeyframes = xa.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, animationNodeList, out animationNode);
                    xaAnimationKeyframe[] destKeyframes;
                    int newEnd = insertPos + newTrack.Value.Length;
                    if (origKeyframes.Length < insertPos)
                    {
                        destKeyframes = new xaAnimationKeyframe[newEnd];
                        xa.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, origKeyframes.Length);
                        xa.animationNormalizeTrack(origKeyframes, destKeyframes, insertPos);
                    }
                    else
                    {
                        if (origKeyframes.Length < newEnd)
                        {
                            destKeyframes = new xaAnimationKeyframe[newEnd];
                        }
                        else
                        {
                            destKeyframes = new xaAnimationKeyframe[origKeyframes.Length];
                            xa.animationCopyKeyframeTransformArray(origKeyframes, newEnd, destKeyframes, newEnd, origKeyframes.Length - newEnd);
                        }
                        xa.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, insertPos);
                    }

                    xa.animationCopyKeyframeTransformArray(newTrack.Value, 0, destKeyframes, insertPos, newTrack.Value.Length);
                    animationNode.KeyframeList = new List<xaAnimationKeyframe>(destKeyframes);
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.Insert)
            {
                foreach (var newTrack in newTrackList)
                {
                    xaAnimationTrack animationNode;
                    xaAnimationKeyframe[] origKeyframes = xa.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, animationNodeList, out animationNode); ;
                    xaAnimationKeyframe[] destKeyframes;
                    int newEnd = insertPos + newTrack.Value.Length;
                    if (origKeyframes.Length < insertPos)
                    {
                        destKeyframes = new xaAnimationKeyframe[newEnd];
                        xa.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, origKeyframes.Length);
                        xa.animationNormalizeTrack(origKeyframes, destKeyframes, insertPos);
                    }
                    else
                    {
                        destKeyframes = new xaAnimationKeyframe[origKeyframes.Length + newTrack.Value.Length];
                        xa.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, insertPos);
                        xa.animationCopyKeyframeTransformArray(origKeyframes, insertPos, destKeyframes, newEnd, origKeyframes.Length - insertPos);
                    }

                    xa.animationCopyKeyframeTransformArray(newTrack.Value, 0, destKeyframes, insertPos, newTrack.Value.Length);
                    animationNode.KeyframeList = new List<xaAnimationKeyframe>(destKeyframes);
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.Append)
            {
                int maxKeyframes = 0;
                foreach (xaAnimationTrack animationNode in animationNodeList)
                {
                    int numKeyframes = animationNode.KeyframeList[animationNode.KeyframeList.Count - 1].Index;
                    if (numKeyframes > maxKeyframes)
                    {
                        maxKeyframes = numKeyframes;
                    }
                }

                foreach (var newTrack in newTrackList)
                {
                    xaAnimationTrack animationNode;
                    xaAnimationKeyframe[] origKeyframes = xa.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, animationNodeList, out animationNode);
                    xaAnimationKeyframe[] destKeyframes = new xaAnimationKeyframe[maxKeyframes + insertPos + newTrack.Value[newTrack.Value.Length - 1].Index + 1];
                    xa.animationCopyKeyframeTransformArray(origKeyframes, destKeyframes, 0);
                    if (origKeyframes.Length > 0 && origKeyframes.Length == origKeyframes[origKeyframes.Length - 1].Index + 1)
                    {
                        xa.animationNormalizeTrack(origKeyframes, destKeyframes, origKeyframes.Length + insertPos);
                    }
                    xa.animationCopyKeyframeTransformArray(newTrack.Value, destKeyframes, maxKeyframes + insertPos);
                    animationNode.KeyframeList = new List<xaAnimationKeyframe>(origKeyframes.Length + insertPos + newTrack.Value.Length);
                    for (int i = 0; i < destKeyframes.Length; i++)
                    {
                        if (destKeyframes[i] == null)
                            continue;

                        animationNode.KeyframeList.Add(destKeyframes[i]);
                    }
                }
            }
            else
            {
                Report.ReportLog("Error: Unexpected animation replace method " + replaceMethod + ". Skipping this animation");
                return;
            }
        }
Example #3
0
        public static void ReplaceAnimation(WorkspaceAnimation wsAnimation, odfParser parser, int resampleCount, bool linear, ReplaceAnimationMethod replaceMethod, string clip, int insertPos, bool negateQuaternionFlips)
        {
            if (parser.AnimSection == null)
            {
                Report.ReportLog(Path.GetFileName(parser.ODFPath) + " doesn't have an animation section. Skipping this animation");
                return;
            }
            if (!(wsAnimation.importedAnimation is ImportedKeyframedAnimation))
            {
                Report.ReportLog("The animation has incompatible keyframes.");
                return;
            }

            Report.ReportLog("Replacing animation ...");
            List <KeyValuePair <string, ImportedAnimationKeyframe[]> > newTrackList = FbxUtility.CopyKeyframedAnimation(wsAnimation, resampleCount, linear);

            List <odfTrack>            animationNodeList = odf.FindClip(clip, parser).ChildList;
            ImportedKeyframedAnimation iAnim             = new ImportedKeyframedAnimation();

            iAnim.TrackList = new List <ImportedAnimationKeyframedTrack>(animationNodeList.Count);
            Dictionary <string, ImportedAnimationKeyframedTrack> animationNodeDic = null;

            if (replaceMethod != ReplaceAnimationMethod.Replace)
            {
                animationNodeDic = new Dictionary <string, ImportedAnimationKeyframedTrack>();
                foreach (odfTrack animationNode in animationNodeList)
                {
                    ImportedAnimationKeyframedTrack iTrack = new ImportedAnimationKeyframedTrack();
                    iTrack.Name      = odf.FindFrame(animationNode.BoneFrameId, parser.FrameSection.RootFrame).Name;
                    iTrack.Keyframes = Plugins.ODFConverter.ConvertTrack(animationNode.KeyframeList);
                    animationNodeDic.Add(odf.FindFrame(animationNode.BoneFrameId, parser.FrameSection.RootFrame).Name, iTrack);
                    iAnim.TrackList.Add(iTrack);
                }
            }

            foreach (var newTrack in newTrackList)
            {
                ImportedAnimationKeyframe[] keyframes = newTrack.Value;
                Quaternion q = keyframes[0].Rotation;
                keyframes[0].Rotation *= -1;

/*	if (keyframes[0].Rotation.Angle == 0 || q.Angle == 0)
 *      {
 *              Report.ReportLog("track " + newTrack.Key + " r=" + keyframes[0].Rotation.Angle + " q=" + q.Angle);
 *      }*/
            }
            FbxUtility.ReplaceAnimation(replaceMethod, insertPos, newTrackList, iAnim, animationNodeDic, negateQuaternionFlips);

            animationNodeList.Clear();
            foreach (var newTrack in iAnim.TrackList)
            {
                ImportedAnimationKeyframe[] keyframes = ((ImportedAnimationKeyframedTrack)newTrack).Keyframes;
                odfTrack animationNode = new odfTrack(keyframes.Length);
                odf.CreateUnknowns(animationNode);
                animationNodeList.Add(animationNode);
                animationNode.KeyframeList = Plugins.ODFConverter.ConvertTrack(keyframes);
                animationNode.BoneFrameId  = odf.FindFrame(newTrack.Name, parser.FrameSection.RootFrame).Id;
            }
        }
Example #4
0
        public static void ReplaceAnimation(ReplaceAnimationMethod replaceMethod, int insertPos, List <KeyValuePair <string, ImportedAnimationKeyframe[]> > newTrackList, ImportedAnimation iAnim, Dictionary <string, ImportedAnimationTrack> animationNodeDic, bool negateQuaternionFlips)
        {
            if (replaceMethod == ReplaceAnimationMethod.Replace)
            {
                foreach (var newTrack in newTrackList)
                {
                    ImportedAnimationTrack iTrack = new ImportedAnimationTrack();
                    iAnim.TrackList.Add(iTrack);
                    iTrack.Name      = newTrack.Key;
                    iTrack.Keyframes = newTrack.Value;
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.Merge)
            {
                foreach (var newTrack in newTrackList)
                {
                    ImportedAnimationTrack      animationNode;
                    ImportedAnimationKeyframe[] origKeyframes = FbxUtility.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, iAnim, out animationNode);
                    ImportedAnimationKeyframe[] destKeyframes;
                    int newEnd = insertPos + newTrack.Value.Length;
                    if (origKeyframes.Length < insertPos)
                    {
                        destKeyframes = new ImportedAnimationKeyframe[newEnd];
                        FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, origKeyframes.Length);
                        FbxUtility.animationNormalizeTrack(origKeyframes, destKeyframes, insertPos);
                    }
                    else
                    {
                        if (origKeyframes.Length < newEnd)
                        {
                            destKeyframes = new ImportedAnimationKeyframe[newEnd];
                        }
                        else
                        {
                            destKeyframes = new ImportedAnimationKeyframe[origKeyframes.Length];
                            FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, newEnd, destKeyframes, newEnd, origKeyframes.Length - newEnd);
                        }
                        FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, insertPos);
                    }

                    FbxUtility.animationCopyKeyframeTransformArray(newTrack.Value, 0, destKeyframes, insertPos, newTrack.Value.Length);
                    animationNode.Keyframes = destKeyframes;
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.Insert)
            {
                foreach (var newTrack in newTrackList)
                {
                    ImportedAnimationTrack      animationNode;
                    ImportedAnimationKeyframe[] origKeyframes = FbxUtility.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, iAnim, out animationNode);
                    ImportedAnimationKeyframe[] destKeyframes;
                    int newEnd = insertPos + newTrack.Value.Length;
                    if (origKeyframes.Length < insertPos)
                    {
                        destKeyframes = new ImportedAnimationKeyframe[newEnd];
                        FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, origKeyframes.Length);
                        FbxUtility.animationNormalizeTrack(origKeyframes, destKeyframes, insertPos);
                    }
                    else
                    {
                        destKeyframes = new ImportedAnimationKeyframe[origKeyframes.Length + newTrack.Value.Length];
                        FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, insertPos);
                        FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, insertPos, destKeyframes, newEnd, origKeyframes.Length - insertPos);
                    }

                    FbxUtility.animationCopyKeyframeTransformArray(newTrack.Value, 0, destKeyframes, insertPos, newTrack.Value.Length);
                    animationNode.Keyframes = destKeyframes;
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.Append)
            {
                foreach (var newTrack in newTrackList)
                {
                    ImportedAnimationTrack      animationNode;
                    ImportedAnimationKeyframe[] origKeyframes = FbxUtility.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, iAnim, out animationNode);
                    ImportedAnimationKeyframe[] destKeyframes = new ImportedAnimationKeyframe[origKeyframes.Length + newTrack.Value.Length];
                    FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, origKeyframes.Length);
                    FbxUtility.animationCopyKeyframeTransformArray(newTrack.Value, 0, destKeyframes, origKeyframes.Length, newTrack.Value.Length);
                    animationNode.Keyframes = destKeyframes;
                }
            }
            else
            {
                Report.ReportLog("Error: Unexpected animation replace method " + replaceMethod + ". Skipping this animation");
            }

            if (negateQuaternionFlips)
            {
                foreach (var newTrack in iAnim.TrackList)
                {
                    Quaternion lastQ = Quaternion.Identity;
                    for (int i = 0, lastUsed_keyIndex = -1; i < newTrack.Keyframes.Length; i++)
                    {
                        ImportedAnimationKeyframe iKeyframe = newTrack.Keyframes[i];
                        if (iKeyframe == null)
                        {
                            continue;
                        }

                        Quaternion q = iKeyframe.Rotation;
                        if (lastUsed_keyIndex >= 0)
                        {
                            bool diffX = Math.Sign(lastQ.X) != Math.Sign(q.X);
                            bool diffY = Math.Sign(lastQ.Y) != Math.Sign(q.Y);
                            bool diffZ = Math.Sign(lastQ.Z) != Math.Sign(q.Z);
                            bool diffW = Math.Sign(lastQ.W) != Math.Sign(q.W);
                            if (diffX && diffY && diffZ && diffW)
                            {
                                q.X = -q.X;
                                q.Y = -q.Y;
                                q.Z = -q.Z;
                                q.W = -q.W;

                                iKeyframe.Rotation = q;
                            }
                        }
                        lastQ             = q;
                        lastUsed_keyIndex = i;
                    }
                }
            }
        }
Example #5
0
        public static void ReplaceAnimation(ReplaceAnimationMethod replaceMethod, int insertPos, List<KeyValuePair<string, ImportedAnimationKeyframe[]>> newTrackList, ImportedAnimation iAnim, Dictionary<string, ImportedAnimationTrack> animationNodeDic, bool negateQuaternionFlips)
        {
            if (replaceMethod == ReplaceAnimationMethod.Replace)
            {
                foreach (var newTrack in newTrackList)
                {
                    ImportedAnimationTrack iTrack = new ImportedAnimationTrack();
                    iAnim.TrackList.Add(iTrack);
                    iTrack.Name = newTrack.Key;
                    iTrack.Keyframes = newTrack.Value;
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.Merge)
            {
                foreach (var newTrack in newTrackList)
                {
                    ImportedAnimationTrack animationNode;
                    ImportedAnimationKeyframe[] origKeyframes = FbxUtility.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, iAnim, out animationNode);
                    ImportedAnimationKeyframe[] destKeyframes;
                    int newEnd = insertPos + newTrack.Value.Length;
                    if (origKeyframes.Length < insertPos)
                    {
                        destKeyframes = new ImportedAnimationKeyframe[newEnd];
                        FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, origKeyframes.Length);
                        FbxUtility.animationNormalizeTrack(origKeyframes, destKeyframes, insertPos);
                    }
                    else
                    {
                        if (origKeyframes.Length < newEnd)
                        {
                            destKeyframes = new ImportedAnimationKeyframe[newEnd];
                        }
                        else
                        {
                            destKeyframes = new ImportedAnimationKeyframe[origKeyframes.Length];
                            FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, newEnd, destKeyframes, newEnd, origKeyframes.Length - newEnd);
                        }
                        FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, insertPos);
                    }

                    FbxUtility.animationCopyKeyframeTransformArray(newTrack.Value, 0, destKeyframes, insertPos, newTrack.Value.Length);
                    animationNode.Keyframes = destKeyframes;
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.Insert)
            {
                foreach (var newTrack in newTrackList)
                {
                    ImportedAnimationTrack animationNode;
                    ImportedAnimationKeyframe[] origKeyframes = FbxUtility.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, iAnim, out animationNode);
                    ImportedAnimationKeyframe[] destKeyframes;
                    int newEnd = insertPos + newTrack.Value.Length;
                    if (origKeyframes.Length < insertPos)
                    {
                        destKeyframes = new ImportedAnimationKeyframe[newEnd];
                        FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, origKeyframes.Length);
                        FbxUtility.animationNormalizeTrack(origKeyframes, destKeyframes, insertPos);
                    }
                    else
                    {
                        destKeyframes = new ImportedAnimationKeyframe[origKeyframes.Length + newTrack.Value.Length];
                        FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, insertPos);
                        FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, insertPos, destKeyframes, newEnd, origKeyframes.Length - insertPos);
                    }

                    FbxUtility.animationCopyKeyframeTransformArray(newTrack.Value, 0, destKeyframes, insertPos, newTrack.Value.Length);
                    animationNode.Keyframes = destKeyframes;
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.Append)
            {
                foreach (var newTrack in newTrackList)
                {
                    ImportedAnimationTrack animationNode;
                    ImportedAnimationKeyframe[] origKeyframes = FbxUtility.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, iAnim, out animationNode);
                    ImportedAnimationKeyframe[] destKeyframes = new ImportedAnimationKeyframe[origKeyframes.Length + newTrack.Value.Length];
                    FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, origKeyframes.Length);
                    FbxUtility.animationCopyKeyframeTransformArray(newTrack.Value, 0, destKeyframes, origKeyframes.Length, newTrack.Value.Length);
                    animationNode.Keyframes = destKeyframes;
                }
            }
            else
            {
                Report.ReportLog("Error: Unexpected animation replace method " + replaceMethod + ". Skipping this animation");
            }

            if (negateQuaternionFlips)
            {
                foreach (var newTrack in iAnim.TrackList)
                {
                    Quaternion lastQ = Quaternion.Identity;
                    for (int i = 0, lastUsed_keyIndex = -1; i < newTrack.Keyframes.Length; i++)
                    {
                        ImportedAnimationKeyframe iKeyframe = newTrack.Keyframes[i];
                        if (iKeyframe == null)
                            continue;

                        Quaternion q = iKeyframe.Rotation;
                        if (lastUsed_keyIndex >= 0)
                        {
                            bool diffX = Math.Sign(lastQ.X) != Math.Sign(q.X);
                            bool diffY = Math.Sign(lastQ.Y) != Math.Sign(q.Y);
                            bool diffZ = Math.Sign(lastQ.Z) != Math.Sign(q.Z);
                            bool diffW = Math.Sign(lastQ.W) != Math.Sign(q.W);
                            if (diffX && diffY && diffZ && diffW)
                            {
                                q.X = -q.X;
                                q.Y = -q.Y;
                                q.Z = -q.Z;
                                q.W = -q.W;

                                iKeyframe.Rotation = q;
                            }
                        }
                        lastQ = q;
                        lastUsed_keyIndex = i;
                    }
                }
            }
        }
Example #6
0
        public static void ReplaceAnimation(WorkspaceAnimation wsAnimation, xaParser parser, int resampleCount, ReplaceAnimationMethod replaceMethod, int insertPos)
        {
            if (parser.AnimationSection == null)
            {
                Report.ReportLog("The .xa file doesn't have an animation section. Skipping this animation");
                return;
            }
            if (!(wsAnimation.importedAnimation is ImportedKeyframedAnimation))
            {
                Report.ReportLog("The animation has incompatible keyframes.");
                return;
            }

            Report.ReportLog("Replacing animation ...");
            List <ImportedAnimationKeyframedTrack> trackList = ((ImportedKeyframedAnimation)wsAnimation.importedAnimation).TrackList;
            List <KeyValuePair <string, xaAnimationKeyframe[]> >          newTrackList      = new List <KeyValuePair <string, xaAnimationKeyframe[]> >(trackList.Count);
            List <Tuple <ImportedAnimationTrack, xaAnimationKeyframe[]> > interpolateTracks = new List <Tuple <ImportedAnimationTrack, xaAnimationKeyframe[]> >();

            foreach (var wsTrack in trackList)
            {
                if (!wsAnimation.isTrackEnabled(wsTrack))
                {
                    continue;
                }
                ImportedAnimationKeyframe[] keyframes    = ((ImportedAnimationKeyframedTrack)wsTrack).Keyframes;
                xaAnimationKeyframe[]       newKeyframes = null;
                int wsTrackKeyframesLength = 0;
                for (int i = 0; i < keyframes.Length; i++)
                {
                    if (keyframes[i] != null)
                    {
                        wsTrackKeyframesLength++;
                    }
                }
                if (resampleCount < 0 || wsTrackKeyframesLength == resampleCount)
                {
                    newKeyframes = new xaAnimationKeyframe[wsTrackKeyframesLength];
                    int keyframeIdx = 0;
                    for (int i = 0; i < keyframes.Length; i++)
                    {
                        ImportedAnimationKeyframe keyframe = keyframes[i];
                        if (keyframe == null)
                        {
                            continue;
                        }

                        newKeyframes[keyframeIdx]          = new xaAnimationKeyframe();
                        newKeyframes[keyframeIdx].Index    = i;
                        newKeyframes[keyframeIdx].Rotation = keyframe.Rotation;
                        xa.CreateUnknowns(newKeyframes[keyframeIdx]);
                        newKeyframes[keyframeIdx].Translation = keyframe.Translation;
                        newKeyframes[keyframeIdx].Scaling     = keyframe.Scaling;
                        keyframeIdx++;
                    }
                }
                else
                {
                    newKeyframes = new xaAnimationKeyframe[resampleCount];
                    if (wsTrackKeyframesLength < 1)
                    {
                        xaAnimationKeyframe keyframe = new xaAnimationKeyframe();
                        keyframe.Rotation    = Quaternion.Identity;
                        keyframe.Scaling     = new Vector3(1, 1, 1);
                        keyframe.Translation = new Vector3(0, 0, 0);
                        xa.CreateUnknowns(keyframe);

                        for (int i = 0; i < newKeyframes.Length; i++)
                        {
                            keyframe.Index  = i;
                            newKeyframes[i] = keyframe;
                        }
                    }
                    else
                    {
                        interpolateTracks.Add(new Tuple <ImportedAnimationTrack, xaAnimationKeyframe[]>(wsTrack, newKeyframes));
                    }
                }

                newTrackList.Add(new KeyValuePair <string, xaAnimationKeyframe[]>(wsTrack.Name, newKeyframes));
            }
            if (interpolateTracks.Count > 0)
            {
                Fbx.InterpolateKeyframes(interpolateTracks, resampleCount);
            }

            List <xaAnimationTrack> animationNodeList = parser.AnimationSection.TrackList;
            Dictionary <string, xaAnimationTrack> animationNodeDic = null;

            if (replaceMethod != ReplaceAnimationMethod.Replace)
            {
                animationNodeDic = new Dictionary <string, xaAnimationTrack>();
                foreach (xaAnimationTrack animationNode in animationNodeList)
                {
                    animationNodeDic.Add(animationNode.Name, animationNode);
                }
            }

            if (replaceMethod == ReplaceAnimationMethod.Replace)
            {
                animationNodeList.Clear();
                foreach (var newTrack in newTrackList)
                {
                    xaAnimationTrack animationNode = new xaAnimationTrack();
                    animationNodeList.Add(animationNode);
                    animationNode.KeyframeList = new List <xaAnimationKeyframe>(newTrack.Value);
                    animationNode.Name         = newTrack.Key;
                    xa.CreateUnknowns(animationNode);
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.ReplacePresent)
            {
                foreach (var newTrack in newTrackList)
                {
                    xaAnimationTrack animationNode = xa.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, animationNodeList);
                    animationNode.KeyframeList = new List <xaAnimationKeyframe>(newTrack.Value);
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.Merge)
            {
                foreach (var newTrack in newTrackList)
                {
                    xaAnimationTrack      animationNode;
                    xaAnimationKeyframe[] origKeyframes = xa.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, animationNodeList, out animationNode);
                    xaAnimationKeyframe[] destKeyframes;
                    int newEnd = insertPos + newTrack.Value.Length;
                    if (origKeyframes.Length < insertPos)
                    {
                        destKeyframes = new xaAnimationKeyframe[newEnd];
                        xa.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, origKeyframes.Length);
                        xa.animationNormalizeTrack(origKeyframes, destKeyframes, insertPos);
                    }
                    else
                    {
                        if (origKeyframes.Length < newEnd)
                        {
                            destKeyframes = new xaAnimationKeyframe[newEnd];
                        }
                        else
                        {
                            destKeyframes = new xaAnimationKeyframe[origKeyframes.Length];
                            xa.animationCopyKeyframeTransformArray(origKeyframes, newEnd, destKeyframes, newEnd, origKeyframes.Length - newEnd);
                        }
                        xa.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, insertPos);
                    }

                    xa.animationCopyKeyframeTransformArray(newTrack.Value, 0, destKeyframes, insertPos, newTrack.Value.Length);
                    animationNode.KeyframeList = new List <xaAnimationKeyframe>(destKeyframes);
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.Insert)
            {
                foreach (var newTrack in newTrackList)
                {
                    xaAnimationTrack      animationNode;
                    xaAnimationKeyframe[] origKeyframes = xa.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, animationNodeList, out animationNode);;
                    xaAnimationKeyframe[] destKeyframes;
                    int newEnd = insertPos + newTrack.Value.Length;
                    if (origKeyframes.Length < insertPos)
                    {
                        destKeyframes = new xaAnimationKeyframe[newEnd];
                        xa.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, origKeyframes.Length);
                        xa.animationNormalizeTrack(origKeyframes, destKeyframes, insertPos);
                    }
                    else
                    {
                        destKeyframes = new xaAnimationKeyframe[origKeyframes.Length + newTrack.Value.Length];
                        xa.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, insertPos);
                        xa.animationCopyKeyframeTransformArray(origKeyframes, insertPos, destKeyframes, newEnd, origKeyframes.Length - insertPos);
                    }

                    xa.animationCopyKeyframeTransformArray(newTrack.Value, 0, destKeyframes, insertPos, newTrack.Value.Length);
                    animationNode.KeyframeList = new List <xaAnimationKeyframe>(destKeyframes);
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.Append)
            {
                int maxKeyframes = 0;
                foreach (xaAnimationTrack animationNode in animationNodeList)
                {
                    int numKeyframes = animationNode.KeyframeList[animationNode.KeyframeList.Count - 1].Index;
                    if (numKeyframes > maxKeyframes)
                    {
                        maxKeyframes = numKeyframes;
                    }
                }

                foreach (var newTrack in newTrackList)
                {
                    xaAnimationTrack      animationNode;
                    xaAnimationKeyframe[] origKeyframes = xa.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, animationNodeList, out animationNode);
                    xaAnimationKeyframe[] destKeyframes = new xaAnimationKeyframe[maxKeyframes + insertPos + newTrack.Value[newTrack.Value.Length - 1].Index + 1];
                    xa.animationCopyKeyframeTransformArray(origKeyframes, destKeyframes, 0);
                    if (origKeyframes.Length > 0 && origKeyframes.Length == origKeyframes[origKeyframes.Length - 1].Index + 1)
                    {
                        xa.animationNormalizeTrack(origKeyframes, destKeyframes, origKeyframes.Length + insertPos);
                    }
                    xa.animationCopyKeyframeTransformArray(newTrack.Value, destKeyframes, maxKeyframes + insertPos);
                    animationNode.KeyframeList = new List <xaAnimationKeyframe>(origKeyframes.Length + insertPos + newTrack.Value.Length);
                    for (int i = 0; i < destKeyframes.Length; i++)
                    {
                        if (destKeyframes[i] == null)
                        {
                            continue;
                        }

                        animationNode.KeyframeList.Add(destKeyframes[i]);
                    }
                }
            }
            else
            {
                Report.ReportLog("Error: Unexpected animation replace method " + replaceMethod + ". Skipping this animation");
                return;
            }
        }
Example #7
0
File: Fbx.cs Project: kkdevs/sb3u
        public static void ReplaceAnimation(ReplaceAnimationMethod replaceMethod, int insertPos, List <KeyValuePair <string, ImportedAnimationSampledTrack> > newTrackList, ImportedSampledAnimation iAnim, Dictionary <string, ImportedAnimationSampledTrack> animationNodeDic, bool negateQuaternions, float filterTolerance)
        {
            if (replaceMethod == ReplaceAnimationMethod.Replace)
            {
                foreach (var newTrack in newTrackList)
                {
                    ImportedAnimationSampledTrack iTrack = new ImportedAnimationSampledTrack();
                    iAnim.TrackList.Add(iTrack);
                    iTrack.Name         = newTrack.Key;
                    iTrack.Scalings     = newTrack.Value.Scalings;
                    iTrack.Rotations    = newTrack.Value.Rotations;
                    iTrack.Translations = newTrack.Value.Translations;
                    iTrack.Curve        = newTrack.Value.Curve;
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.ReplacePresent)
            {
                foreach (var newTrack in newTrackList)
                {
                    ImportedAnimationSampledTrack animationNode = animationGetOriginalSamples(animationNodeDic, newTrack.Key, iAnim.TrackList);
                    animationNode.Scalings     = newTrack.Value.Scalings;
                    animationNode.Rotations    = newTrack.Value.Rotations;
                    animationNode.Translations = newTrack.Value.Translations;
                    animationNode.Curve        = newTrack.Value.Curve;
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.Merge)
            {
                foreach (var newTrack in newTrackList)
                {
                    ImportedAnimationSampledTrack animationNode;
                    ImportedAnimationSampledTrack origSamples = animationGetOriginalSamples(animationNodeDic, newTrack.Key, iAnim, out animationNode);
                    ImportedAnimationSampledTrack destSamples;
                    int newEnd = insertPos + newTrack.Value.Scalings.Length;
                    if (origSamples.Scalings.Length < insertPos)
                    {
                        destSamples              = new ImportedAnimationSampledTrack();
                        destSamples.Scalings     = new Vector3?[newEnd];
                        destSamples.Rotations    = new Quaternion?[newEnd];
                        destSamples.Translations = new Vector3?[newEnd];
                        destSamples.Curve        = new float?[newEnd];
                        animationCopySampleTransformArray(origSamples, 0, destSamples, 0, origSamples.Scalings.Length);
                        animationNormalizeTrack(origSamples, destSamples, insertPos);
                    }
                    else
                    {
                        if (origSamples.Scalings.Length < newEnd)
                        {
                            destSamples              = new ImportedAnimationSampledTrack();
                            destSamples.Scalings     = new Vector3?[newEnd];
                            destSamples.Rotations    = new Quaternion?[newEnd];
                            destSamples.Translations = new Vector3?[newEnd];
                            destSamples.Curve        = new float?[newEnd];
                        }
                        else
                        {
                            destSamples              = new ImportedAnimationSampledTrack();
                            destSamples.Scalings     = new Vector3?[origSamples.Scalings.Length];
                            destSamples.Rotations    = new Quaternion?[origSamples.Rotations.Length];
                            destSamples.Translations = new Vector3?[origSamples.Translations.Length];
                            destSamples.Curve        = new float?[origSamples.Curve.Length];
                            animationCopySampleTransformArray(origSamples, newEnd, destSamples, newEnd, origSamples.Scalings.Length - newEnd);
                        }
                        animationCopySampleTransformArray(origSamples, 0, destSamples, 0, insertPos);
                    }

                    animationCopySampleTransformArray(newTrack.Value, 0, destSamples, insertPos, newTrack.Value.Scalings.Length);
                    animationNode.Scalings     = destSamples.Scalings;
                    animationNode.Rotations    = destSamples.Rotations;
                    animationNode.Translations = destSamples.Translations;
                    animationNode.Curve        = destSamples.Curve;
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.Insert)
            {
                foreach (var newTrack in newTrackList)
                {
                    ImportedAnimationSampledTrack animationNode;
                    ImportedAnimationSampledTrack origSamples = animationGetOriginalSamples(animationNodeDic, newTrack.Key, iAnim, out animationNode);
                    ImportedAnimationSampledTrack destSamples;
                    int newEnd = insertPos + newTrack.Value.Scalings.Length;
                    if (origSamples.Scalings.Length < insertPos)
                    {
                        destSamples              = new ImportedAnimationSampledTrack();
                        destSamples.Scalings     = new Vector3?[newEnd];
                        destSamples.Rotations    = new Quaternion?[newEnd];
                        destSamples.Translations = new Vector3?[newEnd];
                        destSamples.Curve        = new float?[newEnd];
                        animationCopySampleTransformArray(origSamples, 0, destSamples, 0, origSamples.Scalings.Length);
                        animationNormalizeTrack(origSamples, destSamples, insertPos);
                    }
                    else
                    {
                        destSamples              = new ImportedAnimationSampledTrack();
                        destSamples.Scalings     = new Vector3?[origSamples.Scalings.Length + newTrack.Value.Scalings.Length];
                        destSamples.Rotations    = new Quaternion?[origSamples.Rotations.Length + newTrack.Value.Rotations.Length];
                        destSamples.Translations = new Vector3?[origSamples.Translations.Length + newTrack.Value.Translations.Length];
                        destSamples.Curve        = new float?[origSamples.Curve.Length + newTrack.Value.Curve.Length];
                        animationCopySampleTransformArray(origSamples, 0, destSamples, 0, insertPos);
                        animationCopySampleTransformArray(origSamples, insertPos, destSamples, newEnd, origSamples.Scalings.Length - insertPos);
                    }

                    animationCopySampleTransformArray(newTrack.Value, 0, destSamples, insertPos, newTrack.Value.Scalings.Length);
                    animationNode.Scalings     = destSamples.Scalings;
                    animationNode.Rotations    = destSamples.Rotations;
                    animationNode.Translations = destSamples.Translations;
                    animationNode.Curve        = destSamples.Curve;
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.Append)
            {
                foreach (var newTrack in newTrackList)
                {
                    ImportedAnimationSampledTrack animationNode;
                    ImportedAnimationSampledTrack origSamples = animationGetOriginalSamples(animationNodeDic, newTrack.Key, iAnim, out animationNode);
                    ImportedAnimationSampledTrack destSamples = new ImportedAnimationSampledTrack();
                    destSamples.Scalings     = new Vector3?[origSamples.Scalings.Length + insertPos + newTrack.Value.Scalings.Length];
                    destSamples.Rotations    = new Quaternion?[origSamples.Rotations.Length + insertPos + newTrack.Value.Rotations.Length];
                    destSamples.Translations = new Vector3?[origSamples.Translations.Length + insertPos + newTrack.Value.Translations.Length];
                    destSamples.Curve        = new float?[origSamples.Curve.Length + insertPos + newTrack.Value.Curve.Length];
                    animationCopySampleTransformArray(origSamples, destSamples, 0);
                    bool reduced = false;
                    for (int i = 0; i < origSamples.Scalings.Length; i++)
                    {
                        if (origSamples.Scalings[i] == null)
                        {
                            reduced = true;
                            break;
                        }
                    }
                    if (origSamples.Scalings.Length > 0 && !reduced)
                    {
                        animationNormalizeTrack(origSamples, destSamples, origSamples.Scalings.Length + insertPos);
                    }
                    animationCopySampleTransformArray(newTrack.Value, destSamples, origSamples.Scalings.Length + insertPos);
                    animationNode.Scalings     = destSamples.Scalings;
                    animationNode.Rotations    = destSamples.Rotations;
                    animationNode.Translations = destSamples.Translations;
                    animationNode.Curve        = destSamples.Curve;
                }
            }
            else
            {
                Report.ReportLog("Error: Unexpected animation replace method " + replaceMethod + ". Skipping this animation");
                return;
            }

            if (negateQuaternions)
            {
                float thresholdPos = 180.0f - filterTolerance;
                float thresholdNeg = -180.0f + filterTolerance;
                foreach (var newTrack in iAnim.TrackList)
                {
                    if (newTrack.Rotations == null)
                    {
                        continue;
                    }
                    Quaternion lastQ = Quaternion.Identity;
                    Vector3    lastE = Vector3.Zero;
                    Vector3    diffE = Vector3.Zero;
                    bool       flip  = false;
                    for (int i = 0, lastUsed_keyIndex = -1; i < newTrack.Rotations.Length; i++)
                    {
                        if (newTrack.Rotations[i] == null)
                        {
                            continue;
                        }

                        Quaternion q = newTrack.Rotations[i].Value;
                        Vector3    e = FbxUtility.QuaternionToEuler(q);
                        if (lastUsed_keyIndex >= 0)
                        {
                            if (lastE.X - diffE.X > thresholdPos && e.X < thresholdNeg)
                            {
                                diffE.X += 360;
                                flip    ^= true;
                            }
                            else if (lastE.X - diffE.X < thresholdNeg && e.X > thresholdPos)
                            {
                                diffE.X -= 360;
                                flip    ^= true;
                            }
                            e.X += diffE.X;

                            if (lastE.Y - diffE.Y > thresholdPos && e.Y < thresholdNeg)
                            {
                                diffE.Y += 360;
                                flip    ^= true;
                            }
                            else if (lastE.Y - diffE.Y < thresholdNeg && e.Y > thresholdPos)
                            {
                                diffE.Y -= 360;
                                flip    ^= true;
                            }
                            e.Y += diffE.Y;

                            if (lastE.Z - diffE.Z > thresholdPos && e.Z < thresholdNeg)
                            {
                                diffE.Z += 360;
                                flip    ^= true;
                            }
                            else if (lastE.Z - diffE.Z < thresholdNeg && e.Z > thresholdPos)
                            {
                                diffE.Z -= 360;
                                flip    ^= true;
                            }
                            e.Z += diffE.Z;

                            if (flip)
                            {
                                q.X = -q.X;
                                q.Y = -q.Y;
                                q.Z = -q.Z;
                                q.W = -q.W;

                                newTrack.Rotations[i] = q;
                            }

                            bool diffX = Math.Sign(lastQ.X) != Math.Sign(q.X);
                            bool diffY = Math.Sign(lastQ.Y) != Math.Sign(q.Y);
                            bool diffZ = Math.Sign(lastQ.Z) != Math.Sign(q.Z);
                            bool diffW = Math.Sign(lastQ.W) != Math.Sign(q.W);
                            if ((diffX || diffY || diffZ) && diffW)
                            {
                                q.X = -q.X;
                                q.Y = -q.Y;
                                q.Z = -q.Z;
                                q.W = -q.W;

                                newTrack.Rotations[i] = q;
                            }
                        }
                        lastQ             = q;
                        lastE             = e;
                        lastUsed_keyIndex = i;
                    }
                }
            }
        }
Example #8
0
        public static void ReplaceAnimation(ReplaceAnimationMethod replaceMethod, int insertPos, List <KeyValuePair <string, ImportedAnimationSampledTrack> > newTrackList, ImportedSampledAnimation iAnim, Dictionary <string, ImportedAnimationSampledTrack> animationNodeDic, bool negateQuaternionFlips)
        {
            if (replaceMethod == ReplaceAnimationMethod.Replace)
            {
                foreach (var newTrack in newTrackList)
                {
                    ImportedAnimationSampledTrack iTrack = new ImportedAnimationSampledTrack();
                    iAnim.TrackList.Add(iTrack);
                    iTrack.Name         = newTrack.Key;
                    iTrack.Scalings     = newTrack.Value.Scalings;
                    iTrack.Rotations    = newTrack.Value.Rotations;
                    iTrack.Translations = newTrack.Value.Translations;
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.ReplacePresent)
            {
                foreach (var newTrack in newTrackList)
                {
                    ImportedAnimationSampledTrack animationNode = animationGetOriginalSamples(animationNodeDic, newTrack.Key, iAnim.TrackList);
                    animationNode.Scalings     = newTrack.Value.Scalings;
                    animationNode.Rotations    = newTrack.Value.Rotations;
                    animationNode.Translations = newTrack.Value.Translations;
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.Merge)
            {
                foreach (var newTrack in newTrackList)
                {
                    ImportedAnimationSampledTrack animationNode;
                    ImportedAnimationSampledTrack origSamples = animationGetOriginalSamples(animationNodeDic, newTrack.Key, iAnim, out animationNode);
                    ImportedAnimationSampledTrack destSamples;
                    int newEnd = insertPos + newTrack.Value.Scalings.Length;
                    if (origSamples.Scalings.Length < insertPos)
                    {
                        destSamples              = new ImportedAnimationSampledTrack();
                        destSamples.Scalings     = new Vector3?[newEnd];
                        destSamples.Rotations    = new Quaternion?[newEnd];
                        destSamples.Translations = new Vector3?[newEnd];
                        animationCopySampleTransformArray(origSamples, 0, destSamples, 0, origSamples.Scalings.Length);
                        animationNormalizeTrack(origSamples, destSamples, insertPos);
                    }
                    else
                    {
                        if (origSamples.Scalings.Length < newEnd)
                        {
                            destSamples              = new ImportedAnimationSampledTrack();
                            destSamples.Scalings     = new Vector3?[newEnd];
                            destSamples.Rotations    = new Quaternion?[newEnd];
                            destSamples.Translations = new Vector3?[newEnd];
                        }
                        else
                        {
                            destSamples              = new ImportedAnimationSampledTrack();
                            destSamples.Scalings     = new Vector3?[origSamples.Scalings.Length];
                            destSamples.Rotations    = new Quaternion?[origSamples.Rotations.Length];
                            destSamples.Translations = new Vector3?[origSamples.Translations.Length];
                            animationCopySampleTransformArray(origSamples, newEnd, destSamples, newEnd, origSamples.Scalings.Length - newEnd);
                        }
                        animationCopySampleTransformArray(origSamples, 0, destSamples, 0, insertPos);
                    }

                    animationCopySampleTransformArray(newTrack.Value, 0, destSamples, insertPos, newTrack.Value.Scalings.Length);
                    animationNode.Scalings     = destSamples.Scalings;
                    animationNode.Rotations    = destSamples.Rotations;
                    animationNode.Translations = destSamples.Translations;
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.Insert)
            {
                foreach (var newTrack in newTrackList)
                {
                    ImportedAnimationSampledTrack animationNode;
                    ImportedAnimationSampledTrack origSamples = animationGetOriginalSamples(animationNodeDic, newTrack.Key, iAnim, out animationNode);
                    ImportedAnimationSampledTrack destSamples;
                    int newEnd = insertPos + newTrack.Value.Scalings.Length;
                    if (origSamples.Scalings.Length < insertPos)
                    {
                        destSamples              = new ImportedAnimationSampledTrack();
                        destSamples.Scalings     = new Vector3?[newEnd];
                        destSamples.Rotations    = new Quaternion?[newEnd];
                        destSamples.Translations = new Vector3?[newEnd];
                        animationCopySampleTransformArray(origSamples, 0, destSamples, 0, origSamples.Scalings.Length);
                        animationNormalizeTrack(origSamples, destSamples, insertPos);
                    }
                    else
                    {
                        destSamples              = new ImportedAnimationSampledTrack();
                        destSamples.Scalings     = new Vector3?[origSamples.Scalings.Length + newTrack.Value.Scalings.Length];
                        destSamples.Rotations    = new Quaternion?[origSamples.Rotations.Length + newTrack.Value.Rotations.Length];
                        destSamples.Translations = new Vector3?[origSamples.Translations.Length + newTrack.Value.Translations.Length];
                        animationCopySampleTransformArray(origSamples, 0, destSamples, 0, insertPos);
                        animationCopySampleTransformArray(origSamples, insertPos, destSamples, newEnd, origSamples.Scalings.Length - insertPos);
                    }

                    animationCopySampleTransformArray(newTrack.Value, 0, destSamples, insertPos, newTrack.Value.Scalings.Length);
                    animationNode.Scalings     = destSamples.Scalings;
                    animationNode.Rotations    = destSamples.Rotations;
                    animationNode.Translations = destSamples.Translations;
                }
            }
            else if (replaceMethod == ReplaceAnimationMethod.Append)
            {
                foreach (var newTrack in newTrackList)
                {
                    ImportedAnimationSampledTrack animationNode;
                    ImportedAnimationSampledTrack origSamples = animationGetOriginalSamples(animationNodeDic, newTrack.Key, iAnim, out animationNode);
                    ImportedAnimationSampledTrack destSamples = new ImportedAnimationSampledTrack();
                    destSamples.Scalings     = new Vector3?[origSamples.Scalings.Length + insertPos + newTrack.Value.Scalings.Length];
                    destSamples.Rotations    = new Quaternion?[origSamples.Rotations.Length + insertPos + newTrack.Value.Rotations.Length];
                    destSamples.Translations = new Vector3?[origSamples.Translations.Length + insertPos + newTrack.Value.Translations.Length];
                    animationCopySampleTransformArray(origSamples, destSamples, 0);
                    bool reduced = false;
                    for (int i = 0; i < origSamples.Scalings.Length; i++)
                    {
                        if (origSamples.Scalings[i] == null)
                        {
                            reduced = true;
                            break;
                        }
                    }
                    if (origSamples.Scalings.Length > 0 && !reduced)
                    {
                        animationNormalizeTrack(origSamples, destSamples, origSamples.Scalings.Length + insertPos);
                    }
                    animationCopySampleTransformArray(newTrack.Value, destSamples, origSamples.Scalings.Length + insertPos);
                    animationNode.Scalings     = destSamples.Scalings;
                    animationNode.Rotations    = destSamples.Rotations;
                    animationNode.Translations = destSamples.Translations;
                }
            }
            else
            {
                Report.ReportLog("Error: Unexpected animation replace method " + replaceMethod + ". Skipping this animation");
                return;
            }

            if (negateQuaternionFlips)
            {
                foreach (var newTrack in iAnim.TrackList)
                {
                    ImportedAnimationSampledTrack keyframes = newTrack;
                    Quaternion lastQ = Quaternion.Identity;
                    for (int i = 0, lastUsed_keyIndex = -1; i < keyframes.Rotations.Length; i++)
                    {
                        if (keyframes.Rotations[i] == null)
                        {
                            continue;
                        }

                        Quaternion q = keyframes.Rotations[i].Value;
                        if (lastUsed_keyIndex >= 0)
                        {
                            bool diffZ = Math.Sign(lastQ.Z) != Math.Sign(q.Z);
                            bool diffW = Math.Sign(lastQ.W) != Math.Sign(q.W);
                            if (diffZ && diffW)
                            {
                                q.X = -q.X;
                                q.Y = -q.Y;
                                q.Z = -q.Z;
                                q.W = -q.W;

                                keyframes.Rotations[i] = q;
                            }
                        }
                        lastQ             = q;
                        lastUsed_keyIndex = i;
                    }
                }
            }
        }