good cam position + fixed depth mip mapping + trying to understand shit

This commit is contained in:
4sval
2022-08-27 00:42:42 +02:00
parent 7d775a8dd4
commit 0014b6f4ed
9 changed files with 205 additions and 110 deletions

View File

@@ -89,9 +89,13 @@ public partial class App
Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, "Logs"));
Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, ".data"));
#if DEBUG
Log.Logger = new LoggerConfiguration().WriteTo.Console(theme: AnsiConsoleTheme.Literate).CreateLogger();
#else
Log.Logger = new LoggerConfiguration().WriteTo.Console(theme: AnsiConsoleTheme.Literate).WriteTo.File(
Path.Combine(UserSettings.Default.OutputDirectory, "Logs", $"FModel-Log-{DateTime.Now:yyyy-MM-dd}.txt"),
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [FModel] [{Level:u3}] {Message:lj}{NewLine}{Exception}").CreateLogger();
#endif
Log.Information("Version {Version}", Constants.APP_VERSION);
Log.Information("{OS}", GetOperatingSystemProductName());

View File

@@ -9,6 +9,8 @@ public static class Constants
public const string ZERO_64_CHAR = "0000000000000000000000000000000000000000000000000000000000000000";
public static readonly FGuid ZERO_GUID = new(0U);
public const float SCALE_DOWN_RATIO = 0.01F;
public const string WHITE = "#DAE5F2";
public const string GRAY = "#BBBBBB";
public const string RED = "#E06C75";

View File

@@ -105,4 +105,9 @@ public static class Helper
{
return MathF.PI / 180f * degrees;
}
public static float RadiansToDegrees(float radians)
{
return radians* 180f / MathF.PI;
}
}

View File

@@ -79,7 +79,7 @@ public partial class MainWindow
#if DEBUG
await _threadWorkerView.Begin(_ =>
_applicationView.CUE4Parse.Extract(
"FortniteGame/Content/Environments/Props/Winter/Meshes/S_Sled.uasset"));
"/Game/Gadgets/Assets/VinderTech_GliderChute/Glider_Mark_II/Meshes/Glider_Mark_II.uasset"));
#endif
}

View File

@@ -6,22 +6,24 @@ namespace FModel.Views.Snooper;
public class Camera
{
public Vector3 Position { get; set; }
public Vector3 Front { get; set; }
public Vector3 Up { get; private set; }
public float AspectRatio { get; set; }
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;
private float Zoom = 45f;
public Camera(Vector3 position, Vector3 front, Vector3 up, float aspectRatio)
public Camera(Vector3 position, Vector3 direction, float aspectRatio = 16f / 9f)
{
Position = position;
Direction = direction;
AspectRatio = aspectRatio;
Front = front;
Up = up;
// 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));
var pitch = MathF.Atan((Position.Y - Direction.Y) / (Position.Z - Direction.Z));
ModifyDirection(Helper.RadiansToDegrees(yaw), Helper.RadiansToDegrees(pitch));
}
public void ModifyZoom(float zoomAmount)
@@ -38,21 +40,25 @@ 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);
var cameraDirection = Vector3.Zero;
cameraDirection.X = MathF.Cos(Helper.DegreesToRadians(Yaw)) * MathF.Cos(Helper.DegreesToRadians(Pitch));
cameraDirection.Y = MathF.Sin(Helper.DegreesToRadians(Pitch));
cameraDirection.Z = MathF.Sin(Helper.DegreesToRadians(Yaw)) * MathF.Cos(Helper.DegreesToRadians(Pitch));
Front = Vector3.Normalize(cameraDirection);
Direction = Vector3.Normalize(CalculateDirection());
}
public Matrix4x4 GetViewMatrix()
{
return Matrix4x4.CreateLookAt(Position, Position + Front, Up);
return Matrix4x4.CreateLookAt(Position, Position + Direction, Up);
}
public Matrix4x4 GetProjectionMatrix()
{
return Matrix4x4.CreatePerspectiveFieldOfView(Helper.DegreesToRadians(Zoom), AspectRatio, 0.1f, 100.0f);
}
private Vector3 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;
}
}

