public SkeletonExporter(FbxScene scene, FLVER2 flver, HKX.HKASkeleton hKASkeleton, List <DsBone> bones)
 {
     Scene            = scene;
     this.Flver       = flver;
     this.bones       = bones;
     this.hkaSkeleton = hKASkeleton;
 }
Exemple #2
0
        public DsBone(HKX.Bone hkxBone, HKX.HKASkeleton hkaSkeleton) : this()
        {
            HkxBoneIndex = hkaSkeleton.Bones.GetArrayData().Elements.IndexOf(hkxBone);

            Name = hkxBone.Name.GetString();

            ParentName = InitializeHkxParentName(hkxBone, hkaSkeleton);
        }
Exemple #3
0
        private string InitializeHkxParentName(HKX.Bone hkxBone, HKX.HKASkeleton hkaSkeleton)
        {
            short hkxParentBoneIndex = hkaSkeleton.ParentIndices.GetArrayData().Elements[HkxBoneIndex].data;

            if (hkxParentBoneIndex >= 0)
            {
                HKX.Bone hkxParentBone = hkaSkeleton.Bones.GetArrayData().Elements[hkxParentBoneIndex];

                return(hkxParentBone.Name.GetString());
            }

            return(null);
        }
Exemple #4
0
        private static IEnumerable <DsBone> FixupDsBonesInternal(FLVER2 flver, HKX.HKASkeleton hkx)
        {
            if (hkx == null)
            {
                return(FixupDsBones(flver));
            }

            if (flver == null)
            {
                return(FixupDsBones(hkx));
            }

            return(flver.Bones.Join(hkx.Bones.GetArrayData().Elements, flverBone => flverBone.Name, hkxBone => hkxBone.Name.GetString(), (flverBone, hkxBone) =>
                                    new DsBone(flverBone, flver, hkxBone, hkx)
                                    ));
        }
Exemple #5
0
        public static IEnumerable <DsBone> FixupDsBones(FLVER2 flver, HKX.HKASkeleton hkx)
        {
            var skel = FixupDsBonesInternal(flver, hkx);

            Func <DsBone, DsBone> boneConversion = bone => {
                //if (bone.Name == "Pelvis")
                //{
                //    bone.ParentName = "RootRotXZ";
                //}

                if (bone.Name == "Spine")
                {
                    bone.ParentName = "Pelvis";
                }

                return(bone);
            };

            return(skel.Select(boneConversion));
        }
        private static Matrix4x4 CalculateGlobalTransformHka(int hkxBoneIndex, HKX.HKASkeleton skeleton)
        {
            var hkxTransform = skeleton.Transforms.GetArrayData().Elements[hkxBoneIndex];

            Matrix4x4 transformMatrix =
                Matrix4x4.CreateScale(hkxTransform.Scale.Vector.X, hkxTransform.Scale.Vector.Y, hkxTransform.Scale.Vector.Z)
                * Matrix4x4.CreateFromQuaternion(new Quaternion(hkxTransform.Rotation.Vector.X, hkxTransform.Rotation.Vector.Y, hkxTransform.Rotation.Vector.Z, hkxTransform.Rotation.Vector.W))
                * Matrix4x4.CreateTranslation(hkxTransform.Position.Vector.X, hkxTransform.Position.Vector.Y, hkxTransform.Position.Vector.Z);

            short parentIndex = skeleton.ParentIndices[hkxBoneIndex].data;

            if (parentIndex >= 0)
            {
                transformMatrix *= CalculateGlobalTransformHka(parentIndex, skeleton);
            }
            else
            {
                //transformMatrix *= Matrix4x4.CreateRotationX((float)(-Math.PI / 2)) * Matrix4x4.CreateRotationZ((float)(Math.PI / 2));
            }

            return(transformMatrix);
        }
