Skip to content

Commit

Permalink
skeleton tree + fixed skeleton bones incorrect relation
Browse files Browse the repository at this point in the history
  • Loading branch information
4sval committed Aug 20, 2023
1 parent 1aa45b1 commit 841f40e
Show file tree
Hide file tree
Showing 20 changed files with 843 additions and 593 deletions.
4 changes: 4 additions & 0 deletions FModel/FModel.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@
<None Remove="Resources\picking.vert" />
<None Remove="Resources\light.frag" />
<None Remove="Resources\light.vert" />
<None Remove="Resources\bone.frag" />
<None Remove="Resources\bone.vert" />
</ItemGroup>

<ItemGroup>
Expand All @@ -130,6 +132,8 @@
<EmbeddedResource Include="Resources\picking.vert" />
<EmbeddedResource Include="Resources\light.frag" />
<EmbeddedResource Include="Resources\light.vert" />
<EmbeddedResource Include="Resources\bone.frag" />
<EmbeddedResource Include="Resources\bone.vert" />
</ItemGroup>

<ItemGroup>
Expand Down
10 changes: 10 additions & 0 deletions FModel/Resources/bone.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#version 460 core

in vec3 fPos;

out vec4 FragColor;

void main()
{
FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
23 changes: 23 additions & 0 deletions FModel/Resources/bone.vert
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#version 460 core

layout (location = 1) in vec3 vPos;
layout (location = 9) in mat4 vInstanceMatrix;

uniform mat4 uView;
uniform mat4 uProjection;
uniform bool uSocket;

out vec3 fPos;

void main()
{
float scale = 0.0075;
mat4 result;
result[0] = vec4(scale, 0.0, 0.0, 0.0);
result[1] = vec4(0.0, scale, 0.0, 0.0);
result[2] = vec4(0.0, 0.0, scale, 0.0);
result[3] = vInstanceMatrix[3];

gl_Position = uProjection * uView * result * vec4(vPos, 1.0);
fPos = vec3(result * vec4(vPos, 1.0));
}
12 changes: 8 additions & 4 deletions FModel/Views/Snooper/Animations/Animation.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Numerics;
using CUE4Parse_Conversion;
using CUE4Parse_Conversion.Animations.PSA;
using CUE4Parse.UE4.Assets.Exports;
using CUE4Parse.UE4.Objects.Core.Misc;
using FModel.Settings;
using FModel.Views.Snooper.Models;
using ImGuiNET;

namespace FModel.Views.Snooper.Animations;
Expand Down Expand Up @@ -118,19 +122,19 @@ private void Popup(Snooper s, Save saver, int i)
foreach ((var guid, var model) in s.Renderer.Options.Models)
{
var selected = AttachedModels.Contains(guid);
if (ImGui.MenuItem(model.Name, null, selected, (model.HasSkeleton && !model.Skeleton.IsAnimated) || selected))
if (model is SkeletalModel skeletalModel && ImGui.MenuItem(model.Name, null, selected, !skeletalModel.Skeleton.IsAnimated || selected))
{
if (selected) AttachedModels.Remove(guid); else AttachedModels.Add(guid);
model.Skeleton.ResetAnimatedData(true);
if (!selected) model.Skeleton.Animate(UnrealAnim);
skeletalModel.Skeleton.ResetAnimatedData(true);
if (!selected) skeletalModel.Skeleton.Animate(UnrealAnim);
}
}
ImGui.EndMenu();
}
if (ImGui.MenuItem("Save"))
{
s.WindowShouldFreeze(true);
saver.Value = s.Renderer.Options.TrySave(_export, out saver.Label, out saver.Path);
saver.Value = new Exporter(_export).TryWriteToDir(new DirectoryInfo(UserSettings.Default.ModelDirectory), out saver.Label, out saver.Path);
s.WindowShouldFreeze(false);
}
ImGui.Separator();
Expand Down
2 changes: 1 addition & 1 deletion FModel/Views/Snooper/Animations/Bone.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace FModel.Views.Snooper.Animations;
public class Bone
{
public readonly int Index;
public readonly int ParentIndex;
public int ParentIndex;
public readonly Transform Rest;
public readonly bool IsVirtual;

Expand Down
39 changes: 29 additions & 10 deletions FModel/Views/Snooper/Animations/Skeleton.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class Skeleton : IDisposable
private int TotalBoneCount => BoneCount + _additionalBoneCount;

public bool IsAnimated { get; private set; }
public bool DrawAllBones;
public string SelectedBone;

public Skeleton()
Expand Down Expand Up @@ -62,6 +63,7 @@ public Skeleton(FReferenceSkeleton referenceSkeleton) : this()
if (boneIndex == 0) SelectedBone = boneName;
BonesByLoweredName[boneName] = bone;
}
_breadcrumb.Add(SelectedBone);
_boneMatriceAtFrame = new Matrix4x4[BoneCount];
}

Expand All @@ -74,7 +76,7 @@ public void Merge(FReferenceSkeleton referenceSkeleton)