View File

@@ -0,0 +1,128 @@
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
{
private uint _handle;
private GL _gl;
private BufferObject<uint> _ebo;
private BufferObject<float> _vbo;
private VertexArrayObject<float, uint> _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 };
public uint[] Indices;
public float[] Vertices;
public CMaterialParams[] Params;
public Mesh(CBaseMeshLod lod, CMeshVertex[] vertices)
{
var sections = lod.Sections.Value;
Params = new CMaterialParams[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];
for (uint face = 0; face < section.NumFaces; face++)
{
foreach (var f in _facesIndex)
{
var i = face * _faceSize + f;
var index = section.FirstIndex + i;
var indice = lod.Indices.Value[index];
var vert = vertices[indice];
Vertices[index * _vertexSize] = vert.Position.X * Constants.SCALE_DOWN_RATIO;
Vertices[index * _vertexSize + 1] = vert.Position.Z * Constants.SCALE_DOWN_RATIO;
Vertices[index * _vertexSize + 2] = vert.Position.Y * Constants.SCALE_DOWN_RATIO;
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] = (uint) index;
}
}
Params[s] = new CMaterialParams();
if (section.Material != null && section.Material.TryLoad(out var material) && material is UMaterialInterface unrealMaterial)
{
unrealMaterial.GetParams(Params[s]);
}
}
}
public void Setup(GL gl)
{
_gl = gl;
_handle = _gl.CreateProgram();
_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);
_albedoMap = new Texture[Params.Length];
for (int i = 0; i < _albedoMap.Length; i++)
{
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);
}
}
}
public unsafe void Bind(Camera camera)
{
_vao.Bind();
_shader.Use();
_shader.SetUniform("uModel", Matrix4x4.Identity);
_shader.SetUniform("uView", camera.GetViewMatrix());
_shader.SetUniform("uProjection", camera.GetProjectionMatrix());
// _shader.SetUniform("viewPos", _camera.Position);
for (int i = 0; i < _albedoMap.Length; i++)
{
_shader.SetUniform("material.albedo", i);
_albedoMap[i].Bind(TextureUnit.Texture0 + i);
}
_gl.DrawElements(PrimitiveType.Triangles, (uint) Indices.Length, DrawElementsType.UnsignedInt, null);
}
public void Dispose()
{
_ebo.Dispose();
_vbo.Dispose();
_vao.Dispose();
_shader.Dispose();
_gl.DeleteProgram(_handle);
}
}

View File

@@ -48,7 +48,6 @@ struct Material {
};
uniform Material material;
uniform vec3 viewPos;
out vec4 FragColor;

View File