Exemple #7
0
        public void LoadHKXSkeleton(HKX.HKASkeleton skeleton)
        {
            OriginalHavokSkeleton = skeleton;
            HkxSkeleton.Clear();
            for (int i = 0; i < skeleton.Bones.Size; i++)
            {
                var newHkxBone = new HkxBoneInfo();
                newHkxBone.Name                    = skeleton.Bones[i].Name.GetString();
                newHkxBone.ParentIndex             = skeleton.ParentIndices[i].data;
                newHkxBone.RelativeReferenceMatrix =
                    Matrix.CreateScale(new Vector3(
                                           skeleton.Transforms[i].Scale.Vector.X,
                                           skeleton.Transforms[i].Scale.Vector.Y,
                                           skeleton.Transforms[i].Scale.Vector.Z))
                    * Matrix.CreateFromQuaternion(new Quaternion(
                                                      skeleton.Transforms[i].Rotation.Vector.X,
                                                      skeleton.Transforms[i].Rotation.Vector.Y,
                                                      skeleton.Transforms[i].Rotation.Vector.Z,
                                                      skeleton.Transforms[i].Rotation.Vector.W))
                    * Matrix.CreateTranslation(new Vector3(
                                                   skeleton.Transforms[i].Position.Vector.X,
                                                   skeleton.Transforms[i].Position.Vector.Y,
                                                   skeleton.Transforms[i].Position.Vector.Z));

                for (int j = 0; j < FlverSkeleton.Count; j++)
                {
                    if (FlverSkeleton[j].Name == newHkxBone.Name)
                    {
                        FlverSkeleton[j].HkxBoneIndex = i;
                        newHkxBone.FlverBoneIndex     = j;
                        break;
                    }
                }

                HkxSkeleton.Add(newHkxBone);
            }

            Matrix GetAbsoluteReferenceMatrix(int i)
            {
                Matrix result = Matrix.Identity;

                do
                {
                    result *= HkxSkeleton[i].RelativeReferenceMatrix;
                    i       = HkxSkeleton[i].ParentIndex;
                }while (i >= 0);

                return(result);
            }

            var flverDeadBonesToApplyHkxChildrenTo = new Dictionary <int, int>();

            for (int i = 0; i < HkxSkeleton.Count; i++)
            {
                HkxSkeleton[i].ReferenceMatrix = GetAbsoluteReferenceMatrix(i);
                for (int j = 0; j < HkxSkeleton.Count; j++)
                {
                    if (HkxSkeleton[j].ParentIndex == i)
                    {
                        HkxSkeleton[i].ChildIndices.Add(j);
                    }
                }
                if (HkxSkeleton[i].ParentIndex < 0)
                {
                    RootBoneIndices.Add(i);
                }

                if (HkxSkeleton[i].FlverBoneIndex == -1)
                {
                    HkxSkeleton[i].FlverBoneIndex = FlverSkeleton.Count;
                    var newFlverBone = new FlverBoneInfo(HkxSkeleton[i], HkxSkeleton, FlverSkeleton);
                    FlverSkeleton.Add(newFlverBone);
                    if (!flverDeadBonesToApplyHkxChildrenTo.ContainsKey(HkxSkeleton[i].FlverBoneIndex))
                    {
                        flverDeadBonesToApplyHkxChildrenTo.Add(HkxSkeleton[i].FlverBoneIndex, i);
                    }
                }
                else if (FlverSkeleton[HkxSkeleton[i].FlverBoneIndex].IsNub)
                {
                    FlverSkeleton[HkxSkeleton[i].FlverBoneIndex].ApplyHkxBoneProperties(HkxSkeleton[i], HkxSkeleton, FlverSkeleton);
                    if (!flverDeadBonesToApplyHkxChildrenTo.ContainsKey(HkxSkeleton[i].FlverBoneIndex))
                    {
                        flverDeadBonesToApplyHkxChildrenTo.Add(HkxSkeleton[i].FlverBoneIndex, i);
                    }
                }

                foreach (var kvp in flverDeadBonesToApplyHkxChildrenTo)
                {
                    FlverSkeleton[kvp.Key].ChildBones.Clear();
                    var copyFromHkx = HkxSkeleton[kvp.Value];
                    foreach (var ci in copyFromHkx.ChildIndices)
                    {
                        if (ci >= 0 && ci < HkxSkeleton.Count)
                        {
                            var matchingFlverChildBone = FlverSkeleton.FirstOrDefault(b => b.Name == HkxSkeleton[ci].Name);
                            if (matchingFlverChildBone != null && !FlverSkeleton[kvp.Key].ChildBones.Contains(matchingFlverChildBone))
                            {
                                FlverSkeleton[kvp.Key].ChildBones.Add(matchingFlverChildBone);
                            }
                        }
                    }

                    if (HkxSkeleton[kvp.Value].ParentIndex >= 0 && HkxSkeleton[kvp.Value].ParentIndex < HkxSkeleton.Count)
                    {
                        var matchingFlverParentBone = FlverSkeleton.FirstOrDefault(b => b.Name == HkxSkeleton[HkxSkeleton[kvp.Value].ParentIndex].Name);
                        if (matchingFlverParentBone != null && !matchingFlverParentBone.ChildBones.Contains(FlverSkeleton[kvp.Key]))
                        {
                            matchingFlverParentBone.ChildBones.Add(FlverSkeleton[kvp.Key]);
                        }
                    }
                }
            }
        }