if (!BonesByLoweredName.TryGetValue(boneName, out var bone))
{
bone = new Bone(BoneCount + _additionalBoneCount, info.ParentIndex, new Transform
bone = new Bone(BoneCount + _additionalBoneCount, -1, new Transform
{
Rotation = referenceSkeleton.FinalRefBonePose[boneIndex].Rotation,
Position = referenceSkeleton.FinalRefBonePose[boneIndex].Translation * Constants.SCALE_DOWN_RATIO,
Expand All @@ -83,9 +85,10 @@ public void Merge(FReferenceSkeleton referenceSkeleton)

if (!bone.IsRoot)
{
bone.LoweredParentName = referenceSkeleton.FinalRefBoneInfo[bone.ParentIndex].Name.Text.ToLower();
bone.LoweredParentName = referenceSkeleton.FinalRefBoneInfo[info.ParentIndex].Name.Text.ToLower();
var parentBone = BonesByLoweredName[bone.LoweredParentName];

bone.ParentIndex = parentBone.Index;
bone.Rest.Relation = parentBone.Rest.Matrix;
parentBone.LoweredChildNames.Add(boneName);
}
Expand Down Expand Up @@ -241,21 +244,37 @@ public void Render(Shader shader)

public void ImGuiBoneBreadcrumb()
{
for (int i = _breadcrumb.Count - 1; i >= 0; i--)
var p1 = ImGui.GetCursorScreenPos();
var canvasSize = ImGui.GetContentRegionAvail() with { Y = 20 };
var p2 = p1 + canvasSize;
ImGui.BeginChild("skeleton_breadcrumb", canvasSize);

var drawList = ImGui.GetWindowDrawList();
drawList.AddRectFilled(p1, p2, 0xFF242424);

var x = p1.X;
var y = p1.Y + (p2.Y - p1.Y) / 2;
for (int i = Math.Min(_breadcrumb.Count - 1, 5); i >= 1; i--)
{
var boneName = _breadcrumb[i];
ImGui.SameLine();
var clicked = ImGui.SmallButton(boneName);
ImGui.SameLine();
ImGui.Text(">");
var size = ImGui.CalcTextSize(boneName);
var position = new Vector2(x + 5, y - size.Y / 2f);

if (clicked)
ImGui.SetCursorScreenPos(position);
if (ImGui.InvisibleButton($"breakfast_{boneName}", size, ImGuiButtonFlags.MouseButtonLeft))
{
SelectedBone = boneName;
_breadcrumb.RemoveRange(0, i + 1);
_breadcrumb.RemoveRange(0, i);
break;
}

drawList.AddText(position, i == 1 || ImGui.IsItemHovered() ? 0xFFFFFFFF : 0xA0FFFFFF, boneName);
x += size.X + 7.5f;
drawList.AddText(position with { X = x }, 0xA0FFFFFF, ">");
x += 7.5f;
}

ImGui.EndChild();
}

public void ImGuiBoneHierarchy()
Expand All @@ -276,7 +295,7 @@ private void DrawBoneTree(string boneName, Bone bone)

ImGui.SetNextItemOpen(bone.LoweredChildNames.Count <= 1 || flags.HasFlag(ImGuiTreeNodeFlags.Selected), ImGuiCond.Appearing);
var open = ImGui.TreeNodeEx(boneName, flags);
if (ImGui.IsItemClicked() && !ImGui.IsItemToggledOpen())
if (ImGui.IsItemClicked() && !ImGui.IsItemToggledOpen() && bone.IsDaron)
{
SelectedBone = boneName;
_breadcrumb.Clear();
Expand Down
6 changes: 3 additions & 3 deletions FModel/Views/Snooper/Buffers/PickingTexture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,20 +54,20 @@ public void Setup()
Bind(0);
}

public void Render(Matrix4x4 viewMatrix, Matrix4x4 projMatrix, IDictionary<FGuid,Model> models)
public void Render(Matrix4x4 viewMatrix, Matrix4x4 projMatrix, IDictionary<FGuid, UModel> models)
{
Bind();
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

_shader.Render(viewMatrix, projMatrix);
foreach ((FGuid guid, Model model) in models)
foreach ((var guid, var model) in models)
{
_shader.SetUniform("uA", guid.A);
_shader.SetUniform("uB", guid.B);
_shader.SetUniform("uC", guid.C);
_shader.SetUniform("uD", guid.D);

if (!model.Show) continue;
if (!model.IsVisible) continue;
model.PickingRender(_shader);
}

Expand Down
57 changes: 57 additions & 0 deletions FModel/Views/Snooper/Models/Attachment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System.Collections.Generic;
using System.Numerics;
using CUE4Parse.UE4.Objects.Core.Math;

namespace FModel.Views.Snooper.Models;

public class Attachment
{
private string _modelName;
private string _attachedTo;
private readonly List<string> _attachedFor;
private Matrix4x4 _oldRelation;

public bool IsAttached => _attachedTo.Length > 0;
public bool IsAttachment => _attachedFor.Count > 0;

public string Icon => IsAttachment ? "link_has" : IsAttached ? "link_on" : "link_off";
public string Tooltip => IsAttachment ? $"Is Attachment For:\n{string.Join("\n", _attachedFor)}" : IsAttached ? $"Is Attached To {_attachedTo}" : "Not Attached To Any Socket Nor Attachment For Any Model";

public Attachment(string modelName)
{
_modelName = modelName;
_attachedTo = string.Empty;
_attachedFor = new List<string>();
}

public void Attach(UModel attachedTo, Transform transform, Socket socket, SocketAttachementInfo info)
{
socket.AttachedModels.Add(info);

_attachedTo = $"'{socket.Name}' from '{attachedTo.Name}'{(!socket.BoneName.IsNone ? $" at '{socket.BoneName}'" : "")}";
attachedTo.Attachments.AddAttachment(_modelName);

// reset PRS to 0 so it's attached to the actual position (can be transformed relative to the socket later by the user)
_oldRelation = transform.Relation;
transform.Position = FVector.ZeroVector;
transform.Rotation = FQuat.Identity;
transform.Scale = FVector.OneVector;
}

public void Detach(UModel attachedTo, Transform transform, Socket socket, SocketAttachementInfo info)
{
socket.AttachedModels.Remove(info);
SafeDetach(attachedTo, transform);
}

public void SafeDetach(UModel attachedTo, Transform transform)
{
_attachedTo = string.Empty;
attachedTo.Attachments.RemoveAttachment(_modelName);

transform.Relation = _oldRelation;
}

public void AddAttachment(string modelName) => _attachedFor.Add($"'{modelName}'");
public void RemoveAttachment(string modelName) => _attachedFor.Remove($"'{modelName}'");
}
52 changes: 52 additions & 0 deletions FModel/Views/Snooper/Models/BoneModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using CUE4Parse_Conversion.Meshes.PSK;
using FModel.Views.Snooper.Shading;
using OpenTK.Graphics.OpenGL4;

namespace FModel.Views.Snooper.Models;

public class BoneModel : UModel
{
public BoneModel(CStaticMesh staticMesh)
{
var lod = staticMesh.LODs[LodLevel];

Indices = new uint[lod.Indices.Value.Length];
for (int i = 0; i < Indices.Length; i++)
{
Indices[i] = (uint) lod.Indices.Value[i];
}

Vertices = new float[lod.NumVerts * VertexSize];
for (int i = 0; i < lod.Verts.Length; i++)
{
var count = 0;
var baseIndex = i * VertexSize;
var vert = lod.Verts[i];
Vertices[baseIndex + count++] = vert.Position.X * Constants.SCALE_DOWN_RATIO;
Vertices[baseIndex + count++] = vert.Position.Z * Constants.SCALE_DOWN_RATIO;
Vertices[baseIndex + count++] = vert.Position.Y * Constants.SCALE_DOWN_RATIO;
}

Materials = new Material[1];
Materials[0] = new Material { IsUsed = true };

Sections = new Section[1];
Sections[0] = new Section(0, Indices.Length, 0);

Box = staticMesh.BoundingBox * Constants.SCALE_DOWN_RATIO;
}

public override void Render(Shader shader, bool outline = false)
{
GL.Disable(EnableCap.DepthTest);

Vao.Bind();
foreach (var section in Sections)
{
GL.DrawElementsInstanced(PrimitiveType.LineStrip, section.FacesCount, DrawElementsType.UnsignedInt, section.FirstFaceIndexPtr, TransformsCount);
}
Vao.Unbind();

GL.Enable(EnableCap.DepthTest);
}
}
14 changes: 14 additions & 0 deletions FModel/Views/Snooper/Models/EAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace FModel.Views.Snooper.Models;

public enum EAttribute
{
Index,
Position,
Normals,
Tangent,
UVs,
Layer,
Colors,
BonesId,
BonesWeight
}
38 changes: 38 additions & 0 deletions FModel/Views/Snooper/Models/IRenderableModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Numerics;
using FModel.Views.Snooper.Buffers;
using FModel.Views.Snooper.Shading;

namespace FModel.Views.Snooper.Models;

public interface IRenderableModel : IDisposable
{
protected int Handle { get; set; }
protected BufferObject<uint> Ebo { get; set; }
protected BufferObject<float> Vbo { get; set; }
protected BufferObject<Matrix4x4> MatrixVbo { get; set; }
protected VertexArrayObject<float, uint> Vao { get; set; }

public string Path { get; }
public string Name { get; }
public string Type { get; }
public int UvCount { get; }
public uint[] Indices { get; protected set; }
public float[] Vertices { get; protected set; }
public Section[] Sections { get; protected set; }
public List<Transform> Transforms { get; }
public Attachment Attachments { get; }

public bool IsSetup { get; set; }
public bool IsVisible { get; set; }
public bool IsSelected { get; set; }
public bool ShowWireframe { get; set; }

public void Setup(Options options);
public void SetupInstances();
public void Render(Shader shader, bool outline = false);
public void PickingRender(Shader shader);
public void Update(Options options);
public void AddInstance(Transform transform);
}
Loading

0 comments on commit 841f40e

Please sign in to comment.