mirror of
https://github.com/4sval/FModel.git
synced 2026-07-27 22:08:16 -05:00
mesh morphing POC
This commit is contained in:
parent
dd963c7cce
commit
0295d47eba
|
|
@ -1 +1 @@
|
|||
Subproject commit 35f6d437eb0f03855d30265a6214794810868e6a
|
||||
Subproject commit 52871ba0775c211473efb35805a39dd00586d10f
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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++)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user