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); } }
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; } }
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; } }
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; } } } }
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; } } } }
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; } }
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; } } } }
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; } } } }