Пример #1
0
Файл: Fbx.cs Проект: kkdevs/sb3u
            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);
            }
Пример #2
0
 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;
     }
 }
Пример #3
0
        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;
        }
Пример #4
0
 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;
 }
Пример #5
0
Файл: Fbx.cs Проект: kkdevs/sb3u
            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);
            }
Пример #6
0
 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;
     }
 }
Пример #7
0
            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);
                }
            }
Пример #8
0
            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);
                }
            }
Пример #9
0
            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;
            }
Пример #10
0
            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;
            }
Пример #11
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;
                    }
                }
            }
        }