mirror of
https://github.com/4sval/FModel.git
synced 2026-06-21 07:20:05 -05:00
sockets absolute rotation and scale
This commit is contained in:
parent
65d80158db
commit
ed5258895f
|
|
@ -1 +1 @@
|
|||
Subproject commit 996c1c813133c1178b52f5a05667a85019415b0e
|
||||
Subproject commit d5a1610bbd3ec0a43579fe6151539bc11f673505
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user