From 3c2795cdedb6bd1a33877e3ee5d4f0ac8ca30bb1 Mon Sep 17 00:00:00 2001 From: Asval Date: Sun, 27 Aug 2023 23:59:29 +0200 Subject: [PATCH] draw skeleton POC --- FModel/Resources/bone.vert | 16 ++---- FModel/Views/Snooper/Animations/Skeleton.cs | 55 ++++++++++++++++++-- FModel/Views/Snooper/Models/SkeletalModel.cs | 7 +++ FModel/Views/Snooper/Renderer.cs | 11 ++++ FModel/Views/Snooper/SnimGui.cs | 1 + 5 files changed, 75 insertions(+), 15 deletions(-) diff --git a/FModel/Resources/bone.vert b/FModel/Resources/bone.vert index 724f01f1..1d91226c 100644 --- a/FModel/Resources/bone.vert +++ b/FModel/Resources/bone.vert @@ -1,23 +1,15 @@ #version 460 core -layout (location = 1) in vec3 vPos; -layout (location = 9) in mat4 vInstanceMatrix; +layout (location = 0) in vec3 vPos; uniform mat4 uView; uniform mat4 uProjection; -uniform bool uSocket; +uniform mat4 uInstanceMatrix; 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)); + gl_Position = uProjection * uView * uInstanceMatrix * vec4(vPos, 1.0); + fPos = vec3(uInstanceMatrix * vec4(vPos, 1.0)); } diff --git a/FModel/Views/Snooper/Animations/Skeleton.cs b/FModel/Views/Snooper/Animations/Skeleton.cs index 01ae8a69..f3813f31 100644 --- a/FModel/Views/Snooper/Animations/Skeleton.cs +++ b/FModel/Views/Snooper/Animations/Skeleton.cs @@ -28,9 +28,13 @@ public class Skeleton : IDisposable private int TotalBoneCount => BoneCount + _additionalBoneCount; public bool IsAnimated { get; private set; } - public bool DrawAllBones; public string SelectedBone; + private const int _vertexSize = 6; + private BufferObject _vbo; + private int vaoHandle; + private float[] _vertices; + public Skeleton() { BonesByLoweredName = new Dictionary(); @@ -40,6 +44,7 @@ public class Skeleton : IDisposable public Skeleton(FReferenceSkeleton referenceSkeleton) : this() { BoneCount = referenceSkeleton.FinalRefBoneInfo.Length; + _vertices = new float[_vertexSize * BoneCount]; for (int boneIndex = 0; boneIndex < BoneCount; boneIndex++) { var info = referenceSkeleton.FinalRefBoneInfo[boneIndex]; @@ -58,6 +63,14 @@ public class Skeleton : IDisposable bone.Rest.Relation = parentBone.Rest.Matrix; parentBone.LoweredChildNames.Add(boneName); + + var baseIndex = boneIndex * _vertexSize; + _vertices[baseIndex + 0] = bone.Rest.Matrix.Translation.X; + _vertices[baseIndex + 1] = bone.Rest.Matrix.Translation.Y; + _vertices[baseIndex + 2] = bone.Rest.Matrix.Translation.Z; + _vertices[baseIndex + 3] = parentBone.Rest.Matrix.Translation.X; + _vertices[baseIndex + 4] = parentBone.Rest.Matrix.Translation.Y; + _vertices[baseIndex + 5] = parentBone.Rest.Matrix.Translation.Z; } if (boneIndex == 0) SelectedBone = boneName; @@ -104,6 +117,17 @@ public class Skeleton : IDisposable { _handle = GL.CreateProgram(); + _vbo = new BufferObject(_vertices, BufferTarget.ArrayBuffer); + + vaoHandle = GL.GenVertexArray(); + GL.BindVertexArray(vaoHandle); + _vbo.Bind(); + + GL.EnableVertexAttribArray(0); + GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, sizeof(float) * 3, 0); + + GL.BindVertexArray(0); + _rest = new BufferObject(BoneCount, BufferTarget.ShaderStorageBuffer); foreach (var bone in BonesByLoweredName.Values) { @@ -171,7 +195,6 @@ public class Skeleton : IDisposable if (!IsAnimated) return; _ssbo.Bind(); - foreach (var bone in BonesByLoweredName.Values) { var boneMatrix = bone.IsRoot ? bone.Rest.Relation : bone.Rest.LocalMatrix * _boneMatriceAtFrame[bone.ParentIndex]; @@ -199,8 +222,23 @@ public class Skeleton : IDisposable _ssbo.Update(bone.Index, boneMatrix); _boneMatriceAtFrame[bone.Index] = boneMatrix; } - _ssbo.Unbind(); + + _vbo.Bind(); + foreach (var bone in BonesByLoweredName.Values) + { + var baseIndex = bone.Index * _vertexSize; + var boneMatrix = bone.IsRoot ? bone.Rest.Relation : bone.Rest.LocalMatrix * _boneMatriceAtFrame[bone.ParentIndex]; + var parentBoneMatrix = bone.IsRoot ? bone.Rest.Relation : _boneMatriceAtFrame[bone.ParentIndex]; + + _vbo.Update(baseIndex + 0, boneMatrix.Translation.X); + _vbo.Update(baseIndex + 1, boneMatrix.Translation.Y); + _vbo.Update(baseIndex + 2, boneMatrix.Translation.Z); + _vbo.Update(baseIndex + 3, parentBoneMatrix.Translation.X); + _vbo.Update(baseIndex + 4, parentBoneMatrix.Translation.Y); + _vbo.Update(baseIndex + 5, parentBoneMatrix.Translation.Z); + } + _vbo.Unbind(); } private (int, float) GetBoneFrameData(Bone bone, Animation animation) @@ -242,6 +280,17 @@ public class Skeleton : IDisposable _rest.BindBufferBase(2); } + public void RenderBones() + { + GL.Disable(EnableCap.DepthTest); + + GL.BindVertexArray(vaoHandle); + GL.DrawArrays(PrimitiveType.Lines, 0, _vertices.Length); + GL.BindVertexArray(0); + + GL.Enable(EnableCap.DepthTest); + } + public void ImGuiBoneBreadcrumb() { var p1 = ImGui.GetCursorScreenPos(); diff --git a/FModel/Views/Snooper/Models/SkeletalModel.cs b/FModel/Views/Snooper/Models/SkeletalModel.cs index 4d5acdd2..465a7412 100644 --- a/FModel/Views/Snooper/Models/SkeletalModel.cs +++ b/FModel/Views/Snooper/Models/SkeletalModel.cs @@ -20,6 +20,7 @@ public class SkeletalModel : UModel public bool HasMorphTargets => Morphs.Count > 0; public float MorphTime; + public bool DrawSkeleton { get; set; } public SkeletalModel(USkeletalMesh export, CSkeletalMesh skeletalMesh, Transform transform = null) : base(export, skeletalMesh.LODs[LodLevel], export.Materials, skeletalMesh.LODs[LodLevel].Verts, skeletalMesh.LODs.Count, transform) @@ -79,6 +80,12 @@ public class SkeletalModel : UModel Skeleton.Render(shader); } + public void RenderBones(Shader shader) + { + shader.SetUniform("uInstanceMatrix", GetTransform().Matrix); + Skeleton.RenderBones(); + } + public void UpdateMorph(int index) { _morphVbo.Update(Morphs[index].Vertices); diff --git a/FModel/Views/Snooper/Renderer.cs b/FModel/Views/Snooper/Renderer.cs index 54ec487f..fee4c332 100644 --- a/FModel/Views/Snooper/Renderer.cs +++ b/FModel/Views/Snooper/Renderer.cs @@ -45,6 +45,7 @@ public class Renderer : IDisposable private Shader _shader; private Shader _outline; private Shader _light; + private Shader _bone; private bool _saveCameraMode; public bool ShowSkybox; @@ -221,6 +222,7 @@ public class Renderer : IDisposable _shader = new Shader(); _outline = new Shader("outline"); _light = new Shader("light"); + _bone = new Shader("bone"); Picking.Setup(); Options.SetupModelsAndLights(); @@ -258,6 +260,14 @@ public class Renderer : IDisposable Options.Lights[i].Render(_light); } + // bone pass + foreach (var model in Options.Models.Values) + { + if (!model.IsVisible || model is not SkeletalModel { DrawSkeleton: true } skeletalModel) continue; + _bone.Render(viewMatrix, projMatrix); + skeletalModel.RenderBones(_bone); + } + // outline pass if (Options.TryGetModel(out var selected) && selected.IsVisible) { @@ -563,6 +573,7 @@ public class Renderer : IDisposable _shader?.Dispose(); _outline?.Dispose(); _light?.Dispose(); + _bone?.Dispose(); Picking?.Dispose(); Options?.Dispose(); } diff --git a/FModel/Views/Snooper/SnimGui.cs b/FModel/Views/Snooper/SnimGui.cs index bec7e589..158034ea 100644 --- a/FModel/Views/Snooper/SnimGui.cs +++ b/FModel/Views/Snooper/SnimGui.cs @@ -428,6 +428,7 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio s.Renderer.Options.SelectModel(guid); if (ImGui.MenuItem("Show", null, model.IsVisible)) model.IsVisible = !model.IsVisible; if (ImGui.MenuItem("Wireframe", null, model.ShowWireframe)) model.ShowWireframe = !model.ShowWireframe; + if (model is SkeletalModel skeletalModel && ImGui.MenuItem("Draw Skeleton", null, skeletalModel.DrawSkeleton)) skeletalModel.DrawSkeleton = !skeletalModel.DrawSkeleton; ImGui.Separator(); if (ImGui.MenuItem("Save")) {