mesh morphing POC

This commit is contained in:
4sval 2022-09-13 22:29:29 +02:00
parent dd963c7cce
commit 0295d47eba
8 changed files with 68 additions and 38 deletions

@ -1 +1 @@
Subproject commit 35f6d437eb0f03855d30265a6214794810868e6a
Subproject commit 52871ba0775c211473efb35805a39dd00586d10f

View File

@ -79,7 +79,7 @@ public partial class MainWindow
#if DEBUG
await _threadWorkerView.Begin(_ =>
_applicationView.CUE4Parse.Extract(
"FortniteGame/Content/Characters/Player/Male/Medium/Bodies/M_MED_StaminaCat/Meshes/M_MED_StaminaCat.uasset"));
"Hk_project/Content/Character/Zurg/Mesh/SKM_Zurg.uasset"));
#endif
}

View File

@ -5,16 +5,16 @@ namespace FModel.Views.Snooper;
public class Camera
{
public Vector3 Position { get; set; }
public Vector3 Direction { get; private set; }
public Vector3 Position;
public Vector3 Direction;
public Vector3 Up = Vector3.UnitY;
public float Yaw { get; set; } = -90f;
public float Pitch { get; set; } = 0f;
public float Zoom { get; set; } = 60f;
public float Speed { get; set; } = 1f;
public float Near { get; } = 0.01f;
public float Far { get; } = 100f;
public float Yaw = -90f;
public float Pitch = 0f;
public float Zoom = 60f;
public float Speed = 1f;
public float Near = 0.01f;
public float Far = 100f;
public float AspectRatio => 16f / 9f;
public Camera(Vector3 position, Vector3 direction, float near, float far, float speed)

View File

@ -3,7 +3,9 @@ using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using CUE4Parse.UE4.Assets.Exports;
using CUE4Parse.UE4.Assets.Exports.Animation;
using CUE4Parse.UE4.Objects.Engine;
using CUE4Parse.UE4.Objects.UObject;
using CUE4Parse_Conversion.Meshes.PSK;
using Silk.NET.OpenGL;
@ -16,7 +18,8 @@ public class Model : IDisposable
private BufferObject<uint> _ebo;
private BufferObject<float> _vbo;
private BufferObject<Matrix4x4> _mvbo;
private BufferObject<float>[] _morphVbo;
private BufferObject<Matrix4x4> _matrixVbo;
private VertexArrayObject<float, uint> _vao;
private uint _vertexSize = 8; // Position + Normal + UV
@ -28,6 +31,7 @@ public class Model : IDisposable
public readonly string Type;
public readonly bool HasVertexColors;
public readonly bool HasBones;
public readonly bool HasMorphTargets;
public uint[] Indices;
public float[] Vertices;
public Section[] Sections;
@ -50,9 +54,11 @@ public class Model : IDisposable
Transforms = new List<Transform>();
Show = true;
IsSavable = owner is not UWorld;
_morphVbo = Array.Empty<BufferObject<float>>();
}
public Model(UObject owner, string name, string type, CBaseMeshLod lod, CMeshVertex[] vertices, List<CSkelMeshBone> skeleton = null, Transform transform = null)
public Model(UObject owner, string name, string type, CBaseMeshLod lod, CMeshVertex[] vertices, FPackageIndex[] morphTargets = null, List<CSkelMeshBone> skeleton = null, Transform transform = null)
: this(owner, name, type)
{
HasVertexColors = lod.VertexColors != null;
@ -62,6 +68,17 @@ public class Model : IDisposable
HasBones = Skeleton != null;
if (HasBones) _vertexSize += 8; // + BoneIds + BoneWeights
HasMorphTargets = morphTargets != null;
if (HasMorphTargets)
{
_morphVbo = new BufferObject<float>[4 * morphTargets.Length]; // PositionDelta + SourceIdx
var morph = morphTargets[0].Load<UMorphTarget>().MorphLODModels[0];
foreach (var delta in morph.Vertices)
{
vertices[delta.SourceIdx].Position += delta.PositionDelta;
}
}
_vertexSize += 16; // + InstanceMatrix
var sections = lod.Sections.Value;
@ -128,9 +145,9 @@ public class Model : IDisposable
public void UpdateMatrix(int index)
{
_mvbo.Bind();
_mvbo.Update(index, Transforms[index].Matrix);
_mvbo.Unbind();
_matrixVbo.Bind();
_matrixVbo.Update(index, Transforms[index].Matrix);
_matrixVbo.Unbind();
}
public void Setup(GL gl)
@ -155,14 +172,11 @@ public class Model : IDisposable
var instanceMatrix = new Matrix4x4[TransformsCount];
for (var i = 0; i < instanceMatrix.Length; i++)
instanceMatrix[i] = Transforms[i].Matrix;
_mvbo = new BufferObject<Matrix4x4>(_gl, instanceMatrix, BufferTargetARB.ArrayBuffer);
_matrixVbo = new BufferObject<Matrix4x4>(_gl, instanceMatrix, BufferTargetARB.ArrayBuffer);
for (int section = 0; section < Sections.Length; section++)
{
_vao.Bind();
_vao.BindInstancing();
_vao.Unbind();
Sections[section].Setup(_gl);
}
}
@ -214,7 +228,11 @@ public class Model : IDisposable
{
_ebo.Dispose();
_vbo.Dispose();
_mvbo.Dispose();
_matrixVbo.Dispose();
for (int i = 0; i < _morphVbo.Length; i++)
{
_morphVbo[i].Dispose();
}
_vao.Dispose();
for (int section = 0; section < Sections.Length; section++)
{

View File

@ -157,9 +157,6 @@ public class Section : IDisposable
}
}
}
Parameters.RoughnessValue = 1;
Parameters.MetallicValue = 1;
break;
}
case FGame.ShooterGame:
@ -201,9 +198,6 @@ public class Section : IDisposable
break;
}
Parameters.RoughnessValue = 1;
Parameters.MetallicValue = 1;
break;
}
case FGame.Gameface:
@ -224,12 +218,12 @@ public class Section : IDisposable
}
}
}
Parameters.RoughnessValue = 1;
Parameters.MetallicValue = 1;
break;
}
}
Parameters.RoughnessValue = 1;
Parameters.MetallicValue = 1;
}
public void Bind(Shader shader, uint instanceCount)

