public WorkspaceAnimation(ImportedAnimation importedAnimation) : base() { this.TrackList = importedAnimation.TrackList; this.TrackOptions = new Dictionary<ImportedAnimationTrack, AdditionalTrackOptions>(importedAnimation.TrackList.Count); foreach (ImportedAnimationTrack track in importedAnimation.TrackList) { AdditionalTrackOptions options = new AdditionalTrackOptions(); this.TrackOptions.Add(track, options); } }
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; }
private void ImportAnimation(Section section) { ImportedAnimation workspaceAnimation = new ImportedAnimation(); workspaceAnimation.TrackList = new List<ImportedAnimationTrack>(section.children.Count); foreach (Section animSection in section.children) { if (animSection.type == "Animation") { string trackName = null; float[][][] keyDataArray = new float[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][]; for (int i = 0; i < numKeys; i++) { int keyIdx = ConvertInt32(keyNode.Value); 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; } 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"); } ImportedAnimationKeyframe[] keyframes = new ImportedAnimationKeyframe[keyDataArray[0].Length]; for (int i = 0; i < keyframes.Length; i++) { float[] rotation = keyDataArray[0][i]; float[] scaling = keyDataArray[1][i]; float[] translation = keyDataArray[2][i]; keyframes[i] = new ImportedAnimationKeyframe(); keyframes[i].Rotation = new Quaternion(rotation[0], rotation[1], rotation[2], -rotation[3]); keyframes[i].Scaling = new Vector3(scaling[0], scaling[1], scaling[2]); keyframes[i].Translation = new Vector3(translation[0], translation[1], -translation[2]); } if (keyframes.Length > 0) { ImportedAnimationTrack track = new ImportedAnimationTrack(); 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 ImportAnimationSet(List<Document.Animation> animations, ImportedAnimation wsAnimation) { try { if (animations == null) { return; } Document.Animation animation = animations[0]; if (animation.channel == null) { foreach (Document.Animation animationSet in animations) { ImportAnimationSet(animationSet.children, wsAnimation); } } else { ImportAnimation(animations, wsAnimation); } } catch (Exception e) { Report.ReportLog("Error importing animations: " + e.Message); } }
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 Importer(string path) { try { FrameList = new List<ImportedFrame>(); MeshList = new List<ImportedMesh>(); MaterialList = new List<ImportedMaterial>(); TextureList = new List<ImportedTexture>(); AnimationList = new List<ImportedAnimation>(); MorphList = new List<ImportedMorph>(); colladaDoc = new Document(path); if (colladaDoc.asset != null) { if (colladaDoc.asset.up_axis == "Z_UP") { Z_UP = true; ZUpToYUpMatrix[0, 0] = 1; ZUpToYUpMatrix[1, 2] = 1; ZUpToYUpMatrix[2, 1] = -1; } if ((colladaDoc.asset.contributors != null) && colladaDoc.asset.contributors[0].authoring_tool.Contains("Blender")) { IsBlender = true; } } Dictionary<string, ImportedTexture> textureIdDic = new Dictionary<string, ImportedTexture>(); if (colladaDoc.images != null) { for (int i = 0; i < colladaDoc.images.Count; i++) { ImportedTexture tex = ImportImage(colladaDoc.images[i]); if (tex != null) { ImportedTexture prevTex; if (textureDic.TryGetValue(tex.Name, out prevTex)) { tex = prevTex; } else { textureDic.Add(tex.Name, tex); TextureList.Add(tex); } textureIdDic.Add(colladaDoc.images[i].id, tex); } } } if (colladaDoc.materials != null) { for (int i = 0; i < colladaDoc.materials.Count; i++) { ImportedMaterial mat = ImportMaterial(colladaDoc.materials[i], textureIdDic); if ((mat != null) && !materialDic.ContainsKey(mat.Name)) { materialDic.Add(mat.Name, mat); MaterialList.Add(mat); } } } if (colladaDoc.instanceVisualScene != null) { Document.VisualScene scene = (Document.VisualScene)colladaDoc.dic[colladaDoc.instanceVisualScene.url.Fragment]; if (scene != null) { Conditioner.ConvexTriangulator(colladaDoc); for (int i = 0; i < scene.nodes.Count; i++) { ImportedFrame frame = ImportNode(scene.nodes[i]); if (frame != null) { FrameList.Add(frame); } } } } ImportedAnimation wsAnimation = new ImportedAnimation(); wsAnimation.TrackList = new List<ImportedAnimationTrack>(); ImportAnimationSet(colladaDoc.animations, wsAnimation); if (wsAnimation.TrackList.Count > 0) { AnimationList.Add(wsAnimation); } } catch (Exception e) { Report.ReportLog("Error importing Collada: " + e.Message); } }
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; } } } }