Example #1
0
        protected override FbxAnimStack GenerateFbx()
        {
            HavokAnimationData anim = Souls.dsAnimation;

            IDictionary <int, FrameData> frameDatas = ExtractAnimationData(anim);

            var animStack = FbxAnimStack.Create(Scene, anim.Name + "_AnimStack");

            animStack.SetLocalTimeSpan(new FbxTimeSpan(FbxTime.FromFrame(0), FbxTime.FromFrame(anim.FrameCount)));

            FbxAnimLayer animLayer = FbxAnimLayer.Create(animStack, "Layer0");

            animStack.AddMember(animLayer);

            IDictionary <int, AnimExportHelper> boneHelpers = new Dictionary <int, AnimExportHelper>();

            foreach (DsBoneData boneData in Souls.skeleton.boneDatas)
            {
                boneData.exportData.FbxNode.LclTranslation.GetCurveNode(animLayer, true);
                boneData.exportData.FbxNode.LclRotation.GetCurveNode(animLayer, true);
                boneData.exportData.FbxNode.LclScaling.GetCurveNode(animLayer, true);

                boneHelpers.Add(boneData.exportData.SoulsData.HkxBoneIndex, new AnimExportHelper(
                                    animLayer,
                                    boneData.exportData.FbxNode.LclTranslation,
                                    boneData.exportData.FbxNode.LclRotation,
                                    boneData.exportData.FbxNode.LclScaling
                                    )
                                );
            }

            foreach (var frameData in frameDatas)
            {
                FbxTime time = FbxTime.FromFrame(frameData.Key);

                foreach (var boneData in frameData.Value.boneDatas)
                {
                    int hkxBoneIndex = boneData.hkxBoneIndex;

                    var newBlendableTransform = boneData.transform;

                    AnimExportHelper animExportHelper = boneHelpers[hkxBoneIndex];

                    var euler = new Quaternion(newBlendableTransform.Rotation.X, newBlendableTransform.Rotation.Y, newBlendableTransform.Rotation.Z, newBlendableTransform.Rotation.W).QuaternionToEuler();

                    animExportHelper.translation.AddPoint(time, newBlendableTransform.Translation);
                    animExportHelper.rotation.AddPoint(time, euler);
                    animExportHelper.scale.AddPoint(time, newBlendableTransform.Scale);
                }
            }

            foreach (AnimExportHelper helper in boneHelpers.Values)
            {
                helper.translation.Finish();
                helper.rotation.Finish();
                helper.scale.Finish();
            }

            return(null);
        }
        public static void ExportToFile(HavokAnimationData anim, string filePath, string assimpFileFormatStr)
        {
            var scene = ExportToScene(anim);

            using (var x = new AssimpContext())
            {
                x.ExportFile(scene, filePath, assimpFileFormatStr);
            }
        }
Example #3
0
        protected NewHavokAnimation(HavokAnimationData data, NewAnimSkeleton skeleton, NewAnimationContainer container)
        {
            this.data = data;

            ParentContainer = container;
            Skeleton        = skeleton;

            lock (_lock_boneMatrixStuff)
            {
                blendableTransforms = new NewBlendableTransform[skeleton.HkxSkeleton.Count];
            }

            RotMatrixAtStartOfAnim = ParentContainer.MODEL.CurrentRootMotionRotation;
        }
Example #4
0
        public NewHavokAnimation(HavokAnimationData data, NewAnimSkeleton_HKX skeleton, NewAnimationContainer container)
        {
            this.data = data;

            ParentContainer = container;
            Skeleton        = skeleton;

            lock (_lock_boneMatrixStuff)
            {
                blendableTransforms = new NewBlendableTransform[skeleton.HkxSkeleton.Count];
            }

            RootMotion = new RootMotionDataPlayer(data.RootMotion);
        }
        protected NewHavokAnimation(HavokAnimationData data, NewAnimSkeleton skeleton, NewAnimationContainer container)
        {
            this.data = data;

            ParentContainer = container;
            Skeleton        = skeleton;

            lock (_lock_boneMatrixStuff)
            {
                blendableTransforms = new List <NewBlendableTransform>();
                for (int i = 0; i < skeleton.HkxSkeleton.Count; i++)
                {
                    blendableTransforms.Add(NewBlendableTransform.Identity);
                }
            }

            RotMatrixAtStartOfAnim = ParentContainer.MODEL.CurrentRootMotionRotation;
        }
Example #6
0
        private Matrix4x4 GetMatrix(int hkxBoneIndex, float frameIndex)
        {
            HavokAnimationData anim = Souls.dsAnimation;

            NewBlendableTransform newBlendableTransform = anim.GetBlendableTransformOnFrame(hkxBoneIndex, frameIndex);

            var currentTransformMatrix = newBlendableTransform.GetMatrix();

            int parentIndex = Souls.dsAnimation.hkaSkeleton.ParentIndices[hkxBoneIndex].data;

            if (parentIndex >= 0)
            {
                currentTransformMatrix *= GetMatrix(parentIndex, frameIndex);
            }
            else
            {
                //var rootMotion = rootMotionCache.GetRootMotionOnFrame((int)frameIndex);

                //currentTransformMatrix *= Microsoft.Xna.Framework.Matrix.CreateRotationY(rootMotion.W);
                //currentTransformMatrix *= Microsoft.Xna.Framework.Matrix.CreateTranslation(rootMotion.X, rootMotion.Y, rootMotion.Z);
            }

            return(currentTransformMatrix);
        }
