diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index 9f143a85..80dd9cc6 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -130,7 +130,6 @@ - diff --git a/FModel/MainWindow.xaml.cs b/FModel/MainWindow.xaml.cs index 88c73acc..563c3b27 100644 --- a/FModel/MainWindow.xaml.cs +++ b/FModel/MainWindow.xaml.cs @@ -79,7 +79,7 @@ public partial class MainWindow #if DEBUG await _threadWorkerView.Begin(_ => _applicationView.CUE4Parse.Extract( - "/Game/Gadgets/Assets/VinderTech_GliderChute/Glider_Mark_II/Meshes/Glider_Mark_II.uasset")); + "FortniteGame/Content/Environments/Props/Winter/Meshes/SM_ChristmasTree_Llama.uasset")); #endif } diff --git a/FModel/Views/Snooper/Camera.cs b/FModel/Views/Snooper/Camera.cs index e41094f0..9dbaf5d8 100644 --- a/FModel/Views/Snooper/Camera.cs +++ b/FModel/Views/Snooper/Camera.cs @@ -1,5 +1,6 @@ using System; using System.Numerics; +using Serilog; namespace FModel.Views.Snooper; @@ -9,16 +10,15 @@ public class Camera public Vector3 Direction { get; private set; } public Vector3 Up = Vector3.UnitY; - public float AspectRatio { get; } public float Yaw { get; set; } = -90f; - public float Pitch { get; set; } - public float Zoom = 45f; + public float Pitch { get; set; } = 0f; + public float Zoom { get; set; } = 45f; + public float AspectRatio => 16f / 9f; - public Camera(Vector3 position, Vector3 direction, float aspectRatio = 16f / 9f) + public Camera(Vector3 position, Vector3 direction) { Position = position; Direction = direction; - AspectRatio = aspectRatio; // trigonometric math to calculate the cam's yaw/pitch based on position and direction to look var yaw = MathF.Atan((-Position.X - Direction.X) / (Position.Z - Direction.Z)); @@ -40,7 +40,7 @@ public class Camera //We don't want to be able to look behind us by going over our head or under our feet so make sure it stays within these bounds Pitch = Math.Clamp(Pitch, -89f, 89f); - Direction = Vector3.Normalize(CalculateDirection()); + CalculateDirection(); } public Matrix4x4 GetViewMatrix() @@ -53,12 +53,22 @@ public class Camera return Matrix4x4.CreatePerspectiveFieldOfView(Helper.DegreesToRadians(Zoom), AspectRatio, 0.1f, 100.0f); } - private Vector3 CalculateDirection() + public void CalculateDirection() { var direction = Vector3.Zero; - direction.X = MathF.Cos(Helper.DegreesToRadians(Yaw)) * MathF.Cos(Helper.DegreesToRadians(Pitch)); - direction.Y = MathF.Sin(Helper.DegreesToRadians(Pitch)); - direction.Z = MathF.Sin(Helper.DegreesToRadians(Yaw)) * MathF.Cos(Helper.DegreesToRadians(Pitch)); - return direction; + var yaw = Helper.DegreesToRadians(Yaw); + var pitch = Helper.DegreesToRadians(Pitch); + direction.X = MathF.Cos(yaw) * MathF.Cos(pitch); + direction.Y = MathF.Sin(pitch); + direction.Z = MathF.Sin(yaw) * MathF.Cos(pitch); + Direction = Vector3.Normalize(direction); + } + + private void Loge() + { + Log.Logger.Information("Position {Position}", Position); + Log.Logger.Information("Direction {Direction}", Direction); + Log.Logger.Information("Yaw {Yaw}", Yaw); + Log.Logger.Information("Pitch {Pitch}", Pitch); } } diff --git a/FModel/Views/Snooper/Mesh.cs b/FModel/Views/Snooper/Model.cs similarity index 67% rename from FModel/Views/Snooper/Mesh.cs rename to FModel/Views/Snooper/Model.cs index 70869128..9755d97a 100644 --- a/FModel/Views/Snooper/Mesh.cs +++ b/FModel/Views/Snooper/Model.cs @@ -1,15 +1,12 @@ using System; using System.Linq; using System.Numerics; -using CUE4Parse.UE4.Assets.Exports.Material; -using CUE4Parse.UE4.Assets.Exports.Texture; using CUE4Parse_Conversion.Meshes.PSK; -using CUE4Parse_Conversion.Textures; using Silk.NET.OpenGL; namespace FModel.Views.Snooper; -public class Mesh : IDisposable +public class Model : IDisposable { private uint _handle; private GL _gl; @@ -18,28 +15,27 @@ public class Mesh : IDisposable private BufferObject _vbo; private VertexArrayObject _vao; - private Shader _shader; - private Texture[] _albedoMap; - // private Texture _normalMap; - private const int _vertexSize = 8; // Position + Normals + UV private const uint _faceSize = 3; // just so we don't have to do .Length private readonly uint[] _facesIndex = { 1, 0, 2 }; + private Shader _shader; + public uint[] Indices; public float[] Vertices; - public CMaterialParams[] Params; + public Section[] Sections; - public Mesh(CBaseMeshLod lod, CMeshVertex[] vertices) + public Model(CBaseMeshLod lod, CMeshVertex[] vertices) { var sections = lod.Sections.Value; - Params = new CMaterialParams[sections.Length]; + Sections = new Section[sections.Length]; Indices = new uint[sections.Sum(section => section.NumFaces * _faceSize)]; Vertices = new float[Indices.Length * _vertexSize]; for (var s = 0; s < sections.Length; s++) { var section = sections[s]; + Sections[s] = new Section((uint) section.NumFaces * _faceSize, section.FirstIndex, section); for (uint face = 0; face < section.NumFaces; face++) { foreach (var f in _facesIndex) @@ -58,15 +54,9 @@ public class Mesh : IDisposable Vertices[index * _vertexSize + 6] = vert.UV.U; Vertices[index * _vertexSize + 7] = vert.UV.V; - Indices[index] = (uint) index; + Indices[index] = i; } } - - Params[s] = new CMaterialParams(); - if (section.Material != null && section.Material.TryLoad(out var material) && material is UMaterialInterface unrealMaterial) - { - unrealMaterial.GetParams(Params[s]); - } } } @@ -76,6 +66,8 @@ public class Mesh : IDisposable _handle = _gl.CreateProgram(); + _shader = new Shader(_gl); + _ebo = new BufferObject(_gl, Indices, BufferTargetARB.ElementArrayBuffer); _vbo = new BufferObject(_gl, Vertices, BufferTargetARB.ArrayBuffer); _vao = new VertexArrayObject(_gl, _vbo, _ebo); @@ -84,20 +76,13 @@ public class Mesh : IDisposable _vao.VertexAttributePointer(1, 3, VertexAttribPointerType.Float, _vertexSize, 3); // normals _vao.VertexAttributePointer(2, 2, VertexAttribPointerType.Float, _vertexSize, 6); // uv - _shader = new Shader(_gl); - - _albedoMap = new Texture[Params.Length]; - for (int i = 0; i < _albedoMap.Length; i++) + for (int section = 0; section < Sections.Length; section++) { - if (Params[i].Diffuse is UTexture2D { IsVirtual: false } diffuse && diffuse.GetFirstMip() is { } mip) - { - TextureDecoder.DecodeTexture(mip, diffuse.Format, diffuse.isNormalMap, out var data, out _); - _albedoMap[i] = new Texture(_gl, data, (uint) mip.SizeX, (uint) mip.SizeY); - } + Sections[section].Setup(_gl); } } - public unsafe void Bind(Camera camera) + public void Bind(Camera camera) { _vao.Bind(); @@ -106,15 +91,14 @@ public class Mesh : IDisposable _shader.SetUniform("uModel", Matrix4x4.Identity); _shader.SetUniform("uView", camera.GetViewMatrix()); _shader.SetUniform("uProjection", camera.GetProjectionMatrix()); - // _shader.SetUniform("viewPos", _camera.Position); + // _shader.SetUniform("viewPos", camera.Position); - for (int i = 0; i < _albedoMap.Length; i++) + for (int section = 0; section < Sections.Length; section++) { - _shader.SetUniform("material.albedo", i); - _albedoMap[i].Bind(TextureUnit.Texture0 + i); - } + Sections[section].Bind(_shader); - _gl.DrawElements(PrimitiveType.Triangles, (uint) Indices.Length, DrawElementsType.UnsignedInt, null); + _gl.DrawArrays(PrimitiveType.Triangles, Sections[section].FirstFaceIndex, Sections[section].FacesCount); + } } public void Dispose() @@ -123,6 +107,10 @@ public class Mesh : IDisposable _vbo.Dispose(); _vao.Dispose(); _shader.Dispose(); + for (int section = 0; section < Sections.Length; section++) + { + Sections[section].Dispose(); + } _gl.DeleteProgram(_handle); } } diff --git a/FModel/Views/Snooper/Section.cs b/FModel/Views/Snooper/Section.cs new file mode 100644 index 00000000..95200a34 --- /dev/null +++ b/FModel/Views/Snooper/Section.cs @@ -0,0 +1,57 @@ +using System; +using CUE4Parse.UE4.Assets.Exports.Material; +using CUE4Parse.UE4.Assets.Exports.Texture; +using CUE4Parse_Conversion.Meshes.PSK; +using CUE4Parse_Conversion.Textures; +using Silk.NET.OpenGL; + +namespace FModel.Views.Snooper; + +public class Section : IDisposable +{ + private uint _handle; + private GL _gl; + + private Texture _albedoMap; + // private Texture _normalMap; + + public uint FacesCount; + public int FirstFaceIndex; + public CMaterialParams Params; + + public Section(uint facesCount, int firstFaceIndex, CMeshSection section) + { + FacesCount = facesCount; + FirstFaceIndex = firstFaceIndex; + Params = new CMaterialParams(); + if (section.Material != null && section.Material.TryLoad(out var material) && material is UMaterialInterface unrealMaterial) + { + unrealMaterial.GetParams(Params); + } + } + + public void Setup(GL gl) + { + _gl = gl; + + _handle = _gl.CreateProgram(); + + if (Params.Diffuse is UTexture2D { IsVirtual: false } diffuse && diffuse.GetFirstMip() is { } mip) + { + TextureDecoder.DecodeTexture(mip, diffuse.Format, diffuse.isNormalMap, out var data, out _); + _albedoMap = new Texture(_gl, data, (uint) mip.SizeX, (uint) mip.SizeY); + } + } + + public void Bind(Shader shader) + { + shader.SetUniform("material.albedo", 0); + _albedoMap.Bind(TextureUnit.Texture0); + } + + public void Dispose() + { + _albedoMap.Dispose(); + _gl.DeleteProgram(_handle); + } +} diff --git a/FModel/Views/Snooper/Snooper.cs b/FModel/Views/Snooper/Snooper.cs index 14e8bcbe..c8bf7f60 100644 --- a/FModel/Views/Snooper/Snooper.cs +++ b/FModel/Views/Snooper/Snooper.cs @@ -20,7 +20,7 @@ public class Snooper private IKeyboard _keyboard; private Vector2 _previousMousePosition; - private Mesh[] _meshes; + private Model[] _models; public int Width { get; } public int Height { get; } @@ -35,7 +35,6 @@ public class Snooper var options = WindowOptions.Default; options.Size = new Vector2D(Width, Height); - options.Position = new Vector2D(Width, Height); options.Title = "Snooper"; _window = Window.Create(options); @@ -44,18 +43,18 @@ public class Snooper _window.Render += OnRender; _window.Closing += OnClose; - _meshes = new Mesh[1]; + _models = new Model[1]; switch (export) { case UStaticMesh st when st.TryConvert(out var mesh): { - _meshes[0] = new Mesh(mesh.LODs[0], mesh.LODs[0].Verts); + _models[0] = new Model(mesh.LODs[0], mesh.LODs[0].Verts); SetupCamera(mesh.BoundingBox *= Constants.SCALE_DOWN_RATIO); break; } case USkeletalMesh sk when sk.TryConvert(out var mesh): { - _meshes[0] = new Mesh(mesh.LODs[0], mesh.LODs[0].Verts); + _models[0] = new Model(mesh.LODs[0], mesh.LODs[0].Verts); SetupCamera(mesh.BoundingBox *= Constants.SCALE_DOWN_RATIO); break; } @@ -71,10 +70,6 @@ public class Snooper private void SetupCamera(FBox box) { - // X Yaw Gauche Droite - // Y Pitch Haut Bas - // Z Avant Arrière - var center = box.GetCenter(); var position = new Vector3(0f, center.Z, box.Max.Y * 3); _camera = new Camera(position, center); @@ -95,9 +90,9 @@ public class Snooper _gl = GL.GetApi(_window); _gl.Enable(EnableCap.DepthTest); - foreach (var mesh in _meshes) + foreach (var model in _models) { - mesh.Setup(_gl); + model.Setup(_gl); } } @@ -106,9 +101,9 @@ public class Snooper _gl.ClearColor(0.149f, 0.149f, 0.188f, 1.0f); _gl.Clear((uint) ClearBufferMask.ColorBufferBit | (uint) ClearBufferMask.DepthBufferBit); - foreach (var mesh in _meshes) + foreach (var model in _models) { - mesh.Bind(_camera); + model.Bind(_camera); } } @@ -163,9 +158,9 @@ public class Snooper private void OnClose() { - foreach (var mesh in _meshes) + foreach (var model in _models) { - mesh.Dispose(); + model.Dispose(); } } diff --git a/FModel/Views/Snooper/Texture.cs b/FModel/Views/Snooper/Texture.cs index d8d00013..7f9fd236 100644 --- a/FModel/Views/Snooper/Texture.cs +++ b/FModel/Views/Snooper/Texture.cs @@ -24,8 +24,6 @@ public class Texture : IDisposable private void SetParameters() { - _gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int) GLEnum.ClampToEdge); - _gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int) GLEnum.ClampToEdge); _gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) GLEnum.LinearMipmapLinear); _gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int) GLEnum.Linear); _gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBaseLevel, 0);