Exemple #8
0
        public void LoadHKXSkeleton(HKX.HKASkeleton skeleton)
        {
            OriginalHavokSkeleton = skeleton;
            HkxSkeleton.Clear();
            TopLevelHkxBoneIndices.Clear();
            for (int i = 0; i < skeleton.Bones.Size; i++)
            {
                var newHkxBone = new HkxBoneInfo();
                newHkxBone.Name        = skeleton.Bones[i].Name.GetString();
                newHkxBone.ParentIndex = skeleton.ParentIndices[i].data;

                newHkxBone.RelativeReferenceTransform = new NewBlendableTransform()
                {
                    Translation = new System.Numerics.Vector3(
                        skeleton.Transforms[i].Position.Vector.X,
                        skeleton.Transforms[i].Position.Vector.Y,
                        skeleton.Transforms[i].Position.Vector.Z),
                    Rotation = new System.Numerics.Quaternion(
                        skeleton.Transforms[i].Rotation.Vector.X,
                        skeleton.Transforms[i].Rotation.Vector.Y,
                        skeleton.Transforms[i].Rotation.Vector.Z,
                        skeleton.Transforms[i].Rotation.Vector.W),
                    Scale = new System.Numerics.Vector3(
                        skeleton.Transforms[i].Scale.Vector.X,
                        skeleton.Transforms[i].Scale.Vector.Y,
                        skeleton.Transforms[i].Scale.Vector.Z),
                };

                newHkxBone.RelativeReferenceMatrix =
                    Matrix.CreateScale(new Vector3(
                                           skeleton.Transforms[i].Scale.Vector.X,
                                           skeleton.Transforms[i].Scale.Vector.Y,
                                           skeleton.Transforms[i].Scale.Vector.Z))
                    * Matrix.CreateFromQuaternion(Quaternion.Normalize(new Quaternion(
                                                                           skeleton.Transforms[i].Rotation.Vector.X,
                                                                           skeleton.Transforms[i].Rotation.Vector.Y,
                                                                           skeleton.Transforms[i].Rotation.Vector.Z,
                                                                           skeleton.Transforms[i].Rotation.Vector.W)))
                    * Matrix.CreateTranslation(new Vector3(
                                                   skeleton.Transforms[i].Position.Vector.X,
                                                   skeleton.Transforms[i].Position.Vector.Y,
                                                   skeleton.Transforms[i].Position.Vector.Z));



                HkxSkeleton.Add(newHkxBone);
            }

            void GetAbsoluteReferenceMatrix(int i)
            {
                Matrix result = Matrix.Identity;
                int    j      = i;

                do
                {
                    result = HkxSkeleton[j].RelativeReferenceMatrix * result;
                    j      = HkxSkeleton[j].ParentIndex;
                }while (j >= 0);

                HkxSkeleton[i].ReferenceMatrix = result;
                HkxSkeleton[i].ReferenceMatrixRootBoneIndex = j;
            }

            for (int i = 0; i < HkxSkeleton.Count; i++)
            {
                if (HkxSkeleton[i].ParentIndex < 0)
                {
                    TopLevelHkxBoneIndices.Add(i);
                }

                for (int j = 0; j < HkxSkeleton.Count; j++)
                {
                    if (HkxSkeleton[j].ParentIndex == i)
                    {
                        HkxSkeleton[i].ChildIndices.Add(j);
                    }
                }

                GetAbsoluteReferenceMatrix(i);
            }
        }
        private static Matrix4x4 CalculateGlobalTransform(DsBoneData boneData, FLVER2 flver, HKX.HKASkeleton hkaSkeleton)
        {
            if (boneData.exportData.SoulsData.HkxBoneIndex >= 0)
            {
                System.Diagnostics.Debug.Assert(hkaSkeleton != null);

                System.Console.WriteLine("Using HKA transform");

                return(CalculateGlobalTransformHka(boneData.exportData.SoulsData.HkxBoneIndex, hkaSkeleton));
            }

            if (flver != null)
            {
                System.Console.WriteLine("Using FLVER transform");

                return(CalculateGlobalTransformFlver(boneData.flverBone, flver));
            }

            throw new System.ArgumentException("Can't calculate transform " + nameof(boneData));
        }
        public void LoadHKXSkeleton(HKX.HKASkeleton skeleton)
        {
            OriginalHavokSkeleton = skeleton;
            HkxSkeleton.Clear();
            for (int i = 0; i < skeleton.Bones.Size; i++)
            {
                var newHkxBone = new HkxBoneInfo();
                newHkxBone.Name                    = skeleton.Bones[i].Name.GetString();
                newHkxBone.ParentIndex             = skeleton.ParentIndices[i].data;
                newHkxBone.RelativeReferenceMatrix =
                    Matrix.CreateScale(new Vector3(
                                           skeleton.Transforms[i].Scale.Vector.X,
                                           skeleton.Transforms[i].Scale.Vector.Y,
                                           skeleton.Transforms[i].Scale.Vector.Z))
                    * Matrix.CreateFromQuaternion(new Quaternion(
                                                      skeleton.Transforms[i].Rotation.Vector.X,
                                                      skeleton.Transforms[i].Rotation.Vector.Y,
                                                      skeleton.Transforms[i].Rotation.Vector.Z,
                                                      skeleton.Transforms[i].Rotation.Vector.W))
                    * Matrix.CreateTranslation(new Vector3(
                                                   skeleton.Transforms[i].Position.Vector.X,
                                                   skeleton.Transforms[i].Position.Vector.Y,
                                                   skeleton.Transforms[i].Position.Vector.Z));

                for (int j = 0; j < FlverSkeleton.Count; j++)
                {
                    if (FlverSkeleton[j].Name == newHkxBone.Name)
                    {
                        FlverSkeleton[j].HkxBoneIndex = i;
                        newHkxBone.FlverBoneIndex     = j;
                        break;
                    }
                }

                HkxSkeleton.Add(newHkxBone);
            }

            Matrix GetAbsoluteReferenceMatrix(int i)
            {
                Matrix result = Matrix.Identity;

                do
                {
                    result *= HkxSkeleton[i].RelativeReferenceMatrix;
                    i       = HkxSkeleton[i].ParentIndex;
                }while (i >= 0);

                return(result);
            }

            for (int i = 0; i < HkxSkeleton.Count; i++)
            {
                HkxSkeleton[i].ReferenceMatrix = GetAbsoluteReferenceMatrix(i);
                for (int j = 0; j < HkxSkeleton.Count; j++)
                {
                    if (HkxSkeleton[j].ParentIndex == i)
                    {
                        HkxSkeleton[i].ChildIndices.Add(j);
                    }
                }
                if (HkxSkeleton[i].ParentIndex < 0)
                {
                    RootBoneIndices.Add(i);
                }
            }
        }