Example #7
0
        private IDictionary <int, FrameData> ExtractAnimationData(HavokAnimationData anim)
        {
            IDictionary <int, FrameData> frameDatas = new Dictionary <int, FrameData>();

            try
            {
                for (int frameIndex = 0; frameIndex < Souls.dsAnimation.FrameCount; ++frameIndex)
                {
                    var frameBoneDatas = new List <FrameData.FrameBoneData>();

                    FrameData data = new FrameData()
                    {
                        boneDatas = frameBoneDatas, frameIndex = frameIndex
                    };



                    Func <DsBoneData, Matrix4x4> calculateTransform = bone =>
                    {
                        if (bone.parent == null)
                        {
                            return(Matrix4x4.Identity);
                        }

                        var calculatedMatrix = GetMatrix(bone.exportData.SoulsData.HkxBoneIndex, frameIndex);

                        var hackPreMatrix  = Matrix4x4.CreateRotationZ((float)(-Math.PI / 2)); // * Matrix4x4.CreateRotationY((float)(-Math.PI / 2)); ; // Microsoft.Xna.Framework.Matrix.CreateScale(-1, 1, 1);
                        var hackPostMatrix = Matrix4x4.Identity;                               // Matrix4x4.CreateScale(-1, 1, 1); // Matrix4x4.CreateScale(-1,1,1); // * Matrix4x4.CreateRotationY((float)(Math.PI)); // Matrix4x4.CreateScale(1, 1, -1);

                        var transformedMatrix = hackPreMatrix * calculatedMatrix * hackPostMatrix;

                        var btr = new NewBlendableTransform(transformedMatrix);

                        btr.Translation.Z = -btr.Translation.Z;
                        btr.Rotation.X    = -btr.Rotation.X;
                        btr.Rotation.Y    = -btr.Rotation.Y;

                        return(btr.GetMatrix());
                    };

                    foreach (var bone in Souls.skeleton.boneDatas)
                    {
                        var boneData111 = new FrameData.FrameBoneData()
                        {
                            hkxBoneIndex = bone.exportData.SoulsData.HkxBoneIndex
                        };

                        var calculatedMatrix = calculateTransform(bone);

                        var hackNewBlendableMatrix = calculatedMatrix;

                        if (bone.parent != null)
                        {
                            Matrix4x4 parentMatrix = calculateTransform(bone.parent);

                            if (Matrix4x4.Invert(parentMatrix, out var inverted))
                            {
                                hackNewBlendableMatrix *= inverted;
                            }
                            else
                            {
                                throw new Exception();
                            }
                        }
                        else
                        {
                            Func <Matrix4x4> getRefMatrix = () =>
                            {
                                if (Souls.animRefFrame == null)
                                {
                                    return(Matrix4x4.Identity);
                                }

                                return(Matrix4x4.CreateWorld(Vector3.Zero, Souls.animRefFrame.Forward.ToVector3(), Souls.animRefFrame.Up.ToVector3()));
                            };

                            var refMatrix = Matrix4x4.Identity; // getRefMatrix();

                            Matrix4x4 additionalPostTransformation = refMatrix;

                            // this is a root bone
                            if (anim.RootMotion != null)
                            {
                                var rootMotion = anim.RootMotion.ExtractRootMotion(0, anim.Duration * (((float)frameIndex / anim.FrameCount)));

                                rootMotion.positionChange.Z = -rootMotion.positionChange.Z;

                                Matrix4x4 rootMotionTransformation = Matrix4x4.CreateRotationY(rootMotion.directionChange) * Matrix4x4.CreateTranslation(rootMotion.positionChange);
                                additionalPostTransformation *= rootMotionTransformation;
                            }

                            hackNewBlendableMatrix *= additionalPostTransformation;
                        }

                        var newBlendableTransform = new NewBlendableTransform(hackNewBlendableMatrix);

                        int hkxBoneIndex = bone.exportData.SoulsData.HkxBoneIndex;

                        boneData111.hkxBoneIndex = hkxBoneIndex;
                        boneData111.transform    = newBlendableTransform;

                        frameBoneDatas.Add(boneData111);
                    }

                    frameDatas.Add(frameIndex, data);
                }

                return(frameDatas);
            }
            catch (Exception ex)
            {
                throw new AnimationExportException("An exception occured while exporting animations!", ex);
            }
        }
        public static Scene ExportToScene(HavokAnimationData anim)
        {
            var scene = new Scene();

            scene.RootNode = new Node("scene_root");

            scene.RootNode.Metadata["FrameRate"]       = new Metadata.Entry(MetaDataType.Int32, 14);
            scene.RootNode.Metadata["TimeSpanStart"]   = new Metadata.Entry(MetaDataType.UInt64, (ulong)0);
            scene.RootNode.Metadata["TimeSpanStop"]    = new Metadata.Entry(MetaDataType.UInt64, (ulong)0);
            scene.RootNode.Metadata["CustomFrameRate"] = new Metadata.Entry(MetaDataType.Float, 1f / anim.FrameDuration);

            scene.RootNode.Metadata["FrontAxisSign"]           = new Metadata.Entry(MetaDataType.Int32, -1);
            scene.RootNode.Metadata["OriginalUnitScaleFactor"] = new Metadata.Entry(MetaDataType.Int32, 100);
            scene.RootNode.Metadata["UnitScaleFactor"]         = new Metadata.Entry(MetaDataType.Int32, 100);



            var a = new Assimp.Animation();

            a.DurationInTicks = anim.Duration * 30;
            a.TicksPerSecond  = 30;
            a.Name            = anim.Name;

            List <Node> animTrackNodes = new List <Node>();

            for (int i = 0; i < anim.TransformTrackIndexToHkxBoneMap.Length; i++)
            {
                int boneIndex = anim.TransformTrackIndexToHkxBoneMap[i];
                if (boneIndex < 0 || boneIndex > anim.hkaSkeleton.Bones.Capacity)
                {
                    continue;
                }
                string trackName = anim.hkaSkeleton.Bones[boneIndex].Name.GetString();
                var    animTrack = new NodeAnimationChannel();
                animTrack.NodeName = trackName;
                for (int f = 0; f < anim.FrameCount; f++)
                {
                    var t = anim.GetTransformOnFrame(i, f, enableLooping: false);
                    animTrack.PositionKeys.Add(new VectorKey(1.0 * f * anim.FrameDuration, new Vector3D(t.Translation.X * -100, t.Translation.Y * 100, t.Translation.Z * 100)));
                    animTrack.ScalingKeys.Add(new VectorKey(1.0 * f * anim.FrameDuration, new Vector3D(t.Scale.X, t.Scale.Y, t.Scale.Z)));
                    var q = t.Rotation;

                    //q.X *= -1;
                    //q.Y *= -1;
                    //q.Z *= -1;
                    //q.W *= -1;
                    q = SapMath.MirrorQuat(q);
                    //q.X *= -1;
                    //q.Y *= -1;
                    //q.Z *= -1;
                    //q.W *= -1;
                    animTrack.RotationKeys.Add(new QuaternionKey(1.0 * f * anim.FrameDuration, new Quaternion(q.W, q.X, q.Y, q.Z)));
                }



                a.NodeAnimationChannels.Add(animTrack);

                var fakeNode = new Node(trackName);
                animTrackNodes.Add(fakeNode);
            }

            List <Node> topLevelTrackNodes = new List <Node>();

            for (int i = 0; i < animTrackNodes.Count; i++)
            {
                var hkxBoneIndex    = anim.TransformTrackIndexToHkxBoneMap[i];
                var parentBoneIndex = anim.hkaSkeleton.ParentIndices[hkxBoneIndex].data;
                if (parentBoneIndex >= 0)
                {
                    var parentTrackIndex = anim.HkxBoneIndexToTransformTrackMap[parentBoneIndex];
                    if (parentTrackIndex >= 0)
                    {
                        animTrackNodes[parentTrackIndex].Children.Add(animTrackNodes[i]);
                    }
                }
                else
                {
                    topLevelTrackNodes.Add(animTrackNodes[i]);
                }
            }

            var actualRootNode = new Node("root");

            if (anim.RootMotion != null)
            {
                var animTrack = new NodeAnimationChannel();
                animTrack.NodeName = actualRootNode.Name;

                for (int f = 0; f < anim.FrameCount; f++)
                {
                    var rootMotionOnFrame = anim.RootMotion.GetSampleClamped(f * anim.FrameDuration);

                    animTrack.PositionKeys.Add(new VectorKey(1.0 * f * anim.FrameDuration, new Vector3D(rootMotionOnFrame.X * -100, rootMotionOnFrame.Y * 100, rootMotionOnFrame.Z * 100)));

                    var q = NQuaternion.CreateFromRotationMatrix(NMatrix.CreateRotationY(rootMotionOnFrame.W));
                    animTrack.RotationKeys.Add(new QuaternionKey(1.0 * f * anim.FrameDuration, new Quaternion(q.W, q.X, q.Y, q.Z)));
                }

                a.NodeAnimationChannels.Add(animTrack);
            }

            foreach (var t in topLevelTrackNodes)
            {
                actualRootNode.Children.Add(t);
            }

            scene.RootNode.Children.Add(actualRootNode);

            scene.Animations.Add(a);

            return(scene);
        }