sockets absolute rotation and scale

This commit is contained in:
4sval 2023-01-12 15:53:38 +01:00
parent 65d80158db
commit ed5258895f
5 changed files with 40 additions and 56 deletions

@ -1 +1 @@
Subproject commit 996c1c813133c1178b52f5a05667a85019415b0e
Subproject commit d5a1610bbd3ec0a43579fe6151539bc11f673505

View File

@ -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<int, Transform>();
foreach ((_, int boneIndex) in BonesIndexByName)
{
var transforms = new List<Transform>();
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)

View File

@ -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;

View File

@ -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<FGuid> 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()

View File

@ -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");
}
}