mirror of
https://github.com/4sval/FModel.git
synced 2026-07-27 22:08:16 -05:00
proof of concept
This commit is contained in:
parent
9b967341c2
commit
2c0fee3fd3
|
|
@ -1 +1 @@
|
|||
Subproject commit 67a3af8b005e20b14846e77db759382084b989df
|
||||
Subproject commit 5f323ef90c2ee82eb6d7967783c42a3656ed401c
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ using System;
|
|||
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.Core.Math;
|
|||
using CUE4Parse.UE4.Objects.GameplayTags;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using CUE4Parse_Conversion.Textures;
|
||||
using CUE4Parse_Fortnite.Enums;
|
||||
using FModel.Settings;
|
||||
using SkiaSharp;
|
||||
|
||||
|
|
|
|||
|
|
@ -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.Core.i18N;
|
|||
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 class IconStat
|
|||
var sliderWidth = (sliderRight - height * 2) * (floatValue / _maxValue);
|
||||
c.DrawRect(new SKRect(height * 2, y, Math.Min(height * 2 + sliderWidth, sliderRight), y + 5), _statPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ using FModel.Settings;
|
|||
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 @@ public partial class MainWindow
|
|||
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 @@ public partial class MainWindow
|
|||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ using FModel.Services;
|
|||
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 class CUE4ParseViewModel : ViewModel
|
|||
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<ModelViewer>("Model Viewer", () => new ModelViewer().Show());
|
||||
modelViewer.Load(export);
|
||||
});
|
||||
var snooper = new Snooper(export);
|
||||
snooper.Run();
|
||||
return true;
|
||||
}
|
||||
case UMaterialInstance m when ModelIsOverwritingMaterial:
|
||||
|
|
|
|||
34
FModel/Views/Snooper/BufferObject.cs
Normal file
34
FModel/Views/Snooper/BufferObject.cs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
using Silk.NET.OpenGL;
|
||||
|
||||
namespace FModel.Views.Snooper;
|
||||
|
||||
public class BufferObject<TDataType> : IDisposable where TDataType : unmanaged
|
||||
{
|
||||
private uint _handle;
|
||||
private BufferTargetARB _bufferType;
|
||||
private GL _gl;
|
||||
|
||||
public unsafe BufferObject(GL gl, Span<TDataType> 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);
|
||||
}
|
||||
}
|
||||
142
FModel/Views/Snooper/Shader.cs
Normal file
142
FModel/Views/Snooper/Shader.cs
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
193
FModel/Views/Snooper/Snooper.cs
Normal file
193
FModel/Views/Snooper/Snooper.cs
Normal file
|
|
@ -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<uint> _ebo;
|
||||
private BufferObject<float> _vbo;
|
||||
private VertexArrayObject<float, uint> _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<int>(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<uint>(_gl, _indices, BufferTargetARB.ElementArrayBuffer);
|
||||
_vbo = new BufferObject<float>(_gl, _vertices, BufferTargetARB.ArrayBuffer);
|
||||
_vao = new VertexArrayObject<float, uint>(_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();
|
||||
}
|
||||
}
|
||||
}
|
||||
46
FModel/Views/Snooper/Texture.cs
Normal file
46
FModel/Views/Snooper/Texture.cs
Normal file
|
|
@ -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<byte> 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);
|
||||
}
|
||||
}
|
||||
15
FModel/Views/Snooper/Transform.cs
Normal file
15
FModel/Views/Snooper/Transform.cs
Normal file
|
|
@ -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);
|
||||
}
|
||||
36
FModel/Views/Snooper/VertexArrayObject.cs
Normal file
36
FModel/Views/Snooper/VertexArrayObject.cs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
using System;
|
||||
using Silk.NET.OpenGL;
|
||||
|
||||
namespace FModel.Views.Snooper;
|
||||
|
||||
public class VertexArrayObject<TVertexType, TIndexType> : IDisposable where TVertexType : unmanaged where TIndexType : unmanaged
|
||||
{
|
||||
private uint _handle;
|
||||
private GL _gl;
|
||||
|
||||
public VertexArrayObject(GL gl, BufferObject<TVertexType> vbo, BufferObject<TIndexType> 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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<int>(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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user