From 569558640ae813044a4257ea60fadf62750f2eba Mon Sep 17 00:00:00 2001 From: 4sval Date: Thu, 15 Sep 2022 00:39:54 +0200 Subject: [PATCH] poc --- FModel/Resources/default.vert | 22 +++--- FModel/Resources/outline.vert | 6 +- FModel/Views/Snooper/Model.cs | 90 ++++++++++++----------- FModel/Views/Snooper/Morph.cs | 68 +++++++++++++++++ FModel/Views/Snooper/SnimGui.cs | 63 +++++++++------- FModel/Views/Snooper/VertexArrayObject.cs | 16 ++-- 6 files changed, 178 insertions(+), 87 deletions(-) create mode 100644 FModel/Views/Snooper/Morph.cs diff --git a/FModel/Resources/default.vert b/FModel/Resources/default.vert index 6b365d280..9d2aeded 100644 --- a/FModel/Resources/default.vert +++ b/FModel/Resources/default.vert @@ -1,15 +1,18 @@ #version 330 core -layout (location = 0) in vec3 vPos; -layout (location = 1) in vec3 vNormal; -layout (location = 2) in vec2 vTexCoords; -layout (location = 3) in vec4 vColor; -layout (location = 4) in ivec4 vBoneIds; -layout (location = 5) in vec4 vWeights; -layout (location = 6) in mat4 vInstanceMatrix; +layout (location = 1) in vec3 vPos; +layout (location = 2) in vec3 vNormal; +layout (location = 3) in vec2 vTexCoords; +layout (location = 4) in vec4 vColor; +layout (location = 5) in ivec4 vBoneIds; +layout (location = 6) in vec4 vWeights; +layout (location = 7) in mat4 vInstanceMatrix; + +layout (location = 11) in vec3 vPosTarget; uniform mat4 uView; uniform mat4 uProjection; +uniform float morph_time; out vec3 fPos; out vec3 fNormal; @@ -18,9 +21,10 @@ out vec4 fColor; void main() { - gl_Position = uProjection * uView * vInstanceMatrix * vec4(vPos, 1.0); + vec3 pos = mix(vPos, vPosTarget, morph_time); + gl_Position = uProjection * uView * vInstanceMatrix * vec4(pos, 1.0); - fPos = vec3(vInstanceMatrix * vec4(vPos, 1.0)); + fPos = vec3(vInstanceMatrix * vec4(pos, 1.0)); fNormal = mat3(transpose(inverse(vInstanceMatrix))) * vNormal; fTexCoords = vTexCoords; fColor = vColor; diff --git a/FModel/Resources/outline.vert b/FModel/Resources/outline.vert index de1087a5..5d7aeb70 100644 --- a/FModel/Resources/outline.vert +++ b/FModel/Resources/outline.vert @@ -1,8 +1,8 @@ #version 330 core -layout (location = 0) in vec3 vPos; -layout (location = 1) in vec3 vNormal; -layout (location = 6) in mat4 vInstanceMatrix; +layout (location = 1) in vec3 vPos; +layout (location = 2) in vec3 vNormal; +layout (location = 7) in mat4 vInstanceMatrix; uniform mat4 uView; uniform mat4 uProjection; diff --git a/FModel/Views/Snooper/Model.cs b/FModel/Views/Snooper/Model.cs index f9fa9c6a..1cc412b9 100644 --- a/FModel/Views/Snooper/Model.cs +++ b/FModel/Views/Snooper/Model.cs @@ -21,7 +21,7 @@ public class Model : IDisposable private BufferObject _matrixVbo; private VertexArrayObject _vao; - private uint _vertexSize = 8; // Position + Normal + UV + private uint _vertexSize = 9; // VertexIndex + Position + Normal + UV private const uint _faceSize = 3; // just so we don't have to do .Length private readonly uint[] _facesIndex = { 1, 0, 2 }; @@ -34,6 +34,7 @@ public class Model : IDisposable public uint[] Indices; public float[] Vertices; public Section[] Sections; + public Morph[] Morphs; public readonly List Skeleton; public int TransformsCount; @@ -65,18 +66,6 @@ public Model(UObject owner, string name, string type, CBaseMeshLod lod, CMeshVer HasBones = Skeleton != null; if (HasBones) _vertexSize += 8; // + BoneIds + BoneWeights - HasMorphTargets = morphTargets != null; - if (HasMorphTargets) - { - var morph = morphTargets[0].Load().MorphLODModels[0]; - foreach (var delta in morph.Vertices) - { - vertices[delta.SourceIdx].Position += delta.PositionDelta; - } - } - - _vertexSize += 16; // + InstanceMatrix - var sections = lod.Sections.Value; Sections = new Section[sections.Length]; Indices = new uint[sections.Sum(section => section.NumFaces * _faceSize)]; @@ -93,40 +82,41 @@ public Model(UObject owner, string name, string type, CBaseMeshLod lod, CMeshVer var count = 0; var i = face * _faceSize + f; var index = section.FirstIndex + i; + var baseIndex = index * _vertexSize; var indice = lod.Indices.Value[index]; var vert = vertices[indice]; - Vertices[index * _vertexSize + count++] = vert.Position.X * Constants.SCALE_DOWN_RATIO; - Vertices[index * _vertexSize + count++] = vert.Position.Z * Constants.SCALE_DOWN_RATIO; - Vertices[index * _vertexSize + count++] = vert.Position.Y * Constants.SCALE_DOWN_RATIO; - Vertices[index * _vertexSize + count++] = vert.Normal.X; - Vertices[index * _vertexSize + count++] = vert.Normal.Z; - Vertices[index * _vertexSize + count++] = vert.Normal.Y; - Vertices[index * _vertexSize + count++] = vert.UV.U; - Vertices[index * _vertexSize + count++] = vert.UV.V; - + Vertices[baseIndex + count++] = indice; + 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; + Vertices[baseIndex + count++] = vert.Normal.X; + Vertices[baseIndex + count++] = vert.Normal.Z; + Vertices[baseIndex + count++] = vert.Normal.Y; + Vertices[baseIndex + count++] = vert.UV.U; + Vertices[baseIndex + count++] = vert.UV.V; if (HasVertexColors) { var color = lod.VertexColors[indice]; - Vertices[index * _vertexSize + count++] = color.R; - Vertices[index * _vertexSize + count++] = color.G; - Vertices[index * _vertexSize + count++] = color.B; - Vertices[index * _vertexSize + count++] = color.A; + Vertices[baseIndex + count++] = color.R; + Vertices[baseIndex + count++] = color.G; + Vertices[baseIndex + count++] = color.B; + Vertices[baseIndex + count++] = color.A; } if (HasBones) { var skelVert = (CSkelMeshVertex) vert; var weightsHash = skelVert.UnpackWeights(); - Vertices[index * _vertexSize + count++] = skelVert.Bone[0]; - Vertices[index * _vertexSize + count++] = skelVert.Bone[1]; - Vertices[index * _vertexSize + count++] = skelVert.Bone[2]; - Vertices[index * _vertexSize + count++] = skelVert.Bone[3]; - Vertices[index * _vertexSize + count++] = weightsHash[0]; - Vertices[index * _vertexSize + count++] = weightsHash[1]; - Vertices[index * _vertexSize + count++] = weightsHash[2]; - Vertices[index * _vertexSize + count++] = weightsHash[3]; + Vertices[baseIndex + count++] = skelVert.Bone[0]; + Vertices[baseIndex + count++] = skelVert.Bone[1]; + Vertices[baseIndex + count++] = skelVert.Bone[2]; + Vertices[baseIndex + count++] = skelVert.Bone[3]; + Vertices[baseIndex + count++] = weightsHash[0]; + Vertices[baseIndex + count++] = weightsHash[1]; + Vertices[baseIndex + count++] = weightsHash[2]; + Vertices[baseIndex + count++] = weightsHash[3]; } Indices[index] = i; @@ -134,6 +124,16 @@ public Model(UObject owner, string name, string type, CBaseMeshLod lod, CMeshVer } } + HasMorphTargets = morphTargets != null; + if (HasMorphTargets) + { + Morphs = new Morph[morphTargets.Length]; + for (var i = 0; i < Morphs.Length; i++) + { + Morphs[i] = new Morph(Vertices, _vertexSize, morphTargets[i].Load()); + } + } + AddInstance(transform ?? Transform.Identity); } @@ -156,23 +156,28 @@ public void Setup(GL gl) _vbo = new BufferObject(_gl, Vertices, BufferTargetARB.ArrayBuffer); _vao = new VertexArrayObject(_gl, _vbo, _ebo); - _vao.VertexAttributePointer(0, 3, VertexAttribPointerType.Float, _vertexSize, 0); // position - _vao.VertexAttributePointer(1, 3, VertexAttribPointerType.Float, _vertexSize, 3); // normal - _vao.VertexAttributePointer(2, 2, VertexAttribPointerType.Float, _vertexSize, 6); // uv - _vao.VertexAttributePointer(3, 4, VertexAttribPointerType.Float, _vertexSize, 8); // color - _vao.VertexAttributePointer(4, 4, VertexAttribPointerType.Int, _vertexSize, 12); // boneids - _vao.VertexAttributePointer(5, 4, VertexAttribPointerType.Float, _vertexSize, 16); // boneweights - _vao.VertexAttributePointer(6, 16, VertexAttribPointerType.Float, _vertexSize, 20); // instancematrix + _vao.VertexAttributePointer(0, 1, VertexAttribPointerType.Int, _vertexSize, 0); // vertex index + _vao.VertexAttributePointer(1, 3, VertexAttribPointerType.Float, _vertexSize, 1); // position + _vao.VertexAttributePointer(2, 3, VertexAttribPointerType.Float, _vertexSize, 4); // normal + _vao.VertexAttributePointer(3, 2, VertexAttribPointerType.Float, _vertexSize, 7); // uv + _vao.VertexAttributePointer(4, 4, VertexAttribPointerType.Float, _vertexSize, 9); // color + _vao.VertexAttributePointer(5, 4, VertexAttribPointerType.Int, _vertexSize, 13); // boneids + _vao.VertexAttributePointer(6, 4, VertexAttribPointerType.Float, _vertexSize, 17); // boneweights TransformsCount = Transforms.Count; var instanceMatrix = new Matrix4x4[TransformsCount]; for (var i = 0; i < instanceMatrix.Length; i++) instanceMatrix[i] = Transforms[i].Matrix; _matrixVbo = new BufferObject(_gl, instanceMatrix, BufferTargetARB.ArrayBuffer); + _vao.BindInstancing(); + + Morphs[0].Setup(gl); + _vao.Bind(); + _vao.VertexAttributePointer(11, 3, VertexAttribPointerType.Float, _vertexSize, 1); // target position + _vao.Unbind(); for (int section = 0; section < Sections.Length; section++) { - _vao.BindInstancing(); Sections[section].Setup(_gl); } } @@ -187,6 +192,7 @@ public void Bind(Shader shader) _vao.Bind(); shader.SetUniform("display_vertex_colors", DisplayVertexColors); + Morphs[0].Bind(shader); for (int section = 0; section < Sections.Length; section++) { Sections[section].Bind(shader, (uint) TransformsCount); diff --git a/FModel/Views/Snooper/Morph.cs b/FModel/Views/Snooper/Morph.cs new file mode 100644 index 00000000..6c0a25ff --- /dev/null +++ b/FModel/Views/Snooper/Morph.cs @@ -0,0 +1,68 @@ +using System; +using CUE4Parse.UE4.Assets.Exports.Animation; +using CUE4Parse.UE4.Objects.Core.Math; +using Silk.NET.OpenGL; + +namespace FModel.Views.Snooper; + +public class Morph : IDisposable +{ + private uint _handle; + private GL _gl; + + private BufferObject _vbo; + + public readonly string Name; + public float[] Vertices; + + public float Value; + + public Morph(float[] vertices, uint vertexSize, UMorphTarget morphTarget) + { + Name = morphTarget.Name; + Vertices = (float[]) vertices.Clone(); + + bool TryFindVertex(uint index, out FVector positionDelta) + { + foreach (var vertex in morphTarget.MorphLODModels[0].Vertices) + { + if (vertex.SourceIdx == index) + { + positionDelta = vertex.PositionDelta; + return true; + } + } + positionDelta = FVector.ZeroVector; + return false; + } + + for (uint i = 0; i < Vertices.Length; i += vertexSize) + { + if (!TryFindVertex((uint) Vertices[i + 0], out var positionDelta)) continue; + + Vertices[i + 1] += positionDelta.X * Constants.SCALE_DOWN_RATIO; + Vertices[i + 2] += positionDelta.Z * Constants.SCALE_DOWN_RATIO; + Vertices[i + 3] += positionDelta.Y * Constants.SCALE_DOWN_RATIO; + } + } + + public void Setup(GL gl) + { + _gl = gl; + + _handle = _gl.CreateProgram(); + + _vbo = new BufferObject(_gl, Vertices, BufferTargetARB.ArrayBuffer); + } + + public void Bind(Shader shader) + { + shader.SetUniform("morph_time", Value); + } + + public void Dispose() + { + _vbo.Dispose(); + _gl.DeleteProgram(_handle); + } +} diff --git a/FModel/Views/Snooper/SnimGui.cs b/FModel/Views/Snooper/SnimGui.cs index 5baffb94..61954d9d 100644 --- a/FModel/Views/Snooper/SnimGui.cs +++ b/FModel/Views/Snooper/SnimGui.cs @@ -316,6 +316,13 @@ private void DrawProperties(Camera camera, IDictionary models) ImGui.BeginDisabled(!model.HasMorphTargets); if (ImGui.BeginTabItem("Shape Keys")) { + for (int i = 0; i < model.Morphs.Length; i++) + { + ImGui.PushID(i); + ImGui.Text(model.Morphs[i].Name); + ImGui.DragFloat("Value", ref model.Morphs[i].Value, 0.01f, 0.0f, 1.0f, "%.2f", ImGuiSliderFlags.AlwaysClamp); + ImGui.PopID(); + } ImGui.EndTabItem(); } ImGui.EndDisabled(); @@ -343,37 +350,16 @@ private void DrawTextures(IDictionary models) { ImGui.SetNextItemWidth(300); ImGui.ColorEdit4(section.TexturesLabels[0], ref section.DiffuseColor, ImGuiColorEditFlags.AlphaPreview | ImGuiColorEditFlags.AlphaBar); + if (section.Textures[1] is { } normalMap) DrawTexture(normalMap); } - // else + else { - for (var i = 0; i < section.Textures.Length; i++) + for (var i = 0;i < section.Textures.Length; i++) { if (section.Textures[i] is not {} texture) continue; - ImGui.SameLine(); - ImGui.BeginGroup(); - ImGui.Image(texture.GetPointer(), new Vector2(88), Vector2.Zero, Vector2.One, Vector4.One, new Vector4(1, 1, 1, .5f)); - if (ImGui.IsItemHovered()) - { - ImGui.BeginTooltip(); - ImGui.Text($"Type: ({texture.Format}) {texture.Type}:{texture.Name}"); - ImGui.Text($"Texture: {texture.Path}"); - ImGui.Text($"Imported: {texture.ImportedWidth}x{texture.ImportedHeight}"); - ImGui.Text($"Mip Used: {texture.Width}x{texture.Height}"); - ImGui.Spacing(); - ImGui.TextDisabled(texture.Label); - ImGui.EndTooltip(); - } - - if (ImGui.IsItemClicked()) - { - Application.Current.Dispatcher.Invoke(delegate - { - Clipboard.SetText(Utils.FixPath(texture.Path)); - texture.Label = "(?) Copied to Clipboard"; - }); - } + DrawTexture(texture); if (i == 3) // emissive, show color { @@ -393,6 +379,33 @@ private void DrawTextures(IDictionary models) ImGui.End(); } + private void DrawTexture(Texture texture) + { + ImGui.SameLine(); + ImGui.BeginGroup(); + ImGui.Image(texture.GetPointer(), new Vector2(88), Vector2.Zero, Vector2.One, Vector4.One, new Vector4(1, 1, 1, .5f)); + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + ImGui.Text($"Type: ({texture.Format}) {texture.Type}:{texture.Name}"); + ImGui.Text($"Texture: {texture.Path}"); + ImGui.Text($"Imported: {texture.ImportedWidth}x{texture.ImportedHeight}"); + ImGui.Text($"Mip Used: {texture.Width}x{texture.Height}"); + ImGui.Spacing(); + ImGui.TextDisabled(texture.Label); + ImGui.EndTooltip(); + } + + if (ImGui.IsItemClicked()) + { + Application.Current.Dispatcher.Invoke(delegate + { + Clipboard.SetText(Utils.FixPath(texture.Path)); + texture.Label = "(?) Copied to Clipboard"; + }); + } + } + private void Draw3DViewport(FramebufferObject framebuffer, Camera camera, IMouse mouse) { const float lookSensitivity = 0.1f; diff --git a/FModel/Views/Snooper/VertexArrayObject.cs b/FModel/Views/Snooper/VertexArrayObject.cs index 2c27ec92..c1d49a91 100644 --- a/FModel/Views/Snooper/VertexArrayObject.cs +++ b/FModel/Views/Snooper/VertexArrayObject.cs @@ -6,8 +6,8 @@ namespace FModel.Views.Snooper; public class VertexArrayObject : IDisposable where TVertexType : unmanaged where TIndexType : unmanaged { - private uint _handle; - private GL _gl; + private readonly uint _handle; + private readonly GL _gl; public VertexArrayObject(GL gl, BufferObject vbo, BufferObject ebo) { @@ -43,19 +43,19 @@ public unsafe void BindInstancing() Bind(); var vec4Size = (uint) sizeof(Vector4); - _gl.EnableVertexAttribArray(6); - _gl.VertexAttribPointer(6, 4, VertexAttribPointerType.Float, false, 4 * vec4Size, (void*)0); _gl.EnableVertexAttribArray(7); - _gl.VertexAttribPointer(7, 4, VertexAttribPointerType.Float, false, 4 * vec4Size, (void*)(1 * vec4Size)); + _gl.VertexAttribPointer(7, 4, VertexAttribPointerType.Float, false, 4 * vec4Size, (void*)0); _gl.EnableVertexAttribArray(8); - _gl.VertexAttribPointer(8, 4, VertexAttribPointerType.Float, false, 4 * vec4Size, (void*)(2 * vec4Size)); + _gl.VertexAttribPointer(8, 4, VertexAttribPointerType.Float, false, 4 * vec4Size, (void*)(1 * vec4Size)); _gl.EnableVertexAttribArray(9); - _gl.VertexAttribPointer(9, 4, VertexAttribPointerType.Float, false, 4 * vec4Size, (void*)(3 * vec4Size)); + _gl.VertexAttribPointer(9, 4, VertexAttribPointerType.Float, false, 4 * vec4Size, (void*)(2 * vec4Size)); + _gl.EnableVertexAttribArray(10); + _gl.VertexAttribPointer(10, 4, VertexAttribPointerType.Float, false, 4 * vec4Size, (void*)(3 * vec4Size)); - _gl.VertexAttribDivisor(6, 1); _gl.VertexAttribDivisor(7, 1); _gl.VertexAttribDivisor(8, 1); _gl.VertexAttribDivisor(9, 1); + _gl.VertexAttribDivisor(10, 1); Unbind(); }