public static List <odfKeyframe> ConvertTrack(ImportedAnimationKeyframe[] iKeyframes) { List <odfKeyframe> keyframes = new List <odfKeyframe>(iKeyframes.Length); for (int i = 0; i < iKeyframes.Length; i++) { ImportedAnimationKeyframe iKeyframe = iKeyframes[i]; if (iKeyframe == null) { continue; } odfKeyframe keyframe = new odfKeyframe(); keyframes.Add(keyframe); odf.CreateUnknowns(keyframe); keyframe.Index = i; keyframe.FastTranslation = iKeyframe.Translation; // keyframe.FastRotation = FbxUtility.QuaternionToEuler(iKeyframe.Rotation); not used, always 0 keyframe.FastScaling = iKeyframe.Scaling; keyframe.ExtraFastRotation = iKeyframe.Rotation; keyframe.Matrix = Matrix.Scaling(iKeyframe.Scaling) * Matrix.RotationQuaternion(iKeyframe.Rotation) * Matrix.Translation(iKeyframe.Translation); } keyframes.TrimExcess(); return(keyframes); }
public static void animationCopyKeyframeTransformArray(ImportedAnimationKeyframe[] src, int srcIdx, ImportedAnimationKeyframe[] dest, int destIdx, int count) { for (int i = 0; i < count; i++) { ImportedAnimationKeyframe keyframe = src[srcIdx + i]; dest[destIdx + i] = keyframe; } }
public static List<KeyValuePair<string, ImportedAnimationKeyframe[]>> CopyAnimation(WorkspaceAnimation wsAnimation, int resampleCount, bool linear) { List<KeyValuePair<string, ImportedAnimationKeyframe[]>> newTrackList = new List<KeyValuePair<string, ImportedAnimationKeyframe[]>>(wsAnimation.TrackList.Count); List<Tuple<ImportedAnimationTrack, ImportedAnimationKeyframe[]>> interpolateTracks = new List<Tuple<ImportedAnimationTrack, ImportedAnimationKeyframe[]>>(); foreach (var wsTrack in wsAnimation.TrackList) { if (!wsAnimation.isTrackEnabled(wsTrack)) continue; ImportedAnimationKeyframe[] newKeyframes; if (resampleCount < 0 || wsTrack.Keyframes.Length == resampleCount) { newKeyframes = new ImportedAnimationKeyframe[wsTrack.Keyframes.Length]; for (int i = 0; i < wsTrack.Keyframes.Length; i++) { ImportedAnimationKeyframe keyframe = wsTrack.Keyframes[i]; if (keyframe == null) continue; newKeyframes[i] = new ImportedAnimationKeyframe(); newKeyframes[i].Rotation = keyframe.Rotation; newKeyframes[i].Translation = keyframe.Translation; newKeyframes[i].Scaling = keyframe.Scaling; } } else { newKeyframes = new ImportedAnimationKeyframe[resampleCount]; if (wsTrack.Keyframes.Length < 1) { ImportedAnimationKeyframe keyframe = new ImportedAnimationKeyframe(); keyframe.Rotation = Quaternion.Identity; keyframe.Scaling = new Vector3(1, 1, 1); keyframe.Translation = new Vector3(0, 0, 0); for (int i = 0; i < newKeyframes.Length; i++) { newKeyframes[i] = keyframe; } } else { interpolateTracks.Add(new Tuple<ImportedAnimationTrack, ImportedAnimationKeyframe[]>(wsTrack, newKeyframes)); } } newTrackList.Add(new KeyValuePair<string, ImportedAnimationKeyframe[]>(wsTrack.Name, newKeyframes)); } if (resampleCount >= 0) { Fbx.InterpolateKeyframes(interpolateTracks, resampleCount, linear); } return newTrackList; }
public static ImportedAnimationKeyframe[] animationGetOriginalKeyframes(Dictionary<string, ImportedAnimationTrack> animationNodeDic, string trackName, ImportedAnimation anim, out ImportedAnimationTrack animationNode) { ImportedAnimationKeyframe[] origKeyframes; if (animationNodeDic.TryGetValue(trackName, out animationNode)) { origKeyframes = animationNode.Keyframes; } else { animationNode = new ImportedAnimationTrack(); anim.TrackList.Add(animationNode); animationNode.Name = trackName; origKeyframes = new ImportedAnimationKeyframe[0]; } return origKeyframes; }
public static ImportedAnimationKeyframe[] ConvertTrack(List <odfKeyframe> keyframes) { int start = (int)keyframes[0].Index; int end = (int)keyframes[keyframes.Count - 1].Index; ImportedAnimationKeyframe[] iKeyframes = new ImportedAnimationKeyframe[end - start + 1]; for (int i = 0; i < keyframes.Count; i++) { odfKeyframe keyframe = keyframes[i]; ImportedAnimationKeyframe iKeyframe = new ImportedAnimationKeyframe(); iKeyframes[(int)keyframe.Index - start] = iKeyframe; iKeyframe.Scaling = keyframe.FastScaling; iKeyframe.Rotation = keyframe.ExtraFastRotation; iKeyframe.Translation = keyframe.FastTranslation; } return(iKeyframes); }
public static void animationNormalizeTrack(ImportedAnimationKeyframe[] origKeyframes, ImportedAnimationKeyframe[] destKeyframes, int count) { ImportedAnimationKeyframe keyframeCopy; if (origKeyframes.Length > 0) { keyframeCopy = origKeyframes[origKeyframes.Length - 1]; } else { keyframeCopy = new ImportedAnimationKeyframe(); keyframeCopy.Rotation = Quaternion.Identity; keyframeCopy.Scaling = new Vector3(1, 1, 1); keyframeCopy.Translation = new Vector3(0, 0, 0); } for (int j = origKeyframes.Length; j < count; j++) { destKeyframes[j] = keyframeCopy; } }
private void ImportAnimation(Section section) { ImportedKeyframedAnimation workspaceAnimation = new ImportedKeyframedAnimation(); workspaceAnimation.TrackList = new List<ImportedAnimationKeyframedTrack>(section.children.Count); foreach (Section animSection in section.children) { if (animSection.type == "Animation") { string trackName = null; float[][][] keyDataArray = new float[5][][]; int[][] keyIndexArray = new int[5][]; foreach (Section keySection in animSection.children) { if (keySection.type == "AnimationKey") { LinkedListNode<object> keyNode = keySection.data.First; int keyType = ConvertInt32(keyNode.Value); keyNode = keyNode.Next; int numKeys = ConvertInt32(keyNode.Value); keyNode = keyNode.Next; float[][] keyData = new float[numKeys][]; int[] keyIndices = new int[numKeys]; for (int i = 0; i < numKeys; i++) { int keyIdx = ConvertInt32(keyNode.Value); keyIndices[i] = keyIdx; keyNode = keyNode.Next; int numFloats = ConvertInt32(keyNode.Value); keyNode = keyNode.Next; keyData[i] = new float[numFloats]; for (int j = 0; j < numFloats; j++) { keyData[i][j] = ConvertFloat(keyNode.Value); keyNode = keyNode.Next; } } keyDataArray[keyType] = keyData; keyIndexArray[keyType] = keyIndices; } else if (keySection.type == "ref") { trackName = keySection.name; } else { Report.ReportLog("Warning: unexpected section " + animSection.type); } } if (trackName == null) { throw new Exception("animation doesn't have a track name"); } if ((keyDataArray[0] == null) || (keyDataArray[2] == null)) { throw new Exception("animation " + trackName + " doesn't have the correct key types"); } if (keyDataArray[1] == null) { keyDataArray[1] = new float[keyDataArray[0].Length][]; for (int i = 0; i < keyDataArray[1].Length; i++) { keyDataArray[1][i] = new float[] { 1, 1, 1 }; } } if ((keyDataArray[0].Length != keyDataArray[1].Length) || (keyDataArray[0].Length != keyDataArray[2].Length)) { throw new Exception("animation " + trackName + " doesn't have the same number of keys for each type"); } int length = keyIndexArray[0][keyIndexArray[0].Length - 1] + 1; ImportedAnimationKeyframe[] keyframes = new ImportedAnimationKeyframe[length]; for (int i = 0; i < keyIndexArray[0].Length; i++) { int idx = keyIndexArray[0][i]; float[] rotation = keyDataArray[0][i]; float[] scaling = keyDataArray[1][i]; float[] translation = keyDataArray[2][i]; keyframes[idx] = new ImportedAnimationKeyframe(); keyframes[idx].Rotation = new Quaternion(rotation[1], rotation[2], -rotation[3], rotation[0]); keyframes[idx].Scaling = new Vector3(scaling[0], scaling[1], scaling[2]); keyframes[idx].Translation = new Vector3(translation[0], translation[1], -translation[2]); } if (keyframes.Length > 0) { ImportedAnimationKeyframedTrack track = new ImportedAnimationKeyframedTrack(); track.Name = trackName; track.Keyframes = keyframes; workspaceAnimation.TrackList.Add(track); } } else { Report.ReportLog("Warning: unexpected section " + animSection.type); } } if (workspaceAnimation.TrackList.Count > 0) { AnimationList.Add(workspaceAnimation); } }
private void ImportAnimation(List<Document.Animation> animations, ImportedAnimation wsAnimation) { Dictionary<string, List<KeyValuePair<string, Document.Source>>> trackList = new Dictionary<string, List<KeyValuePair<string, Document.Source>>>(); for (int i = 0; i < animations.Count; i++) { int typeIdx = animations[i].channel.target.IndexOf('/'); if (typeIdx < 0) { throw new Exception("Couldn't find transform type for ANIMATION " + animations[i].id); } string frameName = DecodeName(animations[i].channel.target.Substring(0, typeIdx)); typeIdx++; string type = animations[i].channel.target.Substring(typeIdx, animations[i].channel.target.Length - typeIdx); for (int j = 0; j < animations[i].sampler.inputs.Count; j++) { if (animations[i].sampler.inputs[j].semantic == "OUTPUT") { Document.Source source = (Document.Source)animations[i].sampler.inputs[j].source; List<KeyValuePair<string, Document.Source>> track; if (!trackList.TryGetValue(frameName, out track)) { track = new List<KeyValuePair<string, Document.Source>>(); trackList.Add(frameName, track); } track.Add(new KeyValuePair<string, Document.Source>(type, source)); break; } } } foreach (KeyValuePair<string, List<KeyValuePair<string, Document.Source>>> track in trackList) { int numFrames = 0; for (int i = 0; i < track.Value.Count; i++) { int count = track.Value[i].Value.accessor.count; if (count > numFrames) { numFrames = count; } } ImportedAnimationKeyframe[] keyframes = new ImportedAnimationKeyframe[numFrames]; for (int i = 0; i < numFrames; i++) { Vector3 translate = new Vector3(0, 0, 0); Vector3 scale = new Vector3(1, 1, 1); float rotX = 0; float rotY = 0; float rotZ = 0; foreach (KeyValuePair<string, Document.Source> transform in track.Value) { Document.Source source = transform.Value; Document.Array<float> array = (Document.Array<float>)source.array; int arrayIdx = source.accessor.offset + (source.accessor.stride * i); if (arrayIdx < array.Count) { float val = array[arrayIdx]; switch (transform.Key) { case "translate.X": translate[0] = val; break; case "translate.Y": if (Z_UP) { translate[2] = -val; } else { translate[1] = val; } break; case "translate.Z": if (Z_UP) { translate[1] = val; } else { translate[2] = val; } break; case "rotateX.ANGLE": rotX = val; break; case "rotateY.ANGLE": rotY = val; break; case "rotateZ.ANGLE": rotZ = val; break; case "scale.X": scale[0] = val; break; case "scale.Y": if (Z_UP) { scale[2] = val; } else { scale[1] = val; } break; case "scale.Z": if (Z_UP) { scale[1] = val; } else { scale[2] = val; } break; default: throw new Exception("Unknown transform type " + transform.Key + " for ANIMATION " + animations[i].id); } } } Matrix rotMatrix = Matrix.Identity; Matrix rotXMatrix = Matrix.RotationAxis(new Vector3(1, 0, 0), (float)(rotX * Math.PI / 180)); Matrix rotYMatrix = Matrix.RotationAxis(new Vector3(0, 1, 0), (float)(rotY * Math.PI / 180)); Matrix rotZMatrix = Matrix.RotationAxis(new Vector3(0, 0, 1), (float)(rotZ * Math.PI / 180)); rotMatrix = rotMatrix * rotZMatrix; rotMatrix = rotMatrix * rotYMatrix; rotMatrix = rotMatrix * rotXMatrix; if (Z_UP) { rotMatrix = ZUpToYUpMatrix * rotMatrix; } Vector3 dummyScale; Quaternion rotation; Vector3 dummyTranslate; if (!rotMatrix.Decompose(out dummyScale, out rotation, out dummyTranslate)) { throw new Exception("Failed to decompose matrix"); } keyframes[i] = new ImportedAnimationKeyframe(); keyframes[i].Rotation = rotation; keyframes[i].Scaling = scale; keyframes[i].Translation = translate; } ImportedAnimationTrack importedTrack = new ImportedAnimationTrack(); importedTrack.Name = track.Key; importedTrack.Keyframes = keyframes; wsAnimation.TrackList.Add(importedTrack); } }
public static List<odfKeyframe> ConvertTrack(ImportedAnimationKeyframe[] iKeyframes) { List<odfKeyframe> keyframes = new List<odfKeyframe>(iKeyframes.Length); for (int i = 0; i < iKeyframes.Length; i++) { ImportedAnimationKeyframe iKeyframe = iKeyframes[i]; if (iKeyframe == null) continue; odfKeyframe keyframe = new odfKeyframe(); keyframes.Add(keyframe); odf.CreateUnknowns(keyframe); keyframe.Index = i; keyframe.FastTranslation = iKeyframe.Translation; // keyframe.FastRotation = FbxUtility.QuaternionToEuler(iKeyframe.Rotation); not used, always 0 keyframe.FastScaling = iKeyframe.Scaling; keyframe.ExtraFastRotation = iKeyframe.Rotation; keyframe.Matrix = Matrix.Scaling(iKeyframe.Scaling) * Matrix.RotationQuaternion(iKeyframe.Rotation) * Matrix.Translation(iKeyframe.Translation); } keyframes.TrimExcess(); return keyframes; }
public static ImportedAnimationKeyframe[] ConvertTrack(List<odfKeyframe> keyframes) { int start = (int)keyframes[0].Index; int end = (int)keyframes[keyframes.Count - 1].Index; ImportedAnimationKeyframe[] iKeyframes = new ImportedAnimationKeyframe[end - start + 1]; for (int i = 0; i < keyframes.Count; i++) { odfKeyframe keyframe = keyframes[i]; ImportedAnimationKeyframe iKeyframe = new ImportedAnimationKeyframe(); iKeyframes[(int)keyframe.Index - start] = iKeyframe; iKeyframe.Scaling = keyframe.FastScaling; iKeyframe.Rotation = keyframe.ExtraFastRotation; iKeyframe.Translation = keyframe.FastTranslation; } return iKeyframes; }
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; } } } }