trying to merge 2 skeletons, doesn't fix anything

This commit is contained in:
Asval 2023-08-13 08:10:29 +02:00
parent 51516cd7d7
commit 7d698ea8dd
8 changed files with 202 additions and 129 deletions

View File

@ -7,21 +7,27 @@ public class Bone
public readonly int Index;
public readonly int ParentIndex;
public readonly Transform Rest;
public readonly bool IsVirtual;
public string LoweredParentName;
public List<string> LoweredChildNames;
public int SkeletonIndex = -1;
public readonly List<int> AnimatedBySequences;
public Bone(int i, int p, Transform t)
public Bone(int i, int p, Transform t, bool isVirtual = false)
{
Index = i;
ParentIndex = p;
Rest = t;
IsVirtual = isVirtual;
LoweredChildNames = new List<string>();
AnimatedBySequences = new List<int>();
}
public bool IsRoot => Index == 0 && ParentIndex == -1 && string.IsNullOrEmpty(LoweredParentName);
public bool IsDaron => LoweredChildNames.Count > 0;
public bool IsMapped => SkeletonIndex > -1;
public bool IsAnimated => AnimatedBySequences.Count > 0;
public bool IsNative => Index == SkeletonIndex;

View File

@ -6,6 +6,7 @@ using CUE4Parse_Conversion.Animations.PSA;
using CUE4Parse.UE4.Assets.Exports.Animation;
using FModel.Views.Snooper.Buffers;
using FModel.Views.Snooper.Shading;
using ImGuiNET;
using OpenTK.Graphics.OpenGL4;
using Serilog;
@ -16,13 +17,18 @@ public class Skeleton : IDisposable
private int _handle;
private BufferObject<Matrix4x4> _rest;
private BufferObject<Matrix4x4> _ssbo;
private Matrix4x4[] _boneMatriceAtFrame;
public string Name;
public bool IsAnimated { get; private set; }
public readonly string RootBoneName;
public readonly Dictionary<string, Bone> BonesByLoweredName;
public readonly int BoneCount;
public readonly Dictionary<string, Bone> BonesByLoweredName;
private Matrix4x4[] _boneMatriceAtFrame;
public int AdditionalBoneCount;
public int TotalBoneCount => BoneCount + AdditionalBoneCount;
public bool IsAnimated { get; private set; }
public string SelectedBone;
public Skeleton()
{
@ -35,23 +41,75 @@ public class Skeleton : IDisposable
for (int boneIndex = 0; boneIndex < BoneCount; boneIndex++)
{
var info = referenceSkeleton.FinalRefBoneInfo[boneIndex];
var boneTransform = new Transform
var boneName = info.Name.Text.ToLower();
var bone = new Bone(boneIndex, info.ParentIndex, new Transform
{
Rotation = referenceSkeleton.FinalRefBonePose[boneIndex].Rotation,
Position = referenceSkeleton.FinalRefBonePose[boneIndex].Translation * Constants.SCALE_DOWN_RATIO,
Scale = referenceSkeleton.FinalRefBonePose[boneIndex].Scale3D
};
});
var bone = new Bone(boneIndex, info.ParentIndex, boneTransform);
if (!bone.IsRoot)
{
bone.LoweredParentName =
referenceSkeleton.FinalRefBoneInfo[bone.ParentIndex].Name.Text.ToLower();
bone.Rest.Relation = BonesByLoweredName[bone.LoweredParentName].Rest.Matrix;
bone.LoweredParentName = referenceSkeleton.FinalRefBoneInfo[bone.ParentIndex].Name.Text.ToLower();
var parentBone = BonesByLoweredName[bone.LoweredParentName];
bone.Rest.Relation = parentBone.Rest.Matrix;
parentBone.LoweredChildNames.Add(boneName);
}
BonesByLoweredName[info.Name.Text.ToLower()] = bone;
if (boneIndex == 0) RootBoneName = boneName;
BonesByLoweredName[boneName] = bone;
}
_boneMatriceAtFrame = new Matrix4x4[BoneCount];
}
public void Merge(FReferenceSkeleton referenceSkeleton)
{
for (int boneIndex = 0; boneIndex < referenceSkeleton.FinalRefBoneInfo.Length; boneIndex++)
{
var info = referenceSkeleton.FinalRefBoneInfo[boneIndex];
var boneName = info.Name.Text.ToLower();
if (!BonesByLoweredName.TryGetValue(boneName, out var bone))
{
bone = new Bone(BoneCount + AdditionalBoneCount, info.ParentIndex, new Transform
{
Rotation = referenceSkeleton.FinalRefBonePose[boneIndex].Rotation,
Position = referenceSkeleton.FinalRefBonePose[boneIndex].Translation * Constants.SCALE_DOWN_RATIO,
Scale = referenceSkeleton.FinalRefBonePose[boneIndex].Scale3D
}, true);
if (!bone.IsRoot)
{
bone.LoweredParentName = referenceSkeleton.FinalRefBoneInfo[bone.ParentIndex].Name.Text.ToLower();
var parentBone = BonesByLoweredName[bone.LoweredParentName];
bone.Rest.Relation = parentBone.Rest.Matrix;
parentBone.LoweredChildNames.Add(boneName);
}
BonesByLoweredName[boneName] = bone;
AdditionalBoneCount++;
}
}
_boneMatriceAtFrame = new Matrix4x4[BoneCount + AdditionalBoneCount];
}
public void Setup()
{
_handle = GL.CreateProgram();
_rest = new BufferObject<Matrix4x4>(BoneCount, BufferTarget.ShaderStorageBuffer);
foreach (var bone in BonesByLoweredName.Values)
{
if (bone.IsVirtual) break;
_rest.Update(bone.Index, bone.Rest.Matrix);
}
_rest.Unbind();
_ssbo = new BufferObject<Matrix4x4>(TotalBoneCount, BufferTarget.ShaderStorageBuffer);
_ssbo.UpdateRange(Matrix4x4.Identity);
}
public void Animate(CAnimSet animation)
@ -101,28 +159,7 @@ public class Skeleton : IDisposable
if (!full) return;
IsAnimated = false;
_ssbo.UpdateRange(BoneCount, Matrix4x4.Identity);
}
public void Setup()
{
_handle = GL.CreateProgram();
_rest = new BufferObject<Matrix4x4>(BoneCount, BufferTarget.ShaderStorageBuffer);
foreach (var bone in BonesByLoweredName.Values)
{
_rest.Update(bone.Index, bone.Rest.Matrix);
}
_rest.Unbind();
_ssbo = new BufferObject<Matrix4x4>(BoneCount, BufferTarget.ShaderStorageBuffer);
_ssbo.UpdateRange(BoneCount, Matrix4x4.Identity);
_boneMatriceAtFrame = new Matrix4x4[BoneCount];
for (int boneIndex = 0; boneIndex < _boneMatriceAtFrame.Length; boneIndex++)
{
_boneMatriceAtFrame[boneIndex] = Matrix4x4.Identity;
}
_ssbo.UpdateRange(Matrix4x4.Identity);
}
public void UpdateAnimationMatrices(Animation animation, bool rotationOnly)
@ -191,14 +228,7 @@ public class Skeleton : IDisposable
return (s, f);
}
public Matrix4x4 GetBoneMatrix(Bone bone)
{
_ssbo.Bind();
var anim = _ssbo.Get(bone.Index);
_ssbo.Unbind();
return IsAnimated ? anim : bone.Rest.Matrix;
}
public Matrix4x4 GetBoneMatrix(Bone bone) => IsAnimated ? _boneMatriceAtFrame[bone.Index] : bone.Rest.Matrix;
public void Render(Shader shader)
{
@ -208,6 +238,33 @@ public class Skeleton : IDisposable
_rest.BindBufferBase(2);
}
public void ImGuiBoneHierarchy()
{
DrawBoneTree(RootBoneName, BonesByLoweredName[RootBoneName]);
}
private void DrawBoneTree(string boneName, Bone bone)
{
var flags = ImGuiTreeNodeFlags.OpenOnArrow | ImGuiTreeNodeFlags.OpenOnDoubleClick | ImGuiTreeNodeFlags.SpanAvailWidth;
if (boneName == SelectedBone) flags |= ImGuiTreeNodeFlags.Selected;
if (bone.IsVirtual) flags |= ImGuiTreeNodeFlags.Leaf;
else if (!bone.IsDaron) flags |= ImGuiTreeNodeFlags.Bullet;
ImGui.SetNextItemOpen(bone.LoweredChildNames.Count <= 1, ImGuiCond.Appearing);
var open = ImGui.TreeNodeEx(boneName, flags);
if (ImGui.IsItemClicked() && !ImGui.IsItemToggledOpen())
SelectedBone = boneName;
if (open)
{
foreach (var name in bone.LoweredChildNames)
{
DrawBoneTree(name, BonesByLoweredName[name]);
}
ImGui.TreePop();
}
}
public void Dispose()
{
BonesByLoweredName.Clear();

View File

@ -9,6 +9,8 @@ public class BufferObject<TDataType> : IDisposable where TDataType : unmanaged
private readonly int _sizeOf;
private readonly BufferTarget _bufferTarget;
public readonly int Size;
private unsafe BufferObject(BufferTarget bufferTarget)
{
_bufferTarget = bufferTarget;
@ -20,14 +22,17 @@ public class BufferObject<TDataType> : IDisposable where TDataType : unmanaged
public BufferObject(TDataType[] data, BufferTarget bufferTarget) : this(bufferTarget)
{
GL.BufferData(bufferTarget, data.Length * _sizeOf, data, BufferUsageHint.StaticDraw);
Size = data.Length;
GL.BufferData(bufferTarget, Size * _sizeOf, data, BufferUsageHint.StaticDraw);
}
public BufferObject(int length, BufferTarget bufferTarget) : this(bufferTarget)
{
GL.BufferData(bufferTarget, length * _sizeOf, IntPtr.Zero, BufferUsageHint.DynamicDraw);
Size = length;
GL.BufferData(bufferTarget, Size * _sizeOf, IntPtr.Zero, BufferUsageHint.DynamicDraw);
}
public void UpdateRange(TDataType data) => UpdateRange(Size, data);
public void UpdateRange(int count, TDataType data)
{
Bind();

View File

@ -141,6 +141,7 @@ public class Model : IDisposable
if (HasSkeleton && export.Skeleton.TryLoad(out USkeleton skeleton))
{
Skeleton.Name = skeleton.Name;
// Skeleton.Merge(skeleton.ReferenceSkeleton);
sockets.AddRange(skeleton.Sockets);
}
@ -255,6 +256,8 @@ public class Model : IDisposable
var worldMatrix = UpdateMatrices();
foreach (var socket in Sockets)
{
if (!socket.IsDaron) continue;
var boneMatrix = Matrix4x4.Identity;
if (HasSkeleton && Skeleton.BonesByLoweredName.TryGetValue(socket.BoneName.Text.ToLower(), out var bone))
boneMatrix = Skeleton.GetBoneMatrix(bone);
@ -415,6 +418,7 @@ public class Model : IDisposable
GL.DrawElementsInstanced(PrimitiveType.Triangles, section.FacesCount, DrawElementsType.UnsignedInt, section.FirstFaceIndexPtr, TransformsCount);
}
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
_vao.Unbind();
if (IsSelected)

View File

@ -21,6 +21,7 @@ public class Socket : IDisposable
public readonly bool IsVirtual;
public readonly List<SocketAttachementInfo> AttachedModels;
public bool IsDaron => AttachedModels.Count > 0;
private Socket()
{

View File

@ -179,7 +179,7 @@ public class Renderer : IDisposable
if (notifyClass.TryGetValue(out FVector scale, "Scale"))
t.Scale = scale;
var s = new Socket($"TL_{addedModel.Name}", socketName, t, true);
var s = new Socket($"ANIM_{addedModel.Name}", socketName, t, true);
model.Sockets.Add(s);
addedModel.AttachModel(model, s, new SocketAttachementInfo { Guid = guid, Instance = addedModel.SelectedInstance });
}

View File

@ -67,6 +67,7 @@ public class SnimGui
private Vector2 _outlinerSize;
private bool _ti_open;
private bool _bh_open;
private bool _viewportFocus;
private readonly Vector4 _accentColor = new (0.125f, 0.42f, 0.831f, 1.0f);
@ -106,6 +107,7 @@ public class SnimGui
DrawModals(s);
if (_ti_open) DrawTextureInspector(s);
if (_bh_open) DrawBoneHierarchy(s);
Controller.Render();
}
@ -210,52 +212,43 @@ public class SnimGui
ImGui.EndTable();
}
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
if (ImGui.CollapsingHeader("Editor"))
ImGui.SeparatorText("Editor");
if (ImGui.BeginTable("world_editor", 2))
{
if (ImGui.BeginTable("world_editor", 2))
{
Layout("Skybox");ImGui.PushID(1);
ImGui.Checkbox("", ref s.Renderer.ShowSkybox);
ImGui.PopID();Layout("Grid");ImGui.PushID(2);
ImGui.Checkbox("", ref s.Renderer.ShowGrid);
ImGui.PopID();Layout("Lights");ImGui.PushID(3);
ImGui.Checkbox("", ref s.Renderer.ShowLights);
ImGui.PopID();Layout("Animate With Rotation Only");ImGui.PushID(4);
ImGui.Checkbox("", ref s.Renderer.AnimateWithRotationOnly);
ImGui.PopID();Layout("Vertex Colors");ImGui.PushID(5);
var c = (int) s.Renderer.Color;
ImGui.Combo("vertex_colors", ref c,
"Default\0Sections\0Colors\0Normals\0Texture Coordinates\0");
s.Renderer.Color = (VertexColor) c;
ImGui.PopID();
Layout("Skybox");ImGui.PushID(1);
ImGui.Checkbox("", ref s.Renderer.ShowSkybox);
ImGui.PopID();Layout("Grid");ImGui.PushID(2);
ImGui.Checkbox("", ref s.Renderer.ShowGrid);
ImGui.PopID();Layout("Lights");ImGui.PushID(3);
ImGui.Checkbox("", ref s.Renderer.ShowLights);
ImGui.PopID();Layout("Animate With Rotation Only");ImGui.PushID(4);
ImGui.Checkbox("", ref s.Renderer.AnimateWithRotationOnly);
ImGui.PopID();Layout("Vertex Colors");ImGui.PushID(5);
var c = (int) s.Renderer.Color;
ImGui.Combo("vertex_colors", ref c,
"Default\0Sections\0Colors\0Normals\0Texture Coordinates\0");
s.Renderer.Color = (VertexColor) c;
ImGui.PopID();
ImGui.EndTable();
}
ImGui.SeparatorText("Camera");
s.Renderer.CameraOp.ImGuiCamera();
ImGui.SeparatorText("Lights");
for (int i = 0; i < s.Renderer.Options.Lights.Count; i++)
{
var light = s.Renderer.Options.Lights[i];
var id = s.Renderer.Options.TryGetModel(light.Model, out var lightModel) ? lightModel.Name : "None";
id += $"##{i}";
if (ImGui.TreeNode(id) && ImGui.BeginTable(id, 2))
{
s.Renderer.Options.SelectModel(light.Model);
light.ImGuiLight();
ImGui.EndTable();
}
}
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
if (ImGui.CollapsingHeader("Camera"))
{
s.Renderer.CameraOp.ImGuiCamera();
}
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
if (ImGui.CollapsingHeader("Lights"))
{
for (int i = 0; i < s.Renderer.Options.Lights.Count; i++)
{
var light = s.Renderer.Options.Lights[i];
var id = s.Renderer.Options.TryGetModel(light.Model, out var lightModel) ? lightModel.Name : "None";
id += $"##{i}";
if (ImGui.TreeNode(id) && ImGui.BeginTable(id, 2))
{
s.Renderer.Options.SelectModel(light.Model);
light.ImGuiLight();
ImGui.EndTable();
ImGui.TreePop();
}
ImGui.TreePop();
}
}
}
@ -461,6 +454,11 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio
_swapper.Value = true;
}
}
if (ImGui.MenuItem("Bone Hierarchy", model.HasSkeleton))
{
_bh_open = true;
ImGui.SetWindowFocus("Bone Hierarchy");
}
if (ImGui.MenuItem("Teleport To"))
{
var instancePos = model.Transforms[model.SelectedInstance].Matrix.Translation;
@ -665,56 +663,50 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio
ImGui.SameLine(); ImGui.AlignTextToFramePadding(); ImGui.Text(material.Name);
ImGui.Spacing();
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
if (ImGui.CollapsingHeader("Parameters"))
{
material.ImGuiParameters();
}
ImGui.SeparatorText("Parameters");
material.ImGuiParameters();
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
if (ImGui.CollapsingHeader("Textures") && material.ImGuiTextures(icons, model))
ImGui.SeparatorText("Textures");
if (material.ImGuiTextures(icons, model))
{
_ti_open = true;
ImGui.SetWindowFocus("Texture Inspector");
}
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
if (ImGui.CollapsingHeader("Properties"))
ImGui.SeparatorText("Properties");
NoFramePaddingOnY(() =>
{
NoFramePaddingOnY(() =>
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
if (ImGui.TreeNode("Base"))
{
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
if (ImGui.TreeNode("Base"))
{
material.ImGuiBaseProperties("base");
ImGui.TreePop();
}
material.ImGuiBaseProperties("base");
ImGui.TreePop();
}
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
if (ImGui.TreeNode("Scalars"))
{
material.ImGuiDictionaries("scalars", material.Parameters.Scalars, true);
ImGui.TreePop();
}
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
if (ImGui.TreeNode("Switches"))
{
material.ImGuiDictionaries("switches", material.Parameters.Switches, true);
ImGui.TreePop();
}
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
if (ImGui.TreeNode("Colors"))
{
material.ImGuiColors(material.Parameters.Colors);
ImGui.TreePop();
}
if (ImGui.TreeNode("All Textures"))
{
material.ImGuiDictionaries("textures", material.Parameters.Textures);
ImGui.TreePop();
}
});
}
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
if (ImGui.TreeNode("Scalars"))
{
material.ImGuiDictionaries("scalars", material.Parameters.Scalars, true);
ImGui.TreePop();
}
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
if (ImGui.TreeNode("Switches"))
{
material.ImGuiDictionaries("switches", material.Parameters.Switches, true);
ImGui.TreePop();
}
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
if (ImGui.TreeNode("Colors"))
{
material.ImGuiColors(material.Parameters.Colors);
ImGui.TreePop();
}
if (ImGui.TreeNode("All Textures"))
{
material.ImGuiDictionaries("textures", material.Parameters.Textures);
ImGui.TreePop();
}
});
}
private void DrawTextureInspector(Snooper s)
@ -728,6 +720,15 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio
ImGui.End(); // if window is collapsed
}
private void DrawBoneHierarchy(Snooper s)
{
if (ImGui.Begin("Bone Hierarchy", ref _bh_open, ImGuiWindowFlags.NoScrollbar) && s.Renderer.Options.TryGetModel(out var model))
{
model.Skeleton.ImGuiBoneHierarchy();
}
ImGui.End(); // if window is collapsed
}
private void Draw3DViewport(Snooper s)
{
ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero);

View File

@ -113,7 +113,6 @@ public class Snooper : GameWindow
private void ClearWhatHasBeenDrawn()
{
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit);
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
}
protected override void OnRenderFrame(FrameEventArgs args)