draw skeleton POC

This commit is contained in:
Asval 2023-08-27 23:59:29 +02:00
parent a1494bf2e1
commit 3c2795cded
5 changed files with 75 additions and 15 deletions

View File

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

View File

@ -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<float> _vbo;
private int vaoHandle;
private float[] _vertices;
public Skeleton()
{
BonesByLoweredName = new Dictionary<string, Bone>();
@ -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<float>(_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<Matrix4x4>(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();

View File

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

View File

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

View File

@ -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"))
{