@@ -1,12 +1,10 @@
using System;
using System.Linq;
using System.Numerics;
using CUE4Parse.UE4.Assets.Exports;
using CUE4Parse.UE4.Assets.Exports.Material;
using CUE4Parse.UE4.Assets.Exports.SkeletalMesh;
using CUE4Parse.UE4.Assets.Exports.StaticMesh;
using CUE4Parse.UE4.Assets.Exports.Texture;
using CUE4Parse.UE4.Objects.Core.Math;
using CUE4Parse_Conversion.Meshes;
using CUE4Parse_Conversion.Textures;
using Silk.NET.Input;
using Silk.NET.Maths;
using Silk.NET.OpenGL;
@@ -22,25 +20,11 @@ public class Snooper
private IKeyboard _keyboard;
private Vector2 _previousMousePosition;
private BufferObject<uint> _ebo;
private BufferObject<float> _vbo;
private VertexArrayObject<float, uint> _vao;
private Shader _shader;
private CMaterialParams _params;
private Texture _albedoMap;
private Texture _normalMap;
private uint[] _indices;
private float[] _vertices;
private Mesh[] _meshes;
public int Width { get; }
public int Height { get; }
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 };
public Snooper(UObject export)
{
const double ratio = .6;
@@ -60,42 +44,19 @@ public class Snooper
_window.Render += OnRender;
_window.Closing += OnClose;
_meshes = new Mesh[1];
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 i = face * _faceSize + f;
var index = section.FirstIndex + i;
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] = i;
}
}
_params = new CMaterialParams();
if (section.Material != null && section.Material.TryLoad(out var material) && material is UMaterialInterface unrealMaterial)
{
unrealMaterial.GetParams(_params);
}
}
_meshes[0] = new Mesh(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);
SetupCamera(mesh.BoundingBox *= Constants.SCALE_DOWN_RATIO);
break;
}
default:
@@ -108,6 +69,17 @@ public class Snooper
_window.Run();
}
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);
}
private void OnLoad()
{
var input = _window.CreateInput();
@@ -121,65 +93,44 @@ public class Snooper
}
_gl = GL.GetApi(_window);
_gl.Enable(EnableCap.DepthTest);
_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);
if (_params.Diffuse is UTexture2D { IsVirtual: false } diffuse && diffuse.GetFirstMip() is { } mip)
foreach (var mesh in _meshes)
{
TextureDecoder.DecodeTexture(mip, diffuse.Format, diffuse.isNormalMap, out var data, out _);
_albedoMap = new Texture(_gl, data, (uint) mip.SizeX, (uint) mip.SizeY);
mesh.Setup(_gl);
}
}
private unsafe void OnRender(double deltaTime)
private void OnRender(double deltaTime)
{
_gl.Clear((uint) ClearBufferMask.ColorBufferBit);
_gl.ClearColor(0.149f, 0.149f, 0.188f, 1.0f);
_gl.Clear((uint) ClearBufferMask.ColorBufferBit | (uint) ClearBufferMask.DepthBufferBit);
_vao.Bind();
_shader.Use();
_albedoMap.Bind(TextureUnit.Texture0);
_shader.SetUniform("uModel", Matrix4x4.Identity);
_shader.SetUniform("uView", _camera.GetViewMatrix());
_shader.SetUniform("uProjection", _camera.GetProjectionMatrix());
// _shader.SetUniform("viewPos", _camera.Position);
//Configure the materials variables.
_shader.SetUniform("material.albedo", 0);
_gl.DrawElements(PrimitiveType.Triangles, (uint) _indices.Length, DrawElementsType.UnsignedInt, null);
foreach (var mesh in _meshes)
{
mesh.Bind(_camera);
}
}
private void OnUpdate(double deltaTime)
{
var speed = _keyboard.IsKeyPressed(Key.ShiftLeft) ? 5f : 2.5f;
var speed = _keyboard.IsKeyPressed(Key.ShiftLeft) ? 2.5f : 1f;
var moveSpeed = speed * (float) deltaTime;
if (_keyboard.IsKeyPressed(Key.W))
{
_camera.Position += moveSpeed * _camera.Front;
_camera.Position += moveSpeed * _camera.Direction;
}
if (_keyboard.IsKeyPressed(Key.S))
{
_camera.Position -= moveSpeed * _camera.Front;
_camera.Position -= moveSpeed * _camera.Direction;
}
if (_keyboard.IsKeyPressed(Key.A))
{
_camera.Position -= Vector3.Normalize(Vector3.Cross(_camera.Front, _camera.Up)) * moveSpeed;
_camera.Position -= Vector3.Normalize(Vector3.Cross(_camera.Direction, _camera.Up)) * moveSpeed;
}
if (_keyboard.IsKeyPressed(Key.D))
{
_camera.Position += Vector3.Normalize(Vector3.Cross(_camera.Front, _camera.Up)) * moveSpeed;
_camera.Position += Vector3.Normalize(Vector3.Cross(_camera.Direction, _camera.Up)) * moveSpeed;
}
if (_keyboard.IsKeyPressed(Key.E))
{
@@ -212,10 +163,10 @@ public class Snooper
private void OnClose()
{
_ebo.Dispose();
_vbo.Dispose();
_vao.Dispose();
_shader.Dispose();
foreach (var mesh in _meshes)
{
mesh.Dispose();
}
}
private void KeyDown(IKeyboard keyboard, Key key, int arg3)