diff --git a/CUE4Parse b/CUE4Parse index 996c1c81..d5a1610b 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 996c1c813133c1178b52f5a05667a85019415b0e +Subproject commit d5a1610bbd3ec0a43579fe6151539bc11f673505 diff --git a/FModel/Views/Snooper/Models/Animations/Skeleton.cs b/FModel/Views/Snooper/Models/Animations/Skeleton.cs index d03e610c..1e0162a1 100644 --- a/FModel/Views/Snooper/Models/Animations/Skeleton.cs +++ b/FModel/Views/Snooper/Models/Animations/Skeleton.cs @@ -3,11 +3,8 @@ using System.Collections.Generic; using System.Numerics; using CUE4Parse_Conversion.Animations; using CUE4Parse.UE4.Assets.Exports.Animation; -using CUE4Parse.UE4.Assets.Exports.SkeletalMesh; -using CUE4Parse.UE4.Objects.Core.Math; using CUE4Parse.UE4.Objects.UObject; using FModel.Views.Snooper.Shading; -using Serilog; namespace FModel.Views.Snooper.Models.Animations; @@ -33,38 +30,8 @@ public class Skeleton : IDisposable BonesIndexByName = UnrealSkeleton.ReferenceSkeleton.FinalNameToIndexMap; BonesTransformByIndex = new Dictionary(); - foreach ((_, int boneIndex) in BonesIndexByName) - { - var transforms = new List(); - var parentBoneIndex = boneIndex; - while (parentBoneIndex > -1) - { - var parentFound = BonesTransformByIndex.TryGetValue(parentBoneIndex, out var boneTransform); - if (!parentFound) - { - var bone = UnrealSkeleton.ReferenceSkeleton.FinalRefBonePose[parentBoneIndex]; - boneTransform = new Transform - { - Relation = transform.Matrix, - Rotation = bone.Rotation, - Position = bone.Translation * Constants.SCALE_DOWN_RATIO, - Scale = bone.Scale3D - }; - } + UpdateBoneMatrices(transform.Matrix); - parentBoneIndex = UnrealSkeleton.ReferenceSkeleton.FinalRefBoneInfo[parentBoneIndex].ParentIndex; - transforms.Add(boneTransform); - if (parentFound) parentBoneIndex = -1; // the parent transform is already relative to all its parent so we can just skip - } - - for (int j = transforms.Count - 2; j > -1; j--) - { - transforms[j].Relation *= transforms[j + 1].Matrix; - } - - BonesTransformByIndex[boneIndex] = transforms[0]; - transforms.Clear(); - } IsLoaded = true; } @@ -73,13 +40,29 @@ public class Skeleton : IDisposable Anim = new Animation(anim, BonesIndexByName, BonesTransformByIndex); } - public void UpdateRootBoneMatrix(Matrix4x4 delta) + public void UpdateBoneMatrices(Matrix4x4 matrix) { - // Matrix4x4.Decompose(delta, out var scale, out var rotation, out var position); - // Log.Logger.Information("Update"); + foreach (var boneIndex in BonesIndexByName.Values) + { + var bone = UnrealSkeleton.ReferenceSkeleton.FinalRefBonePose[boneIndex]; + var parentIndex = UnrealSkeleton.ReferenceSkeleton.FinalRefBoneInfo[boneIndex].ParentIndex; - // TODO: support for rotation and scale - BonesTransformByIndex[0].Relation.Translation += delta.Translation; + if (!BonesTransformByIndex.TryGetValue(boneIndex, out var boneTransform)) + { + boneTransform = new Transform + { + Rotation = bone.Rotation, + Position = bone.Translation * Constants.SCALE_DOWN_RATIO, + Scale = bone.Scale3D + }; + } + + if (!BonesTransformByIndex.TryGetValue(parentIndex, out var parentTransform)) + parentTransform = new Transform { Relation = matrix }; + + boneTransform.Relation = parentTransform.Matrix; + BonesTransformByIndex[boneIndex] = boneTransform; + } } public void SetUniform(Shader shader) diff --git a/FModel/Views/Snooper/Models/Model.cs b/FModel/Views/Snooper/Models/Model.cs index 2ab68ed1..a6d470d5 100644 --- a/FModel/Views/Snooper/Models/Model.cs +++ b/FModel/Views/Snooper/Models/Model.cs @@ -233,17 +233,14 @@ public class Model : IDisposable public void UpdateMatrices(Options options) { UpdateMatrices(); - if (!HasSockets) - return; - - for (int s = 0; s < Sockets.Length; s++) + foreach (var socket in Sockets) { - for (int g = 0; g < Sockets[s].AttachedModels.Count; g++) + foreach (var attached in socket.AttachedModels) { - if (!options.TryGetModel(Sockets[s].AttachedModels[g], out var attachedModel)) + if (!options.TryGetModel(attached, out var attachedModel)) continue; - attachedModel.Transforms[attachedModel.SelectedInstance].Relation = Sockets[s].Transform.Matrix; + attachedModel.Transforms[attachedModel.SelectedInstance].Relation = socket.Transform.Matrix; attachedModel.UpdateMatrices(); } } @@ -257,12 +254,16 @@ public class Model : IDisposable _matrixVbo.Update(SelectedInstance, matrix); _matrixVbo.Unbind(); - var delta = matrix - _previousMatrix; + if (HasSkeleton) Skeleton.UpdateBoneMatrices(matrix); foreach (var socket in Sockets) { - socket.UpdateSocketMatrix(delta); + if (!HasSkeleton || + !Skeleton.BonesIndexByName.TryGetValue(socket.BoneName.Text, out var boneIndex) || + !Skeleton.BonesTransformByIndex.TryGetValue(boneIndex, out var boneTransform)) + boneTransform = Transforms[SelectedInstance]; + + socket.UpdateSocketMatrix(boneTransform.Matrix); } - if (HasSkeleton) Skeleton.UpdateRootBoneMatrix(delta); _previousMatrix = matrix; } @@ -276,7 +277,7 @@ public class Model : IDisposable public void AttachModel(Model attachedTo, Socket socket) { - _attachedTo = $"'{socket.Name}' from '{attachedTo.Name}'{(socket.Bone.HasValue ? $" at '{socket.Bone}'" : "")}"; + _attachedTo = $"'{socket.Name}' from '{attachedTo.Name}'{(!socket.BoneName.IsNone ? $" at '{socket.BoneName}'" : "")}"; attachedTo._attachedFor.Add($"'{Name}'"); // reset PRS to 0 so it's attached to the actual position (can be transformed relative to the socket later by the user) Transforms[SelectedInstance].Position = FVector.ZeroVector; diff --git a/FModel/Views/Snooper/Models/Socket.cs b/FModel/Views/Snooper/Models/Socket.cs index a31a7814..0a76057e 100644 --- a/FModel/Views/Snooper/Models/Socket.cs +++ b/FModel/Views/Snooper/Models/Socket.cs @@ -11,7 +11,7 @@ namespace FModel.Views.Snooper.Models; public class Socket : IDisposable { public readonly string Name; - public readonly FName? Bone; + public readonly FName BoneName; public readonly Transform Transform; public readonly List AttachedModels; @@ -34,17 +34,16 @@ public class Socket : IDisposable public Socket(USkeletalMeshSocket socket, Transform transform) : this() { Name = socket.SocketName.Text; - Bone = socket.BoneName; + BoneName = socket.BoneName; Transform.Relation = transform.Matrix; Transform.Rotation = socket.RelativeRotation.Quaternion(); Transform.Position = socket.RelativeLocation * Constants.SCALE_DOWN_RATIO; Transform.Scale = socket.RelativeScale; } - public void UpdateSocketMatrix(Matrix4x4 delta) + public void UpdateSocketMatrix(Matrix4x4 matrix) { - // TODO: support for rotation and scale - Transform.Relation.Translation += delta.Translation; + Transform.Relation = matrix; } public void Dispose() diff --git a/FModel/Views/Snooper/SnimGui.cs b/FModel/Views/Snooper/SnimGui.cs index e94db7e0..89f77321 100644 --- a/FModel/Views/Snooper/SnimGui.cs +++ b/FModel/Views/Snooper/SnimGui.cs @@ -692,6 +692,7 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio var guid = s.Renderer.Picking.ReadPixel(ImGui.GetMousePos(), ImGui.GetCursorScreenPos(), size); s.Renderer.Options.SelectModel(guid); ImGui.SetWindowFocus("Outliner"); + ImGui.SetWindowFocus("Details"); } }