Exemple #11
0
        public DsBone(FLVER.Bone flverBone, FLVER2 flver, HKX.Bone hkxBone, HKX.HKASkeleton hkaSkeleton) : this(flverBone, flver)
        {
            HkxBoneIndex = hkaSkeleton.Bones.GetArrayData().Elements.IndexOf(hkxBone);

            ParentName = InitializeHkxParentName(hkxBone, hkaSkeleton);
        }
Exemple #12
0
 private static IEnumerable <DsBone> FixupDsBones(HKX.HKASkeleton hkx)
 {
     return(hkx.Bones.GetArrayData().Elements.Select(hkxBone => new DsBone(hkxBone, hkx)));
 }
Exemple #13
0
        private static void LoadRemoHKX(byte[] hkxBytes, string animName)
        {
            Scene.DisableModelDrawing();
            Scene.DisableModelDrawing2();

            HKX.HKAAnimationBinding          hk_binding = null;
            HKX.HKASplineCompressedAnimation hk_anim    = null;
            HKX.HKASkeleton hk_skeleton = null;

            if (remoCutsLoaded.ContainsKey(animName))
            {
                hk_binding  = remoCutsLoaded[animName].hk_binding;
                hk_anim     = remoCutsLoaded[animName].hk_anim;
                hk_skeleton = remoCutsLoaded[animName].hk_skeleton;
            }
            else
            {
                var hkx = HKX.Read(hkxBytes, HKX.HKXVariation.HKXDS1, false);

                foreach (var o in hkx.DataSection.Objects)
                {
                    if (o is HKX.HKASkeleton asSkeleton)
                    {
                        hk_skeleton = asSkeleton;
                    }
                    else if (o is HKX.HKAAnimationBinding asBinding)
                    {
                        hk_binding = asBinding;
                    }
                    else if (o is HKX.HKASplineCompressedAnimation asAnim)
                    {
                        hk_anim = asAnim;
                    }
                }

                remoCutsLoaded.Add(animName, new RemoCutCache()
                {
                    hk_binding  = hk_binding,
                    hk_anim     = hk_anim,
                    hk_skeleton = hk_skeleton,
                });
            }



            var animContainer = new NewAnimationContainer();

            AnimContainer = animContainer;

            animContainer.ClearAnimations();

            animContainer.Skeleton.LoadHKXSkeleton(hk_skeleton);

            var testIdleAnimThing = new NewHavokAnimation_SplineCompressed(animName,
                                                                           animContainer.Skeleton, null, hk_binding, hk_anim, animContainer);

            animContainer.AddNewAnimation(animName, testIdleAnimThing);

            animContainer.CurrentAnimationName = animName;

            var modelNames = animContainer.Skeleton.TopLevelHkxBoneIndices.Select(b => animContainer.Skeleton.HkxSkeleton[b].Name).ToList();

            CurrentCutHits.Clear();
            CurrentCutOtherBlocks.Clear();
            lock (Scene._lock_ModelLoad_Draw)
            {
                Scene.Models.Clear();
            }
            foreach (var name in modelNames)
            {
                Model mdl = null;

                if (!remoModelDict.ContainsKey(name))
                {
                    PauseStreamBGM();

                    if (name.StartsWith("c"))
                    {
                        string shortName = name.Substring(0, 5);
                        mdl = GameDataManager.LoadCharacter(shortName);
                        FmodManager.LoadInterrootFEV(shortName);

                        if (mdl.IS_PLAYER)
                        {
                            ViewportInteractor.InitializeCharacterModel(mdl, isRemo: true);
                        }
                    }
                    else if (name.StartsWith("o"))
                    {
                        string shortName = name.Substring(0, 5);
                        mdl = GameDataManager.LoadObject(shortName);
                        FmodManager.LoadInterrootFEV(shortName);
                    }
                    else if (name.StartsWith("m"))
                    {
                        mdl = GameDataManager.LoadMapPiece(AreaInt, BlockInt, 0, 0, int.Parse(name.Substring(1, 4)));
                    }
                    else if (name.StartsWith("A"))
                    {
                        int a = int.Parse(name.Substring(1, 2));
                        int b = int.Parse(name.Substring(4, 2));

                        if (b != BlockInt && !CurrentCutOtherBlocks.Contains(b))
                        {
                            CurrentCutOtherBlocks.Add(b);
                        }

                        mdl = GameDataManager.LoadMapPiece(a, b, 0, 0, int.Parse(name.Substring(8, 4)));
                    }
                    else if (name.StartsWith("d"))
                    {
                        // TODO
                        // Dummy entity e.g. 'd0000_0000'. Apparently just acts as a single DummyPoly?
                        mdl = GameDataManager.LoadCharacter("c1000");
                        mdl.RemoDummyTransformPrim =
                            new DebugPrimitives.DbgPrimWireArrow(name, new Transform(Microsoft.Xna.Framework.Matrix.CreateScale(0.25f)
                                                                                     * mdl.CurrentTransform.WorldMatrix), Microsoft.Xna.Framework.Color.Lime)
                        {
                            Category = DebugPrimitives.DbgPrimCategory.AlwaysDraw
                        };
                        mdl.RemoDummyTransformTextPrint = new StatusPrinter(null, Microsoft.Xna.Framework.Color.Lime);
                        mdl.RemoDummyTransformTextPrint.AppendLine(name);
                        mdl.IS_REMO_DUMMY = true;
                    }
                    else if (name.StartsWith("h"))
                    {
                        // Collision.
                        CurrentCutHits.Add(name);
                    }
                    else
                    {
                        throw new NotImplementedException($"Cannot tell what object type '{name}' is in remo HKX");
                    }

                    if (mdl != null)
                    {
                        mdl.Name = name;

                        remoModelDict.Add(name, mdl);
                    }
                }
                else
                {
                    mdl = remoModelDict[name];
                }

                if (mdl != null)
                {
                    mdl.AnimContainer = animContainer;
                    mdl.IsRemoModel   = true;
                    mdl.Name          = name;
                    mdl.SkeletonFlver.RevertToReferencePose();
                    mdl.SkeletonFlver.MapToSkeleton(animContainer.Skeleton, isRemo: true);
                    mdl.UpdateSkeleton();

                    lock (Scene._lock_ModelLoad_Draw)
                    {
                        Scene.Models.Add(mdl);
                    }
                }
            }



            var msbName = GameDataManager.GetInterrootPath($@"map\MapStudio\m{AreaInt:D2}_{BlockInt:D2}_00_00.msb");

            var msb = MSB1.Read(msbName);

            Vector3 mapOffset = msb.Events.MapOffsets.FirstOrDefault()?.Position.ToXna() ?? Vector3.Zero;



            uint dg1 = 0, dg2 = 0, dg3 = 0, dg4 = 0;

            foreach (var hitName in CurrentCutHits)
            {
                var hit = msb.Parts.Collisions.FirstOrDefault(h => h.Name == hitName);
                dg1 |= hit.DrawGroups[0];
                dg2 |= hit.DrawGroups[1];
                dg3 |= hit.DrawGroups[2];
                dg4 |= hit.DrawGroups[3];
            }

            bool IsThingVisible(uint[] drawGroups)
            {
                return(((drawGroups[0] & dg1) == dg1) &&
                       ((drawGroups[1] & dg2) == dg2) &&
                       ((drawGroups[2] & dg3) == dg3) &&
                       ((drawGroups[3] & dg4) == dg4));
            }

            foreach (var mapPiece in msb.Parts.MapPieces)
            {
                var thisEntityName = CurrentCutOtherBlocks.Count > 0 ? $"A{AreaInt:D2}B{BlockInt:D2}_{mapPiece.Name}"
                        : mapPiece.Name;



                if (IsThingVisible(mapPiece.DrawGroups))
                {
                    Model mdl = null;

                    if (remoModelDict.ContainsKey(thisEntityName))
                    {
                        mdl = remoModelDict[thisEntityName];
                        mdl.AnimContainer = animContainer;
                        mdl.IsRemoModel   = true;
                        mdl.SkeletonFlver.RevertToReferencePose();
                        mdl.SkeletonFlver.MapToSkeleton(animContainer.Skeleton, isRemo: true);
                        mdl.UpdateSkeleton();
                        lock (Scene._lock_ModelLoad_Draw)
                        {
                            Scene.Models.Add(mdl);
                        }
                        continue;
                    }

                    mdl = GameDataManager.LoadMapPiece(AreaInt, BlockInt, 0, 0, int.Parse(mapPiece.ModelName.Substring(1, 4)));
                    mdl.AnimContainer = animContainer;
                    mdl.IsRemoModel   = true;
                    mdl.Name          = thisEntityName;
                    mdl.SkeletonFlver.RevertToReferencePose();

                    mdl.StartTransform.Position = mapPiece.Position.ToXna() - mapOffset;
                    mdl.StartTransform.Rotation = Utils.EulerToQuaternion((mapPiece.Rotation * (SapMath.Pi / 180f)).ToXna());
                    mdl.StartTransform.Scale    = mapPiece.Scale.ToXna();
                    mdl.CurrentTransform        = mdl.StartTransform;

                    mdl.IS_REMO_NOTSKINNED = true;

                    mdl.SkeletonFlver.MapToSkeleton(animContainer.Skeleton, isRemo: true);
                    mdl.UpdateSkeleton();

                    lock (Scene._lock_ModelLoad_Draw)
                    {
                        Scene.Models.Add(mdl);
                    }

                    remoModelDict.Add(thisEntityName, mdl);
                }
            }

            foreach (var mapPiece in msb.Parts.Objects)
            {
                var thisEntityName = CurrentCutOtherBlocks.Count > 0 ? $"A{AreaInt:D2}B{BlockInt:D2}_{mapPiece.Name}"
                        : mapPiece.Name;

                if (IsThingVisible(mapPiece.DrawGroups))
                {
                    Model mdl = null;

                    if (remoModelDict.ContainsKey(thisEntityName))
                    {
                        mdl = remoModelDict[thisEntityName];
                        mdl.AnimContainer = animContainer;
                        mdl.IsRemoModel   = true;
                        mdl.SkeletonFlver.RevertToReferencePose();
                        mdl.SkeletonFlver.MapToSkeleton(animContainer.Skeleton, isRemo: true);
                        mdl.UpdateSkeleton();
                        lock (Scene._lock_ModelLoad_Draw)
                        {
                            Scene.Models.Add(mdl);
                        }
                        continue;
                    }

                    mdl = GameDataManager.LoadObject(mapPiece.ModelName);
                    mdl.AnimContainer = animContainer;
                    mdl.IsRemoModel   = true;
                    mdl.Name          = thisEntityName;

                    mdl.StartTransform.Position = mapPiece.Position.ToXna() - mapOffset;
                    mdl.StartTransform.Rotation = Utils.EulerToQuaternion((mapPiece.Rotation * (SapMath.Pi / 180f)).ToXna());
                    mdl.StartTransform.Scale    = mapPiece.Scale.ToXna();
                    mdl.CurrentTransform        = mdl.StartTransform;

                    mdl.IS_REMO_NOTSKINNED = true;

                    mdl.SkeletonFlver.RevertToReferencePose();
                    mdl.SkeletonFlver.MapToSkeleton(animContainer.Skeleton, isRemo: true);

                    mdl.UpdateSkeleton();

                    lock (Scene._lock_ModelLoad_Draw)
                    {
                        Scene.Models.Add(mdl);
                    }

                    remoModelDict.Add(thisEntityName, mdl);
                }
            }

            lock (Scene._lock_ModelLoad_Draw)
            {
                Scene.Models = Scene.Models.OrderBy(m => m.IS_PLAYER ? 0 : 1).ToList();
            }


            CurrentCut = animName;

            animContainer.ScrubRelative(0);

            List <Model> mdls = null;

            lock (Scene._lock_ModelLoad_Draw)
            {
                mdls = Scene.Models.ToList();
            }

            foreach (var m in mdls)
            {
                m.UpdateSkeleton();
            }

            GFX.World.Update(0);

            Scene.EnableModelDrawing();
            Scene.EnableModelDrawing2();

            ResumeStreamedBGM();

            ViewportInteractor.Graph.MainScreen.REMO_HOTFIX_REQUEST_PLAY_RESUME_NEXT_FRAME = true;

            ViewportInteractor.Graph.MainScreen.HardReset();
        }
        private byte[] ImportAnimToHKX()
        {
            var importedAnim = ImportAnim();

            byte[] finalHkxDataToImport = null;

            var compressed2010Hkx = importedAnim.WriteToSplineCompressedHKX2010Bytes(ImportConfig.RotationQuantizationType, ImportConfig.RotationTolerance);

            if (GameDataManager.GameType == SoulsAssetPipeline.SoulsGames.DS1R)
            {
                finalHkxDataToImport = HavokDowngrade.UpgradeHkx2010to2015(compressed2010Hkx);
            }
            else if (GameDataManager.GameType == SoulsAssetPipeline.SoulsGames.DS1)
            {
                finalHkxDataToImport = compressed2010Hkx;
            }
            else if (GameDataManager.GameType == SoulsAssetPipeline.SoulsGames.DS3)
            {
                HKX.HKAAnimationBinding          hk_binding = null;
                HKX.HKASplineCompressedAnimation hk_anim    = null;
                HKX.HKASkeleton hk_skeleton = null;
                HKX.HKADefaultAnimatedReferenceFrame hk_refFrame = null;

                var hkx = HKX.Read(compressed2010Hkx);

                foreach (var o in hkx.DataSection.Objects)
                {
                    if (o is HKX.HKASkeleton asSkeleton)
                    {
                        hk_skeleton = asSkeleton;
                    }
                    else if (o is HKX.HKAAnimationBinding asBinding)
                    {
                        hk_binding = asBinding;
                    }
                    else if (o is HKX.HKASplineCompressedAnimation asAnim)
                    {
                        hk_anim = asAnim;
                    }
                    else if (o is HKX.HKADefaultAnimatedReferenceFrame asRefFrame)
                    {
                        hk_refFrame = asRefFrame;
                    }
                }

                var root = new HKX2.hkRootLevelContainer();

                var animBinding = new HKX2.hkaAnimationBinding();

                var anim = new HKX2.hkaSplineCompressedAnimation();

                animBinding.m_animation                    = anim;
                animBinding.m_originalSkeletonName         = hk_binding.OriginalSkeletonName;
                animBinding.m_transformTrackToBoneIndices  = hk_binding.TransformTrackToBoneIndices.GetArrayData().Elements.Select(x => x.data).ToList();
                animBinding.m_floatTrackToFloatSlotIndices = new List <short>();
                animBinding.m_partitionIndices             = new List <short>();
                animBinding.m_blendHint                    = (HKX2.BlendHint)(int) hk_binding.BlendHint;

                anim.m_blockDuration        = hk_anim.BlockDuration;
                anim.m_blockInverseDuration = hk_anim.InverseBlockDuration;
                anim.m_data     = hk_anim.Data.GetArrayData().Elements.Select(x => x.data).ToList();
                anim.m_duration = hk_anim.Duration;
                anim.m_endian   = hk_anim.Endian;

                if (hk_refFrame != null)
                {
                    var rootMotion = new HKX2.hkaDefaultAnimatedReferenceFrame();

                    rootMotion.m_duration = hk_refFrame.Duration;
                    rootMotion.m_forward  = hk_refFrame.Forward;
                    rootMotion.m_referenceFrameSamples = new List <System.Numerics.Vector4>();
                    foreach (var rf in hk_refFrame.ReferenceFrameSamples.GetArrayData().Elements)
                    {
                        rootMotion.m_referenceFrameSamples.Add(rf.Vector);
                    }
                    rootMotion.m_up = hk_refFrame.Up;

                    anim.m_extractedMotion = rootMotion;
                }

                anim.m_frameDuration           = hk_anim.FrameDuration;
                anim.m_maskAndQuantizationSize = (int)hk_anim.MaskAndQuantization;
                anim.m_maxFramesPerBlock       = hk_anim.FramesPerBlock;
                anim.m_numberOfFloatTracks     = hk_anim.FloatTrackCount;
                anim.m_numberOfTransformTracks = hk_anim.TransformTrackCount;
                anim.m_numBlocks         = hk_anim.BlockCount;
                anim.m_numFrames         = hk_anim.FrameCount;
                anim.m_floatBlockOffsets = hk_anim.FloatBlockOffsets.GetArrayData().Elements.Select(b => b.data).ToList();
                anim.m_type             = HKX2.AnimationType.HK_SPLINE_COMPRESSED_ANIMATION;
                anim.m_blockOffsets     = hk_anim.BlockOffsets.GetArrayData().Elements.Select(b => b.data).ToList();
                anim.m_floatOffsets     = new List <uint>();
                anim.m_transformOffsets = new List <uint>();

                //TODO: IMPLEMENT ANNOTATION TRACK READ IN LEGACY HKX TO TRANSFER IT TO HKX2

                //anim.m_annotationTracks = new List<HKX2.hkaAnnotationTrack>();
                //for (int i = 0; i < hk_anim.TransformTrackCount; i++)
                //{
                //    var boneIndex = animBinding.m_transformTrackToBoneIndices[i];
                //    string boneName = boneNames[boneIndex];

                //    anim.m_annotationTracks.Add(new HKX2.hkaAnnotationTrack()
                //    {
                //        m_trackName = boneName,
                //        m_annotations = new List<HKX2.hkaAnnotationTrackAnnotation>(),
                //    });
                //}



                var animContainer = new HKX2.hkaAnimationContainer();

                animContainer.m_attachments = new List <HKX2.hkaBoneAttachment>();
                animContainer.m_skins       = new List <HKX2.hkaMeshBinding>();
                animContainer.m_skeletons   = new List <HKX2.hkaSkeleton>();

                animContainer.m_animations = new List <HKX2.hkaAnimation>();
                animContainer.m_animations.Add(anim);

                animContainer.m_bindings = new List <HKX2.hkaAnimationBinding>();
                animContainer.m_bindings.Add(animBinding);

                root.m_namedVariants = new List <HKX2.hkRootLevelContainerNamedVariant>();
                root.m_namedVariants.Add(new HKX2.hkRootLevelContainerNamedVariant()
                {
                    m_className = "hkaAnimationContainer",
                    m_name      = "Merged Animation Container",
                    m_variant   = animContainer
                });

                using (MemoryStream s2 = new MemoryStream())
                {
                    BinaryWriterEx bw = new BinaryWriterEx(false, s2);
                    var            s  = new HKX2.PackFileSerializer();
                    s.Serialize(root, bw);

                    finalHkxDataToImport = s2.ToArray();
                }
            }

            return(finalHkxDataToImport);
        }