View File

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Numerics;
using System.Windows;
@ -174,12 +174,13 @@ public class SnimGui : IDisposable
if (ImGui.CollapsingHeader("Camera"))
{
PushStyleCompact();
ImGui.Text($"Position: {camera.Position}");
ImGui.Text($"Direction: {camera.Direction}");
ImGui.Text($"Speed: {camera.Speed}");
ImGui.Text($"Far: {camera.Far}");
ImGui.Text($"Near: {camera.Near}");
ImGui.Text($"Zoom: {camera.Zoom}");
string[] modes = { "free cam", "orbital cam" };
int selectedMode = 0;
ImGui.Combo("Projection", ref selectedMode, modes, modes.Length);
ImGui.DragFloat3("Position", ref camera.Position);
ImGui.DragFloat3("Direction", ref camera.Direction);
ImGui.DragFloat("Speed", ref camera.Speed, 0.01f);
ImGui.DragFloat("Zoom", ref camera.Zoom);
PopStyleCompact();
}
@ -297,12 +298,25 @@ public class SnimGui : IDisposable
ImGui.TableNextColumn();
if (ImGui.Selectable(section.Name, _selectedSection == i, ImGuiSelectableFlags.SpanAllColumns))
_selectedSection = i;
if (ImGui.BeginPopupContextItem())
{
if (ImGui.Selectable("Swap"))
{
}
ImGui.EndPopup();
}
ImGui.PopID();
}
ImGui.EndTable();
PopStyleCompact();
ImGui.EndTabItem();
}
if (ImGui.BeginTabItem("Shape Keys"))
{
ImGui.EndTabItem();
}
}
ImGui.End();

View File

@ -112,7 +112,7 @@ public class Snooper
var guid = Guid.NewGuid();
if (!_models.TryGetValue(guid, out _))
{
_models[guid] = new Model(export, sk.Name, sk.ExportType, mesh.LODs[0], mesh.LODs[0].Verts, mesh.RefSkeleton);
_models[guid] = new Model(export, sk.Name, sk.ExportType, mesh.LODs[0], mesh.LODs[0].Verts, sk.MorphTargets, mesh.RefSkeleton);
SetupCamera(mesh.BoundingBox *= Constants.SCALE_DOWN_RATIO);
}
break;
@ -162,7 +162,7 @@ public class Snooper
continue;
}
model = new Model(export, m.Name, m.ExportType, mesh.LODs[0], mesh.LODs[0].Verts, null, transform);
model = new Model(export, m.Name, m.ExportType, mesh.LODs[0], mesh.LODs[0].Verts, null, null, transform);
if (actor.TryGetAllValues(out FPackageIndex[] textureData, "TextureData"))
{
for (int j = 0; j < textureData.Length; j++)

View File

@ -40,6 +40,8 @@ public class VertexArrayObject<TVertexType, TIndexType> : IDisposable where TVer
public unsafe void BindInstancing()
{
Bind();
var vec4Size = (uint) sizeof(Vector4);
_gl.EnableVertexAttribArray(6);
_gl.VertexAttribPointer(6, 4, VertexAttribPointerType.Float, false, 4 * vec4Size, (void*)0);
@ -54,6 +56,8 @@ public class VertexArrayObject<TVertexType, TIndexType> : IDisposable where TVer
_gl.VertexAttribDivisor(7, 1);
_gl.VertexAttribDivisor(8, 1);
_gl.VertexAttribDivisor(9, 1);
Unbind();
}
public void Unbind()