From 2c0fee3fd362581bf599f6ee55ff074609836338 Mon Sep 17 00:00:00 2001 From: 4sval Date: Thu, 25 Aug 2022 23:38:34 +0200 Subject: [PATCH] proof of concept --- CUE4Parse | 2 +- FModel/Creator/Bases/FN/BaseCommunity.cs | 2 +- FModel/Creator/Bases/FN/BaseIcon.cs | 2 +- FModel/Creator/Bases/FN/BaseIconStats.cs | 4 +- FModel/FModel.sln | 6 - FModel/MainWindow.xaml.cs | 11 +- FModel/ViewModels/CUE4ParseViewModel.cs | 8 +- FModel/Views/Snooper/BufferObject.cs | 34 ++++ FModel/Views/Snooper/Shader.cs | 142 ++++++++++++++++ FModel/Views/Snooper/Snooper.cs | 193 ++++++++++++++++++++++ FModel/Views/Snooper/Texture.cs | 46 ++++++ FModel/Views/Snooper/Transform.cs | 15 ++ FModel/Views/Snooper/VertexArrayObject.cs | 36 ++++ FModel/Views/Snooper/Viewer.cs | 67 -------- 14 files changed, 480 insertions(+), 88 deletions(-) create mode 100644 FModel/Views/Snooper/BufferObject.cs create mode 100644 FModel/Views/Snooper/Shader.cs create mode 100644 FModel/Views/Snooper/Snooper.cs create mode 100644 FModel/Views/Snooper/Texture.cs create mode 100644 FModel/Views/Snooper/Transform.cs create mode 100644 FModel/Views/Snooper/VertexArrayObject.cs delete mode 100644 FModel/Views/Snooper/Viewer.cs diff --git a/CUE4Parse b/CUE4Parse index 67a3af8b..5f323ef9 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 67a3af8b005e20b14846e77db759382084b989df +Subproject commit 5f323ef90c2ee82eb6d7967783c42a3656ed401c diff --git a/FModel/Creator/Bases/FN/BaseCommunity.cs b/FModel/Creator/Bases/FN/BaseCommunity.cs index 1e0a7294..0967d38a 100644 --- a/FModel/Creator/Bases/FN/BaseCommunity.cs +++ b/FModel/Creator/Bases/FN/BaseCommunity.cs @@ -1,8 +1,8 @@ +using CUE4Parse.FN.Enums; using CUE4Parse.UE4.Assets.Exports; using CUE4Parse.UE4.Objects.GameplayTags; using CUE4Parse.UE4.Objects.UObject; using CUE4Parse.UE4.Versions; -using CUE4Parse_Fortnite.Enums; using FModel.Extensions; using FModel.Framework; using FModel.Services; diff --git a/FModel/Creator/Bases/FN/BaseIcon.cs b/FModel/Creator/Bases/FN/BaseIcon.cs index 048e6a0e..15f792e6 100644 --- a/FModel/Creator/Bases/FN/BaseIcon.cs +++ b/FModel/Creator/Bases/FN/BaseIcon.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Windows; +using CUE4Parse.FN.Enums; using CUE4Parse.UE4.Assets.Exports; using CUE4Parse.UE4.Assets.Exports.Engine; using CUE4Parse.UE4.Assets.Exports.Material; @@ -12,7 +13,6 @@ using CUE4Parse.UE4.Objects.GameplayTags; using CUE4Parse.UE4.Objects.UObject; using CUE4Parse_Conversion.Textures; -using CUE4Parse_Fortnite.Enums; using FModel.Settings; using SkiaSharp; diff --git a/FModel/Creator/Bases/FN/BaseIconStats.cs b/FModel/Creator/Bases/FN/BaseIconStats.cs index a23e02fc..3a8e374f 100644 --- a/FModel/Creator/Bases/FN/BaseIconStats.cs +++ b/FModel/Creator/Bases/FN/BaseIconStats.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using CUE4Parse.FN.Enums; using CUE4Parse.UE4.Assets.Exports; using CUE4Parse.UE4.Assets.Exports.Engine; using CUE4Parse.UE4.Assets.Objects; @@ -7,7 +8,6 @@ using CUE4Parse.UE4.Objects.Engine.Curves; using CUE4Parse.UE4.Objects.GameplayTags; using CUE4Parse.UE4.Objects.UObject; -using CUE4Parse_Fortnite.Enums; using FModel.Extensions; using FModel.Framework; using SkiaSharp; @@ -288,4 +288,4 @@ public void Draw(SKCanvas c, SKColor sliderColor, int width, int height, ref flo var sliderWidth = (sliderRight - height * 2) * (floatValue / _maxValue); c.DrawRect(new SKRect(height * 2, y, Math.Min(height * 2 + sliderWidth, sliderRight), y + 5), _statPaint); } -} \ No newline at end of file +} diff --git a/FModel/FModel.sln b/FModel/FModel.sln index 7de93e7b..238d1b59 100644 --- a/FModel/FModel.sln +++ b/FModel/FModel.sln @@ -7,8 +7,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FModel", "FModel.csproj", " EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUE4Parse", "..\CUE4Parse\CUE4Parse\CUE4Parse.csproj", "{C4620341-BBB7-4384-AC7D-5082D3E0386E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUE4Parse-Fortnite", "..\CUE4Parse\CUE4Parse-Fortnite\CUE4Parse-Fortnite.csproj", "{7765FB4C-B54D-427B-ABB6-1073687E56BD}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUE4Parse-Conversion", "..\CUE4Parse\CUE4Parse-Conversion\CUE4Parse-Conversion.csproj", "{D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}" EndProject Global @@ -25,10 +23,6 @@ Global {C4620341-BBB7-4384-AC7D-5082D3E0386E}.Debug|Any CPU.Build.0 = Debug|Any CPU {C4620341-BBB7-4384-AC7D-5082D3E0386E}.Release|Any CPU.ActiveCfg = Release|Any CPU {C4620341-BBB7-4384-AC7D-5082D3E0386E}.Release|Any CPU.Build.0 = Release|Any CPU - {7765FB4C-B54D-427B-ABB6-1073687E56BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7765FB4C-B54D-427B-ABB6-1073687E56BD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7765FB4C-B54D-427B-ABB6-1073687E56BD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7765FB4C-B54D-427B-ABB6-1073687E56BD}.Release|Any CPU.Build.0 = Release|Any CPU {D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}.Debug|Any CPU.Build.0 = Debug|Any CPU {D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/FModel/MainWindow.xaml.cs b/FModel/MainWindow.xaml.cs index f30583bd..d2590bc8 100644 --- a/FModel/MainWindow.xaml.cs +++ b/FModel/MainWindow.xaml.cs @@ -11,7 +11,6 @@ using FModel.ViewModels; using FModel.Views; using FModel.Views.Resources.Controls; -using FModel.Views.Snooper; using ICSharpCode.AvalonEdit.Editing; namespace FModel; @@ -53,10 +52,6 @@ private async void OnLoaded(object sender, RoutedEventArgs e) ApplicationService.ApiEndpointView.FModelApi.CheckForUpdates(UserSettings.Default.UpdateMode); #endif - var v = new Viewer(); - v.Run(); - return; - switch (UserSettings.Default.AesReload) { case EAesReload.Always: @@ -80,6 +75,12 @@ private async void OnLoaded(object sender, RoutedEventArgs e) if (UserSettings.Default.DiscordRpc == EDiscordRpc.Always) _discordHandler.Initialize(_applicationView.CUE4Parse.Game); + +#if DEBUG + await _threadWorkerView.Begin(_ => + _applicationView.CUE4Parse.Extract( + "FortniteGame/Content/Environments/Props/Winter/Meshes/SM_Garland_Merge.uasset")); +#endif } private void OnGridSplitterDoubleClick(object sender, MouseButtonEventArgs e) diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index 440a821e..4b9ac9a6 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -38,6 +38,7 @@ using FModel.Settings; using FModel.Views; using FModel.Views.Resources.Controls; +using FModel.Views.Snooper; using Newtonsoft.Json; using Serilog; using SkiaSharp; @@ -752,11 +753,8 @@ public void ExtractAndScroll(string fullPath, string objectName) export.Owner.Name.EndsWith($"/RenderSwitch_Materials/{export.Name}", StringComparison.OrdinalIgnoreCase) || export.Owner.Name.EndsWith($"/MI_BPTile/{export.Name}", StringComparison.OrdinalIgnoreCase))): { - Application.Current.Dispatcher.Invoke(delegate - { - var modelViewer = Helper.GetWindow("Model Viewer", () => new ModelViewer().Show()); - modelViewer.Load(export); - }); + var snooper = new Snooper(export); + snooper.Run(); return true; } case UMaterialInstance m when ModelIsOverwritingMaterial: diff --git a/FModel/Views/Snooper/BufferObject.cs b/FModel/Views/Snooper/BufferObject.cs new file mode 100644 index 00000000..79fe7058 --- /dev/null +++ b/FModel/Views/Snooper/BufferObject.cs @@ -0,0 +1,34 @@ +using System; +using Silk.NET.OpenGL; + +namespace FModel.Views.Snooper; + +public class BufferObject : IDisposable where TDataType : unmanaged +{ + private uint _handle; + private BufferTargetARB _bufferType; + private GL _gl; + + public unsafe BufferObject(GL gl, Span data, BufferTargetARB bufferType) + { + _gl = gl; + _bufferType = bufferType; + + _handle = _gl.GenBuffer(); + Bind(); + fixed (void* d = data) + { + _gl.BufferData(bufferType, (nuint) (data.Length * sizeof(TDataType)), d, BufferUsageARB.StaticDraw); + } + } + + public void Bind() + { + _gl.BindBuffer(_bufferType, _handle); + } + + public void Dispose() + { + _gl.DeleteBuffer(_handle); + } +} diff --git a/FModel/Views/Snooper/Shader.cs b/FModel/Views/Snooper/Shader.cs new file mode 100644 index 00000000..4cf96dc5 --- /dev/null +++ b/FModel/Views/Snooper/Shader.cs @@ -0,0 +1,142 @@ +using System; +using System.Numerics; +using Silk.NET.OpenGL; + +namespace FModel.Views.Snooper; + +public class Shader : IDisposable +{ + private uint _handle; + private GL _gl; + + private readonly string VertexShaderSource = @" +#version 330 core +layout (location = 0) in vec3 vPos; +layout (location = 1) in vec3 vNormal; +layout (location = 2) in vec2 vTexCoords; + +uniform mat4 uModel; +uniform mat4 uView; +uniform mat4 uProjection; + +out vec3 fNormal; +out vec3 fPos; +out vec2 fTexCoords; + +void main() +{ + //Multiplying our uniform with the vertex position, the multiplication order here does matter. + gl_Position = uProjection * uView * uModel * vec4(vPos, 1.0); + //We want to know the fragment's position in World space, so we multiply ONLY by uModel and not uView or uProjection + fPos = vec3(uModel * vec4(vPos, 1.0)); + //The Normal needs to be in World space too, but needs to account for Scaling of the object + fNormal = mat3(transpose(inverse(uModel))) * vNormal; + //Pass the texture coordinates straight through to the fragment shader + fTexCoords = vTexCoords; +} + "; + + private readonly string FragmentShaderSource = @" +#version 330 core + +in vec3 fNormal; +in vec3 fPos; +in vec2 fTexCoords; + +uniform vec3 viewPos; + +out vec4 FragColor; + +void main() +{ + vec3 viewDirection = normalize(viewPos - fPos); + FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f); +} + "; + + public Shader(GL gl) + { + _gl = gl; + + uint vertex = LoadShader(ShaderType.VertexShader, VertexShaderSource); + uint fragment = LoadShader(ShaderType.FragmentShader, FragmentShaderSource); + _handle = _gl.CreateProgram(); + _gl.AttachShader(_handle, vertex); + _gl.AttachShader(_handle, fragment); + _gl.LinkProgram(_handle); + _gl.GetProgram(_handle, GLEnum.LinkStatus, out var status); + if (status == 0) + { + throw new Exception($"Program failed to link with error: {_gl.GetProgramInfoLog(_handle)}"); + } + _gl.DetachShader(_handle, vertex); + _gl.DetachShader(_handle, fragment); + _gl.DeleteShader(vertex); + _gl.DeleteShader(fragment); + } + + public void Use() + { + _gl.UseProgram(_handle); + } + + public void SetUniform(string name, int value) + { + int location = _gl.GetUniformLocation(_handle, name); + if (location == -1) + { + throw new Exception($"{name} uniform not found on shader."); + } + _gl.Uniform1(location, value); + } + + public unsafe void SetUniform(string name, Matrix4x4 value) + { + //A new overload has been created for setting a uniform so we can use the transform in our shader. + int location = _gl.GetUniformLocation(_handle, name); + if (location == -1) + { + throw new Exception($"{name} uniform not found on shader."); + } + _gl.UniformMatrix4(location, 1, false, (float*) &value); + } + + public void SetUniform(string name, float value) + { + int location = _gl.GetUniformLocation(_handle, name); + if (location == -1) + { + throw new Exception($"{name} uniform not found on shader."); + } + _gl.Uniform1(location, value); + } + + public void SetUniform(string name, Vector3 value) + { + int location = _gl.GetUniformLocation(_handle, name); + if (location == -1) + { + throw new Exception($"{name} uniform not found on shader."); + } + _gl.Uniform3(location, value.X, value.Y, value.Z); + } + + public void Dispose() + { + _gl.DeleteProgram(_handle); + } + + private uint LoadShader(ShaderType type, string content) + { + uint handle = _gl.CreateShader(type); + _gl.ShaderSource(handle, content); + _gl.CompileShader(handle); + string infoLog = _gl.GetShaderInfoLog(handle); + if (!string.IsNullOrWhiteSpace(infoLog)) + { + throw new Exception($"Error compiling shader of type {type}, failed with error {infoLog}"); + } + + return handle; + } +} diff --git a/FModel/Views/Snooper/Snooper.cs b/FModel/Views/Snooper/Snooper.cs new file mode 100644 index 00000000..323c33ec --- /dev/null +++ b/FModel/Views/Snooper/Snooper.cs @@ -0,0 +1,193 @@ +using System; +using System.Linq; +using System.Numerics; +using CUE4Parse.UE4.Assets.Exports; +using CUE4Parse.UE4.Assets.Exports.StaticMesh; +using CUE4Parse_Conversion.Meshes; +using Silk.NET.Input; +using Silk.NET.Maths; +using Silk.NET.OpenGL; +using Silk.NET.Windowing; + +namespace FModel.Views.Snooper; + +public class Snooper +{ + private IWindow _window; + private GL _gl; + private Camera _camera; + private IKeyboard _keyboard; + private Vector2 _previousMousePosition; + + private BufferObject _ebo; + private BufferObject _vbo; + private VertexArrayObject _vao; + private Shader _shader; + + private uint[] _indices; + private float[] _vertices; + + public int Width { get; } + public int Height { get; } + + private const double _ratio = .75; + private const int _vertexSize = 8; // just so we don't have to do .Length + private const uint _faceSize = 3; // just so we don't have to do .Length + private readonly uint[] _facesIndex = { 1, 0, 2 }; + + public Snooper(UObject export) + { + var x = System.Windows.SystemParameters.MaximizedPrimaryScreenWidth; + var y = System.Windows.SystemParameters.MaximizedPrimaryScreenHeight; + Width = Convert.ToInt32(x * _ratio); + Height = Convert.ToInt32(y * _ratio); + + var options = WindowOptions.Default; + options.Size = new Vector2D(Width, Height); + options.Title = "Snooper"; + _window = Window.Create(options); + + _window.Load += OnLoad; + _window.Update += OnUpdate; + _window.Render += OnRender; + _window.Closing += OnClose; + + switch (export) + { + case UStaticMesh st when st.TryConvert(out var mesh): + { + _indices = new uint[mesh.LODs[0].Sections.Value.Sum(section => section.NumFaces * _faceSize)]; + _vertices = new float[_indices.Length * _vertexSize]; + foreach (var section in mesh.LODs[0].Sections.Value) + { + for (uint face = 0; face < section.NumFaces; face++) + { + foreach (var f in _facesIndex) + { + var index = section.FirstIndex + face * _faceSize + f; + var indice = mesh.LODs[0].Indices.Value[index]; + + var vert = mesh.LODs[0].Verts[indice]; + _vertices[index * _vertexSize] = vert.Position.X * 0.01f; + _vertices[index * _vertexSize + 1] = vert.Position.Z * 0.01f; + _vertices[index * _vertexSize + 2] = vert.Position.Y * 0.01f; + _vertices[index * _vertexSize + 3] = vert.Normal.X; + _vertices[index * _vertexSize + 4] = vert.Normal.Z; + _vertices[index * _vertexSize + 5] = vert.Normal.Y; + _vertices[index * _vertexSize + 6] = vert.UV.U; + _vertices[index * _vertexSize + 7] = vert.UV.V; + + _indices[index] = face * _faceSize + f; + } + } + } + break; + } + default: + throw new ArgumentOutOfRangeException(nameof(export)); + } + } + + public void Run() + { + _window.Run(); + } + + private void OnLoad() + { + var input = _window.CreateInput(); + _keyboard = input.Keyboards[0]; + _keyboard.KeyDown += KeyDown; + foreach (var mouse in input.Mice) + { + mouse.Cursor.CursorMode = CursorMode.Raw; + mouse.MouseMove += OnMouseMove; + mouse.Scroll += OnMouseWheel; + } + + _gl = GL.GetApi(_window); + + _ebo = new BufferObject(_gl, _indices, BufferTargetARB.ElementArrayBuffer); + _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); // normals + _vao.VertexAttributePointer(2, 2, VertexAttribPointerType.Float, _vertexSize, 6); // uv + + _shader = new Shader(_gl); + + _camera = new Camera(Vector3.UnitZ * 6, Vector3.UnitZ * -1, Vector3.UnitY, Width / Height); + } + + private unsafe void OnRender(double deltaTime) + { + _gl.Clear((uint) ClearBufferMask.ColorBufferBit); + + _vao.Bind(); + _shader.Use(); + + _shader.SetUniform("uModel", Matrix4x4.Identity); + _shader.SetUniform("uView", _camera.GetViewMatrix()); + _shader.SetUniform("uProjection", _camera.GetProjectionMatrix()); + // _shader.SetUniform("viewPos", _camera.Position); + + _gl.DrawElements(PrimitiveType.Triangles, (uint) _indices.Length, DrawElementsType.UnsignedInt, null); + } + + private void OnUpdate(double deltaTime) + { + var moveSpeed = 5f * (float) deltaTime; + if (_keyboard.IsKeyPressed(Key.W)) + { + _camera.Position += moveSpeed * _camera.Front; + } + if (_keyboard.IsKeyPressed(Key.S)) + { + _camera.Position -= moveSpeed * _camera.Front; + } + if (_keyboard.IsKeyPressed(Key.A)) + { + _camera.Position -= Vector3.Normalize(Vector3.Cross(_camera.Front, _camera.Up)) * moveSpeed; + } + if (_keyboard.IsKeyPressed(Key.D)) + { + _camera.Position += Vector3.Normalize(Vector3.Cross(_camera.Front, _camera.Up)) * moveSpeed; + } + } + + private void OnMouseMove(IMouse mouse, Vector2 position) + { + const float lookSensitivity = 0.1f; + if (_previousMousePosition == default) { _previousMousePosition = position; } + else + { + var xOffset = (position.X - _previousMousePosition.X) * lookSensitivity; + var yOffset = (position.Y - _previousMousePosition.Y) * lookSensitivity; + _previousMousePosition = position; + + _camera.ModifyDirection(xOffset, yOffset); + } + } + + private void OnMouseWheel(IMouse mouse, ScrollWheel scrollWheel) + { + _camera.ModifyZoom(scrollWheel.Y); + } + + private void OnClose() + { + _ebo.Dispose(); + _vbo.Dispose(); + _vao.Dispose(); + _shader.Dispose(); + } + + private void KeyDown(IKeyboard keyboard, Key key, int arg3) + { + if (key == Key.Escape) + { + _window.Close(); + } + } +} diff --git a/FModel/Views/Snooper/Texture.cs b/FModel/Views/Snooper/Texture.cs new file mode 100644 index 00000000..ed843e73 --- /dev/null +++ b/FModel/Views/Snooper/Texture.cs @@ -0,0 +1,46 @@ +using Silk.NET.OpenGL; +using System; + +namespace FModel.Views.Snooper; + +public class Texture : IDisposable +{ + private uint _handle; + private GL _gl; + + public unsafe Texture(GL gl, Span data, uint width, uint height) + { + _gl = gl; + + _handle = _gl.GenTexture(); + Bind(); + + fixed (void* d = &data[0]) + { + _gl.TexImage2D(TextureTarget.Texture2D, 0, (int) InternalFormat.Rgba, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, d); + SetParameters(); + } + } + + 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); + _gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMaxLevel, 8); + _gl.GenerateMipmap(TextureTarget.Texture2D); + } + + public void Bind(TextureUnit textureSlot = TextureUnit.Texture0) + { + _gl.ActiveTexture(textureSlot); + _gl.BindTexture(TextureTarget.Texture2D, _handle); + } + + public void Dispose() + { + _gl.DeleteTexture(_handle); + } +} diff --git a/FModel/Views/Snooper/Transform.cs b/FModel/Views/Snooper/Transform.cs new file mode 100644 index 00000000..563fb14d --- /dev/null +++ b/FModel/Views/Snooper/Transform.cs @@ -0,0 +1,15 @@ +using System.Numerics; + +namespace FModel.Views.Snooper; + +public class Transform +{ + public Vector3 Position { get; set; } = new Vector3(0, 0, 0); + + public float Scale { get; set; } = 1f; + + public Quaternion Rotation { get; set; } = Quaternion.Identity; + + //Note: The order here does matter. + public Matrix4x4 ViewMatrix => Matrix4x4.Identity * Matrix4x4.CreateFromQuaternion(Rotation) * Matrix4x4.CreateScale(Scale) * Matrix4x4.CreateTranslation(Position); +} diff --git a/FModel/Views/Snooper/VertexArrayObject.cs b/FModel/Views/Snooper/VertexArrayObject.cs new file mode 100644 index 00000000..17068915 --- /dev/null +++ b/FModel/Views/Snooper/VertexArrayObject.cs @@ -0,0 +1,36 @@ +using System; +using Silk.NET.OpenGL; + +namespace FModel.Views.Snooper; + +public class VertexArrayObject : IDisposable where TVertexType : unmanaged where TIndexType : unmanaged +{ + private uint _handle; + private GL _gl; + + public VertexArrayObject(GL gl, BufferObject vbo, BufferObject ebo) + { + _gl = gl; + + _handle = _gl.GenVertexArray(); + Bind(); + vbo.Bind(); + ebo.Bind(); + } + + public unsafe void VertexAttributePointer(uint index, int count, VertexAttribPointerType type, uint vertexSize, int offSet) + { + _gl.VertexAttribPointer(index, count, type, false, vertexSize * (uint) sizeof(TVertexType), (void*) (offSet * sizeof(TVertexType))); + _gl.EnableVertexAttribArray(index); + } + + public void Bind() + { + _gl.BindVertexArray(_handle); + } + + public void Dispose() + { + _gl.DeleteVertexArray(_handle); + } +} diff --git a/FModel/Views/Snooper/Viewer.cs b/FModel/Views/Snooper/Viewer.cs deleted file mode 100644 index eced863f..00000000 --- a/FModel/Views/Snooper/Viewer.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.Numerics; -using Silk.NET.Input; -using Silk.NET.Maths; -using Silk.NET.OpenGL; -using Silk.NET.Windowing; - -namespace FModel.Views.Snooper; - -public class Viewer -{ - private IWindow _window; - private GL _gl; - private Camera _camera; - private IKeyboard _keyboard; - - public int Width { get; } - public int Height { get; } - - private const double _ratio = .75; - - public Viewer() - { - var x = System.Windows.SystemParameters.MaximizedPrimaryScreenWidth; - var y = System.Windows.SystemParameters.MaximizedPrimaryScreenHeight; - Width = Convert.ToInt32(x * _ratio); - Height = Convert.ToInt32(y * _ratio); - - var options = WindowOptions.Default; - options.Size = new Vector2D(Width, Height); - options.Title = "Snooper"; - _window = Window.Create(options); - - _window.Load += OnLoad; - _window.Closing += OnClose; - } - - public void Run() - { - _window.Run(); - } - - private void OnLoad() - { - var input = _window.CreateInput(); - _keyboard = input.Keyboards[0]; - _keyboard.KeyDown += KeyDown; - - _gl = GL.GetApi(_window); - - //Start a camera at position 3 on the Z axis, looking at position -1 on the Z axis - _camera = new Camera(Vector3.UnitZ * 6, Vector3.UnitZ * -1, Vector3.UnitY, Width / Height); - } - - private void OnClose() - { - - } - - private void KeyDown(IKeyboard keyboard, Key key, int arg3) - { - if (key == Key.Escape) - { - _window.Close(); - } - } -}