mirror of
https://github.com/4sval/FModel.git
synced 2026-03-22 01:34:37 -05:00
convex collision preview
This commit is contained in:
parent
d3ce4bedd7
commit
ca95df2dd4
|
|
@ -1 +1 @@
|
|||
Subproject commit 38be126747f52c4a72f98d09de2d8073c4af750e
|
||||
Subproject commit fb9413d0362457867e0c46c339ab3756c2b0a399
|
||||
|
|
@ -41,8 +41,6 @@ public partial class App
|
|||
{
|
||||
UserSettings.Default = JsonConvert.DeserializeObject<UserSettings>(
|
||||
File.ReadAllText(UserSettings.FilePath), JsonNetSerializer.SerializerSettings);
|
||||
|
||||
/*if (UserSettings.Default.ShowChangelog) */MigrateV1Games();
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
@ -143,17 +141,6 @@ public partial class App
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void MigrateV1Games()
|
||||
{
|
||||
foreach ((var gameDir, var setting) in UserSettings.Default.ManualGames)
|
||||
{
|
||||
if (!Directory.Exists(gameDir)) continue;
|
||||
UserSettings.Default.PerDirectory[gameDir] =
|
||||
DirectorySettings.Default(setting.GameName, setting.GameDirectory, true, setting.OverridedGame, setting.AesKeys?.MainKey);
|
||||
}
|
||||
UserSettings.Default.ManualGames.Clear();
|
||||
}
|
||||
|
||||
private string GetOperatingSystemProductName()
|
||||
{
|
||||
var productName = string.Empty;
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@
|
|||
<None Remove="Resources\light.vert" />
|
||||
<None Remove="Resources\bone.frag" />
|
||||
<None Remove="Resources\bone.vert" />
|
||||
<None Remove="Resources\collision.vert" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
@ -141,6 +142,7 @@
|
|||
<EmbeddedResource Include="Resources\light.vert" />
|
||||
<EmbeddedResource Include="Resources\bone.frag" />
|
||||
<EmbeddedResource Include="Resources\bone.vert" />
|
||||
<EmbeddedResource Include="Resources\collision.vert" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -83,9 +83,9 @@ public partial class MainWindow
|
|||
).ConfigureAwait(false);
|
||||
|
||||
#if DEBUG
|
||||
await _threadWorkerView.Begin(cancellationToken =>
|
||||
_applicationView.CUE4Parse.Extract(cancellationToken,
|
||||
"ShooterGame/Content/Characters/Smonk/S0/3P/Models/TP_Smonk_S0_Skelmesh.uasset"));
|
||||
// await _threadWorkerView.Begin(cancellationToken =>
|
||||
// _applicationView.CUE4Parse.Extract(cancellationToken,
|
||||
// "FortniteGame/Content/Environments/Asteria/Props/Coastal/Coastal_Boat_B/Meshes/SM_Coastal_Boat_B.uasset"));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
20
FModel/Resources/collision.vert
Normal file
20
FModel/Resources/collision.vert
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#version 460 core
|
||||
|
||||
layout (location = 0) in vec3 vPos;
|
||||
|
||||
uniform mat4 uView;
|
||||
uniform mat4 uProjection;
|
||||
uniform mat4 uInstanceMatrix;
|
||||
uniform mat4 uCollisionMatrix;
|
||||
uniform float uScaleDown;
|
||||
|
||||
out vec3 fPos;
|
||||
out vec3 fColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_PointSize = 7.5f;
|
||||
gl_Position = uProjection * uView * uInstanceMatrix * uCollisionMatrix * vec4(vPos.xzy * uScaleDown, 1.0);
|
||||
fPos = vec3(uInstanceMatrix * uCollisionMatrix * vec4(vPos.xzy * uScaleDown, 1.0));
|
||||
fColor = vec3(1.0);
|
||||
}
|
||||
|
|
@ -17,7 +17,6 @@ public class EndpointSettings : ViewModel
|
|||
return new EndpointSettings[]
|
||||
{
|
||||
new("https://fortnitecentral.genxgames.gg/api/v1/aes", "$.['mainKey','dynamicKeys']"),
|
||||
// new("https://fortnitecentral.genxgames.gg/api/v1/mappings", "$.[?(@.meta.compressionMethod=='Oodle')].['url','fileName']")
|
||||
new("https://fortnitecentral.genxgames.gg/api/v1/mappings", "$.[0].['url','fileName']") // just get the first available, not just oodle! (Unfortunately not default except when resetting settings)
|
||||
};
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -399,6 +399,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
else if (endpoint.IsValid)
|
||||
{
|
||||
var mappingsFolder = Path.Combine(UserSettings.Default.OutputDirectory, ".data");
|
||||
if (endpoint.Path == "$.[?(@.meta.compressionMethod=='Oodle')].['url','fileName']") endpoint.Path = "$.[0].['url','fileName']";
|
||||
var mappings = _apiEndpointView.DynamicApi.GetMappings(default, endpoint.Url, endpoint.Path);
|
||||
if (mappings is { Length: > 0 })
|
||||
{
|
||||
|
|
|
|||
62
FModel/Views/Snooper/Models/Collision.cs
Normal file
62
FModel/Views/Snooper/Models/Collision.cs
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
using System;
|
||||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
using CUE4Parse.UE4.Objects.PhysicsEngine;
|
||||
using FModel.Views.Snooper.Buffers;
|
||||
using FModel.Views.Snooper.Shading;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
|
||||
namespace FModel.Views.Snooper.Models;
|
||||
|
||||
public class Collision : IDisposable
|
||||
{
|
||||
private readonly int[] _indexData;
|
||||
private readonly FVector[] _vertexData;
|
||||
private readonly Transform _transform;
|
||||
|
||||
private int _handle;
|
||||
private BufferObject<int> _ebo { get; set; }
|
||||
private BufferObject<FVector> _vbo { get; set; }
|
||||
private VertexArrayObject<FVector, int> _vao { get; set; }
|
||||
|
||||
public Collision(FKConvexElem convexElems)
|
||||
{
|
||||
_indexData = convexElems.IndexData;
|
||||
_vertexData = convexElems.VertexData;
|
||||
_transform = new Transform
|
||||
{
|
||||
Position = convexElems.Transform.Translation * Constants.SCALE_DOWN_RATIO,
|
||||
Rotation = convexElems.Transform.Rotation,
|
||||
Scale = convexElems.Transform.Scale3D
|
||||
};
|
||||
}
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
_handle = GL.CreateProgram();
|
||||
_ebo = new BufferObject<int>(_indexData, BufferTarget.ElementArrayBuffer);
|
||||
_vbo = new BufferObject<FVector>(_vertexData, BufferTarget.ArrayBuffer);
|
||||
_vao = new VertexArrayObject<FVector, int>(_vbo, _ebo);
|
||||
|
||||
_vao.VertexAttributePointer(0, 3, VertexAttribPointerType.Float, 1, 0);
|
||||
_vao.Unbind();
|
||||
}
|
||||
|
||||
public void Render(Shader shader)
|
||||
{
|
||||
shader.SetUniform("uCollisionMatrix", _transform.Matrix);
|
||||
|
||||
_vao.Bind();
|
||||
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
|
||||
GL.DrawElements(PrimitiveType.Triangles, _ebo.Size, DrawElementsType.UnsignedInt, 0);
|
||||
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
|
||||
_vao.Unbind();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_ebo?.Dispose();
|
||||
_vbo?.Dispose();
|
||||
_vao?.Dispose();
|
||||
GL.DeleteProgram(_handle);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ using CUE4Parse_Conversion.Meshes.PSK;
|
|||
using CUE4Parse.UE4.Assets.Exports.Animation;
|
||||
using CUE4Parse.UE4.Assets.Exports.SkeletalMesh;
|
||||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
using CUE4Parse.UE4.Objects.PhysicsEngine;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using FModel.Views.Snooper.Animations;
|
||||
using FModel.Views.Snooper.Buffers;
|
||||
|
|
@ -44,6 +45,18 @@ public class SkeletalModel : UModel
|
|||
Sockets.Add(new Socket(socket));
|
||||
}
|
||||
|
||||
if (export.PhysicsAsset.TryLoad(out UPhysicsAsset physicsAsset))
|
||||
{
|
||||
foreach (var skeletalBodySetup in physicsAsset.SkeletalBodySetups)
|
||||
{
|
||||
if (!skeletalBodySetup.TryLoad(out USkeletalBodySetup bodySetup)) continue;
|
||||
foreach (var convexElem in bodySetup.AggGeom.ConvexElems)
|
||||
{
|
||||
Collisions.Add(new Collision(convexElem));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Morphs = new List<Morph>();
|
||||
for (var i = 0; i < export.MorphTargets.Length; i++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using CUE4Parse_Conversion.Meshes.PSK;
|
||||
using CUE4Parse.UE4.Assets.Exports.Material;
|
||||
using CUE4Parse.UE4.Assets.Exports.StaticMesh;
|
||||
using CUE4Parse.UE4.Objects.PhysicsEngine;
|
||||
using FModel.Views.Snooper.Shading;
|
||||
|
||||
namespace FModel.Views.Snooper.Models;
|
||||
|
|
@ -52,6 +53,14 @@ public class StaticModel : UModel
|
|||
public StaticModel(UStaticMesh export, CStaticMesh staticMesh, Transform transform = null)
|
||||
: base(export, staticMesh.LODs[LodLevel], export.Materials, staticMesh.LODs[LodLevel].Verts, staticMesh.LODs.Count, transform)
|
||||
{
|
||||
if (export.BodySetup.TryLoad(out UBodySetup bodySetup))
|
||||
{
|
||||
foreach (var convexElem in bodySetup.AggGeom.ConvexElems)
|
||||
{
|
||||
Collisions.Add(new Collision(convexElem));
|
||||
}
|
||||
}
|
||||
|
||||
Box = staticMesh.BoundingBox * Constants.SCALE_DOWN_RATIO;
|
||||
for (int i = 0; i < export.Sockets.Length; i++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ public abstract class UModel : IRenderableModel
|
|||
|
||||
public FBox Box;
|
||||
public readonly List<Socket> Sockets;
|
||||
public readonly List<Collision> Collisions;
|
||||
public Material[] Materials;
|
||||
public bool IsTwoSided;
|
||||
public bool IsProp;
|
||||
|
|
@ -67,12 +68,14 @@ public abstract class UModel : IRenderableModel
|
|||
public int VertexSize => _vertexAttributes.Where(x => x.Enabled).Sum(x => x.Size);
|
||||
public bool HasVertexColors => _vertexAttributes[(int) EAttribute.Colors].Enabled;
|
||||
public bool HasSockets => Sockets.Count > 0;
|
||||
public bool HasCollisions => Collisions.Count > 0;
|
||||
public int TransformsCount => Transforms.Count;
|
||||
|
||||
public bool IsSetup { get; set; }
|
||||
public bool IsVisible { get; set; }
|
||||
public bool IsSelected { get; set; }
|
||||
public bool ShowWireframe { get; set; }
|
||||
public bool ShowCollisions { get; set; }
|
||||
public int SelectedInstance;
|
||||
|
||||
protected UModel()
|
||||
|
|
@ -82,6 +85,7 @@ public abstract class UModel : IRenderableModel
|
|||
|
||||
Box = new FBox(new FVector(-2f), new FVector(2f));
|
||||
Sockets = new List<Socket>();
|
||||
Collisions = new List<Collision>();
|
||||
Transforms = new List<Transform>();
|
||||
}
|
||||
|
||||
|
|
@ -95,6 +99,7 @@ public abstract class UModel : IRenderableModel
|
|||
|
||||
Box = new FBox(new FVector(-2f), new FVector(2f));
|
||||
Sockets = new List<Socket>();
|
||||
Collisions = new List<Collision>();
|
||||
Transforms = new List<Transform>();
|
||||
Attachments = new Attachment(Name);
|
||||
|
||||
|
|
@ -209,6 +214,11 @@ public abstract class UModel : IRenderableModel
|
|||
Materials[i].Setup(options, broken ? 1 : UvCount);
|
||||
}
|
||||
|
||||
foreach (var collision in Collisions)
|
||||
{
|
||||
collision.Setup();
|
||||
}
|
||||
|
||||
if (options.Models.Count == 1 && Sections.All(x => !x.Show))
|
||||
{
|
||||
IsVisible = true;
|
||||
|
|
@ -294,6 +304,16 @@ public abstract class UModel : IRenderableModel
|
|||
if (IsTwoSided) GL.Enable(EnableCap.CullFace);
|
||||
}
|
||||
|
||||
public void RenderCollision(Shader shader)
|
||||
{
|
||||
shader.SetUniform("uInstanceMatrix", GetTransform().Matrix);
|
||||
shader.SetUniform("uScaleDown", Constants.SCALE_DOWN_RATIO);
|
||||
foreach (var collision in Collisions)
|
||||
{
|
||||
collision.Render(shader);
|
||||
}
|
||||
}
|
||||
|
||||
public void Update(Options options)
|
||||
{
|
||||
MatrixVbo.Bind();
|
||||
|
|
@ -381,6 +401,11 @@ public abstract class UModel : IRenderableModel
|
|||
socket?.Dispose();
|
||||
}
|
||||
Sockets.Clear();
|
||||
foreach (var collision in Collisions)
|
||||
{
|
||||
collision?.Dispose();
|
||||
}
|
||||
Collisions.Clear();
|
||||
|
||||
GL.DeleteProgram(Handle);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ public class Renderer : IDisposable
|
|||
private Shader _outline;
|
||||
private Shader _light;
|
||||
private Shader _bone;
|
||||
private Shader _collision;
|
||||
private bool _saveCameraMode;
|
||||
|
||||
public bool ShowSkybox;
|
||||
|
|
@ -227,6 +228,7 @@ public class Renderer : IDisposable
|
|||
_outline = new Shader("outline");
|
||||
_light = new Shader("light");
|
||||
_bone = new Shader("bone");
|
||||
_collision = new Shader("collision", "bone");
|
||||
|
||||
Picking.Setup();
|
||||
Options.SetupModelsAndLights();
|
||||
|
|
@ -272,6 +274,11 @@ public class Renderer : IDisposable
|
|||
_bone.Render(viewMatrix, projMatrix);
|
||||
skeletalModel.RenderBones(_bone);
|
||||
}
|
||||
else if (selected.ShowCollisions)
|
||||
{
|
||||
_collision.Render(viewMatrix, projMatrix);
|
||||
selected.RenderCollision(_collision);
|
||||
}
|
||||
|
||||
_outline.Render(viewMatrix, CameraOp.Position, projMatrix);
|
||||
selected.Render(_outline, Color == VertexColor.TextureCoordinates ? Options.Icons["checker"] : null, true);
|
||||
|
|
@ -642,6 +649,7 @@ public class Renderer : IDisposable
|
|||
_outline?.Dispose();
|
||||
_light?.Dispose();
|
||||
_bone?.Dispose();
|
||||
_collision?.Dispose();
|
||||
Picking?.Dispose();
|
||||
Options?.Dispose();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@ public class Shader : IDisposable
|
|||
|
||||
public Shader() : this("default") {}
|
||||
|
||||
public Shader(string name)
|
||||
public Shader(string name1, string name2 = null)
|
||||
{
|
||||
_handle = GL.CreateProgram();
|
||||
|
||||
var v = LoadShader(ShaderType.VertexShader, $"{name}.vert");
|
||||
var f = LoadShader(ShaderType.FragmentShader, $"{name}.frag");
|
||||
var v = LoadShader(ShaderType.VertexShader, $"{name1}.vert");
|
||||
var f = LoadShader(ShaderType.FragmentShader, $"{name2 ?? name1}.frag");
|
||||
GL.AttachShader(_handle, v);
|
||||
GL.AttachShader(_handle, f);
|
||||
GL.LinkProgram(_handle);
|
||||
|
|
|
|||
|
|
@ -421,6 +421,7 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio
|
|||
s.Renderer.Options.SelectModel(guid);
|
||||
if (ImGui.MenuItem("Show", null, model.IsVisible)) model.IsVisible = !model.IsVisible;
|
||||
if (ImGui.MenuItem("Wireframe", null, model.ShowWireframe)) model.ShowWireframe = !model.ShowWireframe;
|
||||
if (ImGui.MenuItem("Collisions", null, model.ShowCollisions, model.HasCollisions)) model.ShowCollisions = !model.ShowCollisions;
|
||||
ImGui.Separator();
|
||||
if (ImGui.MenuItem("Save"))
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user