mirror of
https://github.com/4sval/FModel.git
synced 2026-07-27 22:08:16 -05:00
merged options and cache + imgui lights + roughness parameter
This commit is contained in:
parent
9926d0de7c
commit
fd7b1226b5
|
|
@ -42,8 +42,8 @@ struct Parameters
|
|||
Mask M;
|
||||
bool HasM;
|
||||
|
||||
float Roughness;
|
||||
float EmissiveMult;
|
||||
|
||||
float UVScale;
|
||||
};
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ struct Light {
|
|||
vec3 Position;
|
||||
float Intensity;
|
||||
|
||||
vec3 Direction;
|
||||
vec2 Direction;
|
||||
float ConeAngle;
|
||||
float Attenuation;
|
||||
|
||||
|
|
@ -114,10 +114,10 @@ float geomSmith(float roughness, float dp)
|
|||
return dp / denom;
|
||||
}
|
||||
|
||||
vec3 CalcPBRLight(int layer, vec3 normals)
|
||||
vec3 CalcCameraLight(int layer, vec3 normals)
|
||||
{
|
||||
vec3 specular_masks = SamplerToVector(uParameters.SpecularMasks[layer].Sampler).rgb;
|
||||
float roughness = max(0.0f, specular_masks.b);
|
||||
float roughness = max(0.0f, mix(specular_masks.r, specular_masks.b, uParameters.Roughness));
|
||||
|
||||
vec3 intensity = vec3(1.0f) * 1.0f;
|
||||
vec3 l = -uViewDir;
|
||||
|
|
@ -192,21 +192,21 @@ void main()
|
|||
|
||||
if (!bVertexColors[1])
|
||||
{
|
||||
result += CalcPBRLight(layer, normals);
|
||||
result += CalcCameraLight(layer, normals);
|
||||
|
||||
vec3 lights = vec3(uNumLights > 0 ? 0 : 1);
|
||||
for (int i = 0; i < uNumLights; i++)
|
||||
{
|
||||
float distanceToLight = length(uLights[i].Position - fPos);
|
||||
|
||||
float attenuation = 0.0;
|
||||
float distanceToLight = length(uLights[i].Position - fPos);
|
||||
|
||||
if (uLights[i].Type == 0)
|
||||
{
|
||||
attenuation = 1.0 / (1.0 + uLights[i].Linear * distanceToLight + uLights[i].Quadratic * pow(distanceToLight, 2));
|
||||
}
|
||||
else if (uLights[i].Type == 1)
|
||||
{
|
||||
float theta = dot(normalize(uLights[i].Position - fPos), normalize(-uLights[i].Direction));
|
||||
float theta = dot(normalize(uLights[i].Position - fPos), normalize(-vec3(uLights[i].Direction.x, -uLights[i].Attenuation, uLights[i].Direction.y)));
|
||||
if(theta > uLights[i].ConeAngle)
|
||||
{
|
||||
attenuation = 1.0 / (1.0 + uLights[i].Attenuation * pow(distanceToLight, 2));
|
||||
|
|
|
|||
|
|
@ -1,125 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using CUE4Parse_Conversion.Meshes;
|
||||
using CUE4Parse_Conversion.Textures;
|
||||
using CUE4Parse.UE4.Assets.Exports.StaticMesh;
|
||||
using CUE4Parse.UE4.Assets.Exports.Texture;
|
||||
using CUE4Parse.UE4.Objects.Core.Misc;
|
||||
using FModel.Settings;
|
||||
|
||||
namespace FModel.Views.Snooper;
|
||||
|
||||
public class Cache : IDisposable
|
||||
{
|
||||
public readonly Dictionary<FGuid, Model> Models;
|
||||
public readonly Dictionary<FGuid, Texture> Textures;
|
||||
public readonly List<Light> Lights;
|
||||
|
||||
public readonly Dictionary<string, Texture> Icons;
|
||||
|
||||
private ETexturePlatform _platform;
|
||||
private readonly FGame _game;
|
||||
|
||||
public Cache()
|
||||
{
|
||||
Models = new Dictionary<FGuid, Model>();
|
||||
Textures = new Dictionary<FGuid, Texture>();
|
||||
Lights = new List<Light>();
|
||||
|
||||
Icons = new Dictionary<string, Texture>
|
||||
{
|
||||
["material"] = new ("materialicon"),
|
||||
["noimage"] = new ("T_Placeholder_Item_Image"),
|
||||
["pointlight"] = new ("pointlight"),
|
||||
["spotlight"] = new ("spotlight"),
|
||||
};
|
||||
|
||||
_platform = UserSettings.Default.OverridedPlatform;
|
||||
_game = Services.ApplicationService.ApplicationView.CUE4Parse.Game;
|
||||
}
|
||||
|
||||
public bool TryGetCachedModel(UStaticMesh o, out Model model)
|
||||
{
|
||||
var guid = o.LightingGuid;
|
||||
if (!Models.TryGetValue(guid, out model) && o.TryConvert(out var mesh))
|
||||
{
|
||||
model = new Model(o.Name, o.ExportType, o.Materials, mesh);
|
||||
Models[guid] = model;
|
||||
}
|
||||
return model != null;
|
||||
}
|
||||
|
||||
public bool TryGetCachedTexture(UTexture2D o, bool fix, out Texture texture)
|
||||
{
|
||||
var guid = o.LightingGuid;
|
||||
if (!Textures.TryGetValue(guid, out texture) && o.GetFirstMip() is { } mip)
|
||||
{
|
||||
TextureDecoder.DecodeTexture(mip, o.Format, o.isNormalMap, _platform, out var data, out _);
|
||||
// if (fix) FixChannels(o, mip, ref data);
|
||||
|
||||
texture = new Texture(data, mip.SizeX, mip.SizeY, o);
|
||||
Textures[guid] = texture;
|
||||
}
|
||||
return texture != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Red : Specular
|
||||
/// Blue : Roughness
|
||||
/// Green : Metallic
|
||||
/// </summary>
|
||||
private void FixChannels(UTexture2D o, FTexture2DMipMap mip, ref byte[] data)
|
||||
{
|
||||
// only if it makes a big difference pls
|
||||
}
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
foreach (var model in Models.Values)
|
||||
{
|
||||
if (model.IsSetup) continue;
|
||||
model.Setup(this);
|
||||
}
|
||||
|
||||
foreach (var light in Lights)
|
||||
{
|
||||
light.Setup();
|
||||
}
|
||||
}
|
||||
|
||||
public void DisposeModels()
|
||||
{
|
||||
foreach (var model in Models.Values)
|
||||
{
|
||||
model.Dispose();
|
||||
}
|
||||
}
|
||||
public void DisposeTextures()
|
||||
{
|
||||
foreach (var texture in Textures.Values)
|
||||
{
|
||||
texture.Dispose();
|
||||
}
|
||||
|
||||
foreach (var texture in Icons.Values)
|
||||
{
|
||||
texture.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
DisposeModels();
|
||||
Models.Clear();
|
||||
Lights.Clear();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Reset();
|
||||
|
||||
DisposeTextures();
|
||||
Textures.Clear();
|
||||
Icons.Clear();
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@ using System;
|
|||
using System.Numerics;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
using CUE4Parse.UE4.Objects.Core.Misc;
|
||||
using ImGuiNET;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
|
||||
namespace FModel.Views.Snooper;
|
||||
|
|
@ -24,13 +26,15 @@ public abstract class Light : IDisposable
|
|||
1f, 1f, 0f,
|
||||
1f, -1f, 0
|
||||
};
|
||||
public Texture Icon;
|
||||
public readonly FGuid Model;
|
||||
public readonly Texture Icon;
|
||||
public readonly Transform Transform;
|
||||
|
||||
public readonly Vector4 Color;
|
||||
public readonly float Intensity;
|
||||
public Vector4 Color;
|
||||
public float Intensity;
|
||||
public bool IsSetup;
|
||||
|
||||
public Light(Texture icon, UObject parent, UObject light, FVector position)
|
||||
public Light(FGuid model, Texture icon, UObject parent, UObject light, FVector position)
|
||||
{
|
||||
var p = light.GetOrDefault("RelativeLocation", parent.GetOrDefault("RelativeLocation", FVector.ZeroVector));
|
||||
var r = light.GetOrDefault("RelativeRotation", parent.GetOrDefault("RelativeRotation", FRotator.ZeroRotator));
|
||||
|
|
@ -39,6 +43,7 @@ public abstract class Light : IDisposable
|
|||
Transform.Scale = new FVector(0.25f);
|
||||
Transform.Position = position + r.RotateVector(p.ToMapVector()) * Constants.SCALE_DOWN_RATIO;
|
||||
|
||||
Model = model;
|
||||
Icon = icon;
|
||||
|
||||
Color = light.GetOrDefault("LightColor", parent.GetOrDefault("LightColor", new FColor(0xFF, 0xFF, 0xFF, 0xFF)));
|
||||
|
|
@ -62,13 +67,12 @@ public abstract class Light : IDisposable
|
|||
|
||||
_vao.VertexAttributePointer(0, 3, VertexAttribPointerType.Float, 3, 0); // position
|
||||
SetupInstances();
|
||||
}
|
||||
|
||||
public abstract void Render(int i, Shader shader);
|
||||
IsSetup = true;
|
||||
}
|
||||
|
||||
public void Render(Shader shader)
|
||||
{
|
||||
// GL.Disable(EnableCap.DepthTest);
|
||||
_vao.Bind();
|
||||
|
||||
Icon?.Bind(TextureUnit.Texture0);
|
||||
|
|
@ -76,7 +80,21 @@ public abstract class Light : IDisposable
|
|||
shader.SetUniform("uColor", Color);
|
||||
|
||||
GL.DrawArrays(PrimitiveType.Triangles, 0, Indices.Length);
|
||||
// GL.Enable(EnableCap.DepthTest);
|
||||
}
|
||||
|
||||
public virtual void Render(int i, Shader shader)
|
||||
{
|
||||
shader.SetUniform($"uLights[{i}].Color", Color);
|
||||
shader.SetUniform($"uLights[{i}].Position", Transform.Position);
|
||||
shader.SetUniform($"uLights[{i}].Intensity", Intensity);
|
||||
}
|
||||
|
||||
public virtual void ImGuiLight()
|
||||
{
|
||||
SnimGui.Layout("Color");ImGui.PushID(1);
|
||||
ImGui.ColorEdit4("", ref Color, ImGuiColorEditFlags.NoAlpha);
|
||||
ImGui.PopID();SnimGui.Layout("Intensity");ImGui.PushID(2);
|
||||
ImGui.DragFloat("", ref Intensity, 0.1f);ImGui.PopID();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ public class Material : IDisposable
|
|||
public Mask M;
|
||||
public bool HasM;
|
||||
|
||||
public float Roughness = 0.5f;
|
||||
public float EmissiveMult = 1f;
|
||||
public float UVScale = 1f;
|
||||
|
||||
|
|
@ -60,7 +61,7 @@ public class Material : IDisposable
|
|||
unrealMaterial.GetParams(Parameters);
|
||||
}
|
||||
|
||||
public void Setup(Cache cache, int numTexCoords)
|
||||
public void Setup(Options options, int numTexCoords)
|
||||
{
|
||||
_handle = GL.CreateProgram();
|
||||
|
||||
|
|
@ -76,10 +77,10 @@ public class Material : IDisposable
|
|||
else
|
||||
{
|
||||
{ // textures
|
||||
Diffuse = FillTextures(cache, numTexCoords, Parameters.HasTopDiffuse, CMaterialParams2.Diffuse, CMaterialParams2.FallbackDiffuse, true);
|
||||
Normals = FillTextures(cache, numTexCoords, Parameters.HasTopNormals, CMaterialParams2.Normals, CMaterialParams2.FallbackNormals);
|
||||
SpecularMasks = FillTextures(cache, numTexCoords, Parameters.HasTopSpecularMasks, CMaterialParams2.SpecularMasks, CMaterialParams2.FallbackSpecularMasks);
|
||||
Emissive = FillTextures(cache, numTexCoords, true, CMaterialParams2.Emissive, CMaterialParams2.FallbackEmissive);
|
||||
Diffuse = FillTextures(options, numTexCoords, Parameters.HasTopDiffuse, CMaterialParams2.Diffuse, CMaterialParams2.FallbackDiffuse, true);
|
||||
Normals = FillTextures(options, numTexCoords, Parameters.HasTopNormals, CMaterialParams2.Normals, CMaterialParams2.FallbackNormals);
|
||||
SpecularMasks = FillTextures(options, numTexCoords, Parameters.HasTopSpecularMasks, CMaterialParams2.SpecularMasks, CMaterialParams2.FallbackSpecularMasks);
|
||||
Emissive = FillTextures(options, numTexCoords, true, CMaterialParams2.Emissive, CMaterialParams2.FallbackEmissive);
|
||||
}
|
||||
|
||||
{ // colors
|
||||
|
|
@ -88,7 +89,7 @@ public class Material : IDisposable
|
|||
}
|
||||
|
||||
{ // scalars
|
||||
if (Parameters.TryGetTexture2d(out var original, "M", "AEM") && cache.TryGetCachedTexture(original, false, out var transformed))
|
||||
if (Parameters.TryGetTexture2d(out var original, "M", "AEM") && options.TryGetTexture(original, false, out var transformed))
|
||||
{
|
||||
M = new Mask { Texture = transformed, AmbientOcclusion = 0.7f };
|
||||
HasM = true;
|
||||
|
|
@ -96,6 +97,12 @@ public class Material : IDisposable
|
|||
M.SkinBoost = new Boost { Color = new Vector3(l.R, l.G, l.B), Exponent = l.A };
|
||||
}
|
||||
|
||||
if (Parameters.TryGetScalar(out var roughnessMin, "RoughnessMin", "SpecRoughnessMin") &&
|
||||
Parameters.TryGetScalar(out var roughnessMax, "RoughnessMax", "SpecRoughnessMax"))
|
||||
Roughness = (roughnessMin + roughnessMax) / 2f;
|
||||
if (Parameters.TryGetScalar(out var roughness, "Rough", "Roughness"))
|
||||
Roughness = roughness;
|
||||
|
||||
if (Parameters.TryGetScalar(out var emissiveMult, "emissive mult", "Emissive_Mult"))
|
||||
EmissiveMult = emissiveMult;
|
||||
|
||||
|
|
@ -105,13 +112,13 @@ public class Material : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
/// <param name="cache">just the cache object</param>
|
||||
/// <param name="options">just the cache object</param>
|
||||
/// <param name="numTexCoords">number of item in the array</param>
|
||||
/// <param name="top">has at least 1 clearly defined texture, else will go straight to fallback</param>
|
||||
/// <param name="triggers">list of texture parameter names by uv channel</param>
|
||||
/// <param name="fallback">fallback texture name to use if no top texture found</param>
|
||||
/// <param name="first">if no top texture, no fallback texture, then use the first texture found</param>
|
||||
private Texture[] FillTextures(Cache cache, int numTexCoords, bool top, IReadOnlyList<string[]> triggers, string fallback, bool first = false)
|
||||
private Texture[] FillTextures(Options options, int numTexCoords, bool top, IReadOnlyList<string[]> triggers, string fallback, bool first = false)
|
||||
{
|
||||
UTexture2D original;
|
||||
Texture transformed;
|
||||
|
|
@ -122,18 +129,18 @@ public class Material : IDisposable
|
|||
{
|
||||
for (int i = 0; i < textures.Length; i++)
|
||||
{
|
||||
if (Parameters.TryGetTexture2d(out original, triggers[i]) && cache.TryGetCachedTexture(original, fix, out transformed))
|
||||
if (Parameters.TryGetTexture2d(out original, triggers[i]) && options.TryGetTexture(original, fix, out transformed))
|
||||
textures[i] = transformed;
|
||||
else if (i > 0 && textures[i - 1] != null)
|
||||
textures[i] = textures[i - 1];
|
||||
}
|
||||
}
|
||||
else if (Parameters.TryGetTexture2d(out original, fallback) && cache.TryGetCachedTexture(original, fix, out transformed))
|
||||
else if (Parameters.TryGetTexture2d(out original, fallback) && options.TryGetTexture(original, fix, out transformed))
|
||||
{
|
||||
for (int i = 0; i < textures.Length; i++)
|
||||
textures[i] = transformed;
|
||||
}
|
||||
else if (first && Parameters.TryGetFirstTexture2d(out original) && cache.TryGetCachedTexture(original, fix, out transformed))
|
||||
else if (first && Parameters.TryGetFirstTexture2d(out original) && options.TryGetTexture(original, fix, out transformed))
|
||||
{
|
||||
for (int i = 0; i < textures.Length; i++)
|
||||
textures[i] = transformed;
|
||||
|
|
@ -198,8 +205,8 @@ public class Material : IDisposable
|
|||
shader.SetUniform("uParameters.M.Cavity", M.Cavity);
|
||||
shader.SetUniform("uParameters.HasM", HasM);
|
||||
|
||||
shader.SetUniform("uParameters.Roughness", Roughness);
|
||||
shader.SetUniform("uParameters.EmissiveMult", EmissiveMult);
|
||||
|
||||
shader.SetUniform("uParameters.UVScale", UVScale);
|
||||
}
|
||||
|
||||
|
|
@ -219,21 +226,23 @@ public class Material : IDisposable
|
|||
PushStyle();
|
||||
if (ImGui.BeginTable("parameters", 2))
|
||||
{
|
||||
SnimGui.Layout("Emissive Multiplier");ImGui.PushID(1);
|
||||
SnimGui.Layout("Roughness");ImGui.PushID(1);
|
||||
ImGui.DragFloat("", ref Roughness, _step, _zero, 1.0f, _mult, _clamp);
|
||||
SnimGui.Layout("Emissive Multiplier");ImGui.PushID(2);
|
||||
ImGui.DragFloat("", ref EmissiveMult, _step, _zero, _infinite, _mult, _clamp);
|
||||
ImGui.PopID();SnimGui.Layout("UV Scale");ImGui.PushID(2);
|
||||
ImGui.PopID();SnimGui.Layout("UV Scale");ImGui.PushID(3);
|
||||
ImGui.DragFloat("", ref UVScale, _step, _zero, _infinite, _mult, _clamp);
|
||||
ImGui.PopID();
|
||||
|
||||
if (HasM)
|
||||
{
|
||||
SnimGui.Layout("Ambient Occlusion");ImGui.PushID(3);
|
||||
SnimGui.Layout("Ambient Occlusion");ImGui.PushID(4);
|
||||
ImGui.DragFloat("", ref M.AmbientOcclusion, _step, _zero, 1.0f, _mult, _clamp);
|
||||
ImGui.PopID();SnimGui.Layout("Cavity");ImGui.PushID(4);
|
||||
ImGui.PopID();SnimGui.Layout("Cavity");ImGui.PushID(5);
|
||||
ImGui.DragFloat("", ref M.Cavity, _step, _zero, 1.0f, _mult, _clamp);
|
||||
ImGui.PopID();SnimGui.Layout("Skin Boost Exponent");ImGui.PushID(5);
|
||||
ImGui.PopID();SnimGui.Layout("Skin Boost Exponent");ImGui.PushID(6);
|
||||
ImGui.DragFloat("", ref M.SkinBoost.Exponent, _step, _zero, _infinite, _mult, _clamp);
|
||||
ImGui.PopID();SnimGui.Layout("Skin Boost Color");ImGui.PushID(6);
|
||||
ImGui.PopID();SnimGui.Layout("Skin Boost Color");ImGui.PushID(7);
|
||||
ImGui.ColorEdit3("", ref M.SkinBoost.Color);
|
||||
ImGui.PopID();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ public class Model : IDisposable
|
|||
_vao.BindInstancing(); // VertexAttributePointer
|
||||
}
|
||||
|
||||
public void Setup(Cache cache)
|
||||
public void Setup(Options options)
|
||||
{
|
||||
_handle = GL.CreateProgram();
|
||||
|
||||
|
|
@ -216,7 +216,7 @@ public class Model : IDisposable
|
|||
for (var i = 0; i < Materials.Length; i++)
|
||||
{
|
||||
if (!Materials[i].IsUsed) continue;
|
||||
Materials[i].Setup(cache, NumTexCoords);
|
||||
Materials[i].Setup(options, NumTexCoords);
|
||||
}
|
||||
|
||||
if (HasMorphTargets)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using CUE4Parse_Conversion.Textures;
|
||||
using CUE4Parse.UE4.Assets.Exports.Texture;
|
||||
using CUE4Parse.UE4.Objects.Core.Misc;
|
||||
using FModel.Settings;
|
||||
|
||||
namespace FModel.Views.Snooper;
|
||||
|
||||
|
|
@ -9,21 +13,65 @@ public class Options
|
|||
public int SelectedSection { get; private set; }
|
||||
public int SelectedMorph { get; private set; }
|
||||
|
||||
public readonly Dictionary<FGuid, Model> Models;
|
||||
public readonly Dictionary<FGuid, Texture> Textures;
|
||||
public readonly List<Light> Lights;
|
||||
|
||||
public readonly Dictionary<string, Texture> Icons;
|
||||
|
||||
private ETexturePlatform _platform;
|
||||
private readonly FGame _game;
|
||||
|
||||
public Options()
|
||||
{
|
||||
Reset();
|
||||
Models = new Dictionary<FGuid, Model>();
|
||||
Textures = new Dictionary<FGuid, Texture>();
|
||||
Lights = new List<Light>();
|
||||
|
||||
Icons = new Dictionary<string, Texture>
|
||||
{
|
||||
["material"] = new ("materialicon"),
|
||||
["noimage"] = new ("T_Placeholder_Item_Image"),
|
||||
["pointlight"] = new ("pointlight"),
|
||||
["spotlight"] = new ("spotlight"),
|
||||
};
|
||||
|
||||
_platform = UserSettings.Default.OverridedPlatform;
|
||||
_game = Services.ApplicationService.ApplicationView.CUE4Parse.Game;
|
||||
|
||||
SelectModel(Guid.Empty);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
public void SetupModelsAndLights()
|
||||
{
|
||||
SelectedModel = Guid.Empty;
|
||||
SelectedSection = 0;
|
||||
SelectedMorph = 0;
|
||||
foreach (var model in Models.Values)
|
||||
{
|
||||
if (model.IsSetup) continue;
|
||||
model.Setup(this);
|
||||
}
|
||||
|
||||
foreach (var light in Lights)
|
||||
{
|
||||
if (light.IsSetup) continue;
|
||||
light.Setup();
|
||||
}
|
||||
}
|
||||
|
||||
public void SelectModel(FGuid guid)
|
||||
{
|
||||
SelectedModel = guid;
|
||||
// unselect old
|
||||
if (TryGetModel(out var model))
|
||||
model.IsSelected = false;
|
||||
|
||||
// select new
|
||||
if (!TryGetModel(guid, out model))
|
||||
SelectedModel = Guid.Empty;
|
||||
else
|
||||
{
|
||||
model.IsSelected = true;
|
||||
SelectedModel = guid;
|
||||
}
|
||||
|
||||
SelectedSection = 0;
|
||||
SelectedMorph = 0;
|
||||
}
|
||||
|
|
@ -39,6 +87,44 @@ public class Options
|
|||
model.UpdateMorph(SelectedMorph);
|
||||
}
|
||||
|
||||
public bool TryGetTexture(UTexture2D o, bool fix, out Texture texture)
|
||||
{
|
||||
var guid = o.LightingGuid;
|
||||
if (!Textures.TryGetValue(guid, out texture) && o.GetFirstMip() is { } mip)
|
||||
{
|
||||
TextureDecoder.DecodeTexture(mip, o.Format, o.isNormalMap, _platform, out var data, out _);
|
||||
// if (fix) FixChannels(o, mip, ref data);
|
||||
|
||||
texture = new Texture(data, mip.SizeX, mip.SizeY, o);
|
||||
Textures[guid] = texture;
|
||||
}
|
||||
return texture != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Red : Specular
|
||||
/// Blue : Roughness
|
||||
/// Green : Metallic
|
||||
/// </summary>
|
||||
private void FixChannels(UTexture2D o, FTexture2DMipMap mip, ref byte[] data)
|
||||
{
|
||||
// only if it makes a big difference pls
|
||||
}
|
||||
|
||||
public bool TryGetModel(out Model model) => Models.TryGetValue(SelectedModel, out model);
|
||||
public bool TryGetModel(FGuid guid, out Model model) => Models.TryGetValue(guid, out model);
|
||||
|
||||
public bool TryGetSection(out Section section) => TryGetSection(SelectedModel, out section);
|
||||
public bool TryGetSection(FGuid guid, out Section section)
|
||||
{
|
||||
if (TryGetModel(guid, out var model))
|
||||
{
|
||||
return TryGetSection(model, out section);
|
||||
}
|
||||
|
||||
section = null;
|
||||
return false;
|
||||
}
|
||||
public bool TryGetSection(Model model, out Section section)
|
||||
{
|
||||
if (SelectedSection >= 0 && SelectedSection < model.Sections.Length)
|
||||
|
|
@ -55,4 +141,29 @@ public class Options
|
|||
{
|
||||
Services.ApplicationService.ApplicationView.CUE4Parse.ModelIsWaitingAnimation = value;
|
||||
}
|
||||
|
||||
public void ResetModelsAndLights()
|
||||
{
|
||||
foreach (var model in Models.Values)
|
||||
{
|
||||
model.Dispose();
|
||||
}
|
||||
Models.Clear();
|
||||
Lights.Clear();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ResetModelsAndLights();
|
||||
foreach (var texture in Textures.Values)
|
||||
{
|
||||
texture.Dispose();
|
||||
}
|
||||
Textures.Clear();
|
||||
foreach (var texture in Icons.Values)
|
||||
{
|
||||
texture.Dispose();
|
||||
}
|
||||
Icons.Clear();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
using System;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
using CUE4Parse.UE4.Objects.Core.Misc;
|
||||
using ImGuiNET;
|
||||
|
||||
namespace FModel.Views.Snooper;
|
||||
|
||||
public class PointLight : Light
|
||||
{
|
||||
public readonly float Linear;
|
||||
public readonly float Quadratic;
|
||||
public float Linear;
|
||||
public float Quadratic;
|
||||
|
||||
public PointLight(Texture icon, UObject parent, UObject point, FVector position) : base(icon, parent, point, position)
|
||||
public PointLight(FGuid model, Texture icon, UObject parent, UObject point, FVector position) : base(model, icon, parent, point, position)
|
||||
{
|
||||
if (!point.TryGetValue(out float radius, "AttenuationRadius", "SourceRadius"))
|
||||
radius = 1.0f;
|
||||
|
|
@ -21,12 +23,19 @@ public class PointLight : Light
|
|||
|
||||
public override void Render(int i, Shader shader)
|
||||
{
|
||||
shader.SetUniform($"uLights[{i}].Color", Color);
|
||||
shader.SetUniform($"uLights[{i}].Position", Transform.Position);
|
||||
shader.SetUniform($"uLights[{i}].Intensity", Intensity);
|
||||
base.Render(i, shader);
|
||||
shader.SetUniform($"uLights[{i}].Linear", Linear);
|
||||
shader.SetUniform($"uLights[{i}].Quadratic", Quadratic);
|
||||
|
||||
shader.SetUniform($"uLights[{i}].Type", 0);
|
||||
}
|
||||
|
||||
public override void ImGuiLight()
|
||||
{
|
||||
base.ImGuiLight();
|
||||
SnimGui.Layout("Linear");ImGui.PushID(3);
|
||||
ImGui.DragFloat("", ref Linear, 0.1f);
|
||||
ImGui.PopID();SnimGui.Layout("Quadratic");ImGui.PushID(4);
|
||||
ImGui.DragFloat("", ref Quadratic, 0.1f);ImGui.PopID();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,8 +31,7 @@ public class Renderer : IDisposable
|
|||
public int VertexColor;
|
||||
|
||||
public PickingTexture Picking { get; }
|
||||
public Cache Cache { get; }
|
||||
public Options Settings { get; }
|
||||
public Options Options { get; }
|
||||
|
||||
public Renderer(int width, int height)
|
||||
{
|
||||
|
|
@ -40,8 +39,7 @@ public class Renderer : IDisposable
|
|||
_grid = new Grid();
|
||||
|
||||
Picking = new PickingTexture(width, height);
|
||||
Cache = new Cache();
|
||||
Settings = new Options();
|
||||
Options = new Options();
|
||||
|
||||
ShowSkybox = UserSettings.Default.ShowSkybox;
|
||||
ShowGrid = UserSettings.Default.ShowGrid;
|
||||
|
|
@ -63,22 +61,21 @@ public class Renderer : IDisposable
|
|||
|
||||
public void Swap(UMaterialInstance unrealMaterial)
|
||||
{
|
||||
if (!Cache.Models.TryGetValue(Settings.SelectedModel, out var model) ||
|
||||
!Settings.TryGetSection(model, out var section)) return;
|
||||
if (!Options.TryGetModel(out var model) || !Options.TryGetSection(model, out var section)) return;
|
||||
|
||||
model.Materials[section.MaterialIndex].SwapMaterial(unrealMaterial);
|
||||
Application.Current.Dispatcher.Invoke(() => model.Materials[section.MaterialIndex].Setup(Cache, model.NumTexCoords));
|
||||
Settings.SwapMaterial(false);
|
||||
Application.Current.Dispatcher.Invoke(() => model.Materials[section.MaterialIndex].Setup(Options, model.NumTexCoords));
|
||||
Options.SwapMaterial(false);
|
||||
}
|
||||
|
||||
public void Animate(UAnimSequence animSequence)
|
||||
{
|
||||
if (!Cache.Models.TryGetValue(Settings.SelectedModel, out var model) || !model.Skeleton.IsLoaded ||
|
||||
if (!Options.TryGetModel(out var model) || !model.Skeleton.IsLoaded ||
|
||||
model.Skeleton?.RefSkel.ConvertAnims(animSequence) is not { } anim || anim.Sequences.Count == 0)
|
||||
return;
|
||||
|
||||
model.Skeleton.Anim = new Animation(anim);
|
||||
Settings.AnimateMesh(false);
|
||||
Options.AnimateMesh(false);
|
||||
}
|
||||
|
||||
public void Setup()
|
||||
|
|
@ -91,7 +88,7 @@ public class Renderer : IDisposable
|
|||
_light = new Shader("light");
|
||||
|
||||
Picking.Setup();
|
||||
Cache.Setup();
|
||||
Options.SetupModelsAndLights();
|
||||
}
|
||||
|
||||
public void Render(Camera cam)
|
||||
|
|
@ -107,34 +104,34 @@ public class Renderer : IDisposable
|
|||
_shader.SetUniform($"bVertexColors[{i}]", i == VertexColor);
|
||||
|
||||
// render model pass
|
||||
foreach (var model in Cache.Models.Values)
|
||||
foreach (var model in Options.Models.Values)
|
||||
{
|
||||
if (!model.Show) continue;
|
||||
model.Render(_shader);
|
||||
}
|
||||
|
||||
{ // light pass
|
||||
var uNumLights = Cache.Lights.Count;
|
||||
var uNumLights = Math.Min(Options.Lights.Count, 100);
|
||||
_shader.SetUniform("uNumLights", ShowLights ? uNumLights : 0);
|
||||
|
||||
if (ShowLights)
|
||||
for (int i = 0; i < uNumLights; i++)
|
||||
Cache.Lights[i].Render(i, _shader);
|
||||
Options.Lights[i].Render(i, _shader);
|
||||
|
||||
_light.Render(viewMatrix, projMatrix);
|
||||
for (int i = 0; i < uNumLights; i++)
|
||||
Cache.Lights[i].Render(_light);
|
||||
Options.Lights[i].Render(_light);
|
||||
}
|
||||
|
||||
// outline pass
|
||||
if (Cache.Models.TryGetValue(Settings.SelectedModel, out var selected) && selected.Show)
|
||||
if (Options.TryGetModel(out var selected) && selected.Show)
|
||||
{
|
||||
_outline.Render(viewMatrix, cam.Position, projMatrix);
|
||||
selected.Outline(_outline);
|
||||
}
|
||||
|
||||
// picking pass (dedicated FBO, binding to 0 afterward)
|
||||
Picking.Render(viewMatrix, projMatrix, Cache.Models);
|
||||
Picking.Render(viewMatrix, projMatrix, Options.Models);
|
||||
}
|
||||
|
||||
private Camera SetupCamera(FBox box)
|
||||
|
|
@ -150,7 +147,7 @@ public class Renderer : IDisposable
|
|||
private Camera LoadStaticMesh(UStaticMesh original)
|
||||
{
|
||||
var guid = original.LightingGuid;
|
||||
if (Cache.Models.TryGetValue(guid, out var model))
|
||||
if (Options.TryGetModel(guid, out var model))
|
||||
{
|
||||
model.AddInstance(Transform.Identity);
|
||||
Application.Current.Dispatcher.Invoke(() => model.SetupInstances());
|
||||
|
|
@ -160,28 +157,28 @@ public class Renderer : IDisposable
|
|||
if (!original.TryConvert(out var mesh))
|
||||
return null;
|
||||
|
||||
Cache.Models[guid] = new Model(original.Name, original.ExportType, original.Materials, mesh);
|
||||
Settings.SelectModel(guid);
|
||||
Options.Models[guid] = new Model(original.Name, original.ExportType, original.Materials, mesh);
|
||||
Options.SelectModel(guid);
|
||||
return SetupCamera(mesh.BoundingBox *= Constants.SCALE_DOWN_RATIO);
|
||||
}
|
||||
|
||||
private Camera LoadSkeletalMesh(USkeletalMesh original)
|
||||
{
|
||||
var guid = Guid.NewGuid();
|
||||
if (Cache.Models.ContainsKey(guid) || !original.TryConvert(out var mesh)) return null;
|
||||
if (Options.Models.ContainsKey(guid) || !original.TryConvert(out var mesh)) return null;
|
||||
|
||||
Cache.Models[guid] = new Model(original.Name, original.ExportType, original.Materials, original.Skeleton, original.MorphTargets, mesh);
|
||||
Settings.SelectModel(guid);
|
||||
Options.Models[guid] = new Model(original.Name, original.ExportType, original.Materials, original.Skeleton, original.MorphTargets, mesh);
|
||||
Options.SelectModel(guid);
|
||||
return SetupCamera(mesh.BoundingBox *= Constants.SCALE_DOWN_RATIO);
|
||||
}
|
||||
|
||||
private Camera LoadMaterialInstance(UMaterialInstance original)
|
||||
{
|
||||
var guid = Guid.NewGuid();
|
||||
if (Cache.Models.ContainsKey(guid)) return null;
|
||||
if (Options.Models.ContainsKey(guid)) return null;
|
||||
|
||||
Cache.Models[guid] = new Cube(original);
|
||||
Settings.SelectModel(guid);
|
||||
Options.Models[guid] = new Cube(original);
|
||||
Options.SelectModel(guid);
|
||||
return SetupCamera(new FBox(new FVector(-.65f), new FVector(.65f)));
|
||||
}
|
||||
|
||||
|
|
@ -254,7 +251,7 @@ public class Renderer : IDisposable
|
|||
Scale = staticMeshComp.GetOrDefault("RelativeScale3D", FVector.OneVector).ToMapVector()
|
||||
};
|
||||
|
||||
if (Cache.Models.TryGetValue(guid, out var model))
|
||||
if (Options.TryGetModel(guid, out var model))
|
||||
{
|
||||
model.AddInstance(t);
|
||||
}
|
||||
|
|
@ -295,18 +292,18 @@ public class Renderer : IDisposable
|
|||
model.Materials[model.Sections[j].MaterialIndex].SwapMaterial(unrealMaterial);
|
||||
}
|
||||
}
|
||||
Cache.Models[guid] = model;
|
||||
Options.Models[guid] = model;
|
||||
}
|
||||
|
||||
if (actor.TryGetValue(out FPackageIndex treasureLight, "TreasureLight", "PointLight") &&
|
||||
treasureLight.TryLoad(out var tl1) && tl1.Template.TryLoad(out var tl2))
|
||||
if (actor.TryGetValue(out FPackageIndex treasureLight, "PointLight", "TreasureLight") &&
|
||||
treasureLight.TryLoad(out var pl1) && pl1.Template.TryLoad(out var pl2))
|
||||
{
|
||||
Cache.Lights.Add(new PointLight(Cache.Icons["pointlight"], tl1, tl2, t.Position));
|
||||
Options.Lights.Add(new PointLight(guid, Options.Icons["pointlight"], pl1, pl2, t.Position));
|
||||
}
|
||||
if (actor.TryGetValue(out FPackageIndex spotLight, "SpotLight") &&
|
||||
spotLight.TryLoad(out var sl1) && sl1.Template.TryLoad(out var sl2))
|
||||
{
|
||||
Cache.Lights.Add(new SpotLight(Cache.Icons["spotlight"], sl1, sl2, t.Position));
|
||||
Options.Lights.Add(new SpotLight(guid, Options.Icons["spotlight"], sl1, sl2, t.Position));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -344,6 +341,6 @@ public class Renderer : IDisposable
|
|||
_outline?.Dispose();
|
||||
_light?.Dispose();
|
||||
Picking?.Dispose();
|
||||
Cache?.Dispose();
|
||||
Options?.Dispose();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,6 +96,12 @@ public class Shader : IDisposable
|
|||
GL.Uniform1(GetUniformLocation(name), value);
|
||||
}
|
||||
|
||||
public void SetUniform(string name, Vector2 value) => SetUniform3(name, value.X, value.Y);
|
||||
public void SetUniform3(string name, float x, float y)
|
||||
{
|
||||
GL.Uniform2(GetUniformLocation(name), x, y);
|
||||
}
|
||||
|
||||
public void SetUniform(string name, Vector3 value) => SetUniform3(name, value.X, value.Y, value.Z);
|
||||
public void SetUniform3(string name, float x, float y, float z)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -82,7 +82,17 @@ public class SnimGui
|
|||
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
|
||||
if (ImGui.CollapsingHeader("Lights"))
|
||||
{
|
||||
|
||||
for (int i = 0; i < s.Renderer.Options.Lights.Count; i++)
|
||||
{
|
||||
var id = $"[{i}] {s.Renderer.Options.Models[s.Renderer.Options.Lights[i].Model].Name}";
|
||||
if (ImGui.TreeNode(id) && ImGui.BeginTable(id, 2))
|
||||
{
|
||||
s.Renderer.Options.SelectModel(s.Renderer.Options.Lights[i].Model);
|
||||
s.Renderer.Options.Lights[i].ImGuiLight();
|
||||
ImGui.EndTable();
|
||||
ImGui.TreePop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -143,7 +153,7 @@ public class SnimGui
|
|||
ImGui.TableHeadersRow();
|
||||
|
||||
var i = 0;
|
||||
foreach ((FGuid guid, Model model) in s.Renderer.Cache.Models)
|
||||
foreach ((FGuid guid, Model model) in s.Renderer.Options.Models)
|
||||
{
|
||||
ImGui.PushID(i);
|
||||
ImGui.TableNextRow();
|
||||
|
|
@ -157,14 +167,13 @@ public class SnimGui
|
|||
ImGui.TableNextColumn();
|
||||
ImGui.Text(model.NumTexCoords.ToString("D"));
|
||||
ImGui.TableNextColumn();
|
||||
model.IsSelected = s.Renderer.Settings.SelectedModel == guid;
|
||||
if (ImGui.Selectable(model.Name, model.IsSelected, ImGuiSelectableFlags.SpanAllColumns))
|
||||
if (ImGui.Selectable(model.Name, s.Renderer.Options.SelectedModel == guid, ImGuiSelectableFlags.SpanAllColumns))
|
||||
{
|
||||
s.Renderer.Settings.SelectModel(guid);
|
||||
s.Renderer.Options.SelectModel(guid);
|
||||
}
|
||||
if (ImGui.BeginPopupContextItem())
|
||||
{
|
||||
s.Renderer.Settings.SelectModel(guid);
|
||||
s.Renderer.Options.SelectModel(guid);
|
||||
if (ImGui.MenuItem("Show", null, model.Show)) model.Show = !model.Show;
|
||||
if (ImGui.MenuItem("Wireframe", null, model.Wireframe)) model.Wireframe = !model.Wireframe;
|
||||
ImGui.Separator();
|
||||
|
|
@ -175,12 +184,12 @@ public class SnimGui
|
|||
ImGui.BeginDisabled(!model.HasSkeleton);
|
||||
if (ImGui.Selectable("Animate"))
|
||||
{
|
||||
s.Renderer.Settings.AnimateMesh(true);
|
||||
s.Renderer.Options.AnimateMesh(true);
|
||||
s.WindowShouldClose(true, false);
|
||||
}
|
||||
ImGui.EndDisabled();
|
||||
if (ImGui.Selectable("Delete")) s.Renderer.Cache.Models.Remove(guid);
|
||||
if (ImGui.Selectable("Deselect")) s.Renderer.Settings.SelectModel(Guid.Empty);
|
||||
if (ImGui.Selectable("Delete")) s.Renderer.Options.Models.Remove(guid);
|
||||
if (ImGui.Selectable("Deselect")) s.Renderer.Options.SelectModel(Guid.Empty);
|
||||
ImGui.Separator();
|
||||
if (ImGui.Selectable("Copy Name to Clipboard")) ImGui.SetClipboardText(model.Name);
|
||||
ImGui.EndPopup();
|
||||
|
|
@ -197,7 +206,7 @@ public class SnimGui
|
|||
|
||||
private void DrawSockets(Snooper s)
|
||||
{
|
||||
foreach (var model in s.Renderer.Cache.Models.Values)
|
||||
foreach (var model in s.Renderer.Options.Models.Values)
|
||||
{
|
||||
if (!model.HasSkeleton || model.IsSelected) return;
|
||||
if (ImGui.TreeNode($"{model.Name} [{model.Skeleton.Sockets.Length}]"))
|
||||
|
|
@ -210,14 +219,10 @@ public class SnimGui
|
|||
ImGui.Text($"P: {socket.Transform.Matrix.M41} | {socket.Transform.Matrix.M42} | {socket.Transform.Matrix.M43}");
|
||||
// ImGui.Text($"R: {socket.Transform.Rotation}");
|
||||
// ImGui.Text($"S: {socket.Transform.Scale}");
|
||||
if (ImGui.Button("Attach"))
|
||||
if (ImGui.Button("Attach") && s.Renderer.Options.TryGetModel(out var selected))
|
||||
{
|
||||
var guid = s.Renderer.Settings.SelectedModel;
|
||||
if (s.Renderer.Cache.Models.TryGetValue(guid, out var selected))
|
||||
{
|
||||
selected.Transforms[selected.SelectedInstance] = socket.Transform;
|
||||
selected.UpdateMatrix(selected.SelectedInstance);
|
||||
}
|
||||
selected.Transforms[selected.SelectedInstance] = socket.Transform;
|
||||
selected.UpdateMatrix(selected.SelectedInstance);
|
||||
}
|
||||
ImGui.PopID();
|
||||
i++;
|
||||
|
|
@ -233,7 +238,7 @@ public class SnimGui
|
|||
MeshWindow("Details", s.Renderer, (icons, model) =>
|
||||
{
|
||||
ImGui.Text($"Entity: ({model.Type}) {model.Name}");
|
||||
ImGui.Text($"Guid: {s.Renderer.Settings.SelectedModel.ToString(EGuidFormats.UniqueObjectGuid)}");
|
||||
ImGui.Text($"Guid: {s.Renderer.Options.SelectedModel.ToString(EGuidFormats.UniqueObjectGuid)}");
|
||||
ImGui.Spacing();
|
||||
if (ImGui.Button("Go To"))
|
||||
{
|
||||
|
|
@ -265,19 +270,19 @@ public class SnimGui
|
|||
|
||||
ImGui.Text(section.MaterialIndex.ToString("D"));
|
||||
ImGui.TableNextColumn();
|
||||
if (ImGui.Selectable(material.Name, s.Renderer.Settings.SelectedSection == i, ImGuiSelectableFlags.SpanAllColumns))
|
||||
if (ImGui.Selectable(material.Name, s.Renderer.Options.SelectedSection == i, ImGuiSelectableFlags.SpanAllColumns))
|
||||
{
|
||||
s.Renderer.Settings.SelectSection(i);
|
||||
s.Renderer.Options.SelectSection(i);
|
||||
}
|
||||
if (ImGui.BeginPopupContextItem())
|
||||
{
|
||||
s.Renderer.Settings.SelectSection(i);
|
||||
s.Renderer.Options.SelectSection(i);
|
||||
if (ImGui.MenuItem("Show", null, section.Show)) section.Show = !section.Show;
|
||||
if (ImGui.Selectable("Swap"))
|
||||
{
|
||||
if (_swapAwareness)
|
||||
{
|
||||
s.Renderer.Settings.SwapMaterial(true);
|
||||
s.Renderer.Options.SwapMaterial(true);
|
||||
s.WindowShouldClose(true, false);
|
||||
}
|
||||
else swap = true;
|
||||
|
|
@ -306,7 +311,7 @@ public class SnimGui
|
|||
if (ImGui.Button("OK", size))
|
||||
{
|
||||
ImGui.CloseCurrentPopup();
|
||||
s.Renderer.Settings.SwapMaterial(true);
|
||||
s.Renderer.Options.SwapMaterial(true);
|
||||
s.WindowShouldClose(true, false);
|
||||
}
|
||||
|
||||
|
|
@ -399,9 +404,9 @@ public class SnimGui
|
|||
for (int i = 0; i < model.Morphs.Length; i++)
|
||||
{
|
||||
ImGui.PushID(i);
|
||||
if (ImGui.Selectable(model.Morphs[i].Name, s.Renderer.Settings.SelectedMorph == i))
|
||||
if (ImGui.Selectable(model.Morphs[i].Name, s.Renderer.Options.SelectedMorph == i))
|
||||
{
|
||||
s.Renderer.Settings.SelectMorph(i, model);
|
||||
s.Renderer.Options.SelectMorph(i, model);
|
||||
}
|
||||
ImGui.PopID();
|
||||
}
|
||||
|
|
@ -491,7 +496,7 @@ public class SnimGui
|
|||
if (ImGui.IsMouseClicked(ImGuiMouseButton.Right))
|
||||
{
|
||||
var guid = s.Renderer.Picking.ReadPixel(ImGui.GetMousePos(), ImGui.GetCursorScreenPos(), size);
|
||||
s.Renderer.Settings.SelectModel(guid);
|
||||
s.Renderer.Options.SelectModel(guid);
|
||||
ImGui.SetWindowFocus("Outliner");
|
||||
}
|
||||
}
|
||||
|
|
@ -534,7 +539,7 @@ public class SnimGui
|
|||
{
|
||||
Window(name, () =>
|
||||
{
|
||||
if (renderer.Cache.Models.TryGetValue(renderer.Settings.SelectedModel, out var model)) content(renderer.Cache.Icons, model);
|
||||
if (renderer.Options.TryGetModel(out var model)) content(renderer.Options.Icons, model);
|
||||
else NoMeshSelected();
|
||||
}, styled);
|
||||
}
|
||||
|
|
@ -543,7 +548,7 @@ public class SnimGui
|
|||
{
|
||||
MeshWindow(name, renderer, (icons, model) =>
|
||||
{
|
||||
if (renderer.Settings.TryGetSection(model, out var section)) content(icons, model, section);
|
||||
if (renderer.Options.TryGetSection(model, out var section)) content(icons, model, section);
|
||||
else NoSectionSelected();
|
||||
}, styled);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Numerics;
|
||||
using System.Threading;
|
||||
|
|
@ -41,7 +42,7 @@ public class Snooper : GameWindow
|
|||
Camera = newCamera;
|
||||
_previousSpeed = Camera.Speed;
|
||||
}
|
||||
return Renderer.Cache.Models.Count > 0;
|
||||
return Renderer.Options.Models.Count > 0;
|
||||
}
|
||||
|
||||
public unsafe void WindowShouldClose(bool value, bool clear)
|
||||
|
|
@ -49,8 +50,8 @@ public class Snooper : GameWindow
|
|||
if (clear)
|
||||
{
|
||||
_previousSpeed = 0f;
|
||||
Renderer.Cache.Reset();
|
||||
Renderer.Settings.Reset();
|
||||
Renderer.Options.ResetModelsAndLights();
|
||||
Renderer.Options.SelectModel(Guid.Empty);
|
||||
Renderer.Save();
|
||||
}
|
||||
|
||||
|
|
@ -71,7 +72,7 @@ public class Snooper : GameWindow
|
|||
{
|
||||
if (_init)
|
||||
{
|
||||
Renderer.Cache.Setup();
|
||||
Renderer.Options.SetupModelsAndLights();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,36 +2,49 @@
|
|||
using System.Numerics;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
using CUE4Parse.UE4.Objects.Core.Misc;
|
||||
using ImGuiNET;
|
||||
|
||||
namespace FModel.Views.Snooper;
|
||||
|
||||
public class SpotLight : Light
|
||||
{
|
||||
public Vector3 Direction; // ???
|
||||
public Vector2 Direction; // ???
|
||||
public float Attenuation;
|
||||
public float ConeAngle;
|
||||
|
||||
public SpotLight(Texture icon, UObject parent, UObject spot, FVector position) : base(icon, parent, spot, position)
|
||||
public SpotLight(FGuid model, Texture icon, UObject parent, UObject spot, FVector position) : base(model, icon, parent, spot, position)
|
||||
{
|
||||
if (!spot.TryGetValue(out Attenuation, "AttenuationRadius", "SourceRadius"))
|
||||
Attenuation = 1.0f;
|
||||
|
||||
Attenuation *= Constants.SCALE_DOWN_RATIO;
|
||||
Direction = Vector3.Zero;
|
||||
Direction.Y -= Attenuation;
|
||||
Direction = Vector2.Zero;
|
||||
ConeAngle = (spot.GetOrDefault("InnerConeAngle", 50.0f) + spot.GetOrDefault("OuterConeAngle", 60.0f)) / 2.0f;
|
||||
ConeAngle = MathF.Cos(Helper.DegreesToRadians(ConeAngle));
|
||||
}
|
||||
|
||||
public override void Render(int i, Shader shader)
|
||||
{
|
||||
shader.SetUniform($"uLights[{i}].Color", Color);
|
||||
shader.SetUniform($"uLights[{i}].Position", Transform.Position);
|
||||
shader.SetUniform($"uLights[{i}].Intensity", Intensity);
|
||||
base.Render(i, shader);
|
||||
shader.SetUniform($"uLights[{i}].Direction", Direction);
|
||||
shader.SetUniform($"uLights[{i}].Attenuation", Attenuation);
|
||||
shader.SetUniform($"uLights[{i}].ConeAngle", ConeAngle);
|
||||
|
||||
shader.SetUniform($"uLights[{i}].Type", 1);
|
||||
}
|
||||
|
||||
public override void ImGuiLight()
|
||||
{
|
||||
base.ImGuiLight();
|
||||
SnimGui.Layout("Direction");ImGui.PushID(3);
|
||||
ImGui.DragFloat2("", ref Direction, 0.01f);
|
||||
ImGui.PopID();SnimGui.Layout("Attenuation");ImGui.PushID(4);
|
||||
ImGui.DragFloat("", ref Attenuation, 0.1f);ImGui.PopID();
|
||||
|
||||
var angle = Helper.RadiansToDegrees(MathF.Acos(ConeAngle));
|
||||
SnimGui.Layout("Cone Angle");ImGui.PushID(5);
|
||||
ImGui.DragFloat("", ref angle, 0.1f, 0.0f, 90.0f, "%.1f°");ImGui.PopID();
|
||||
ConeAngle = MathF.Cos(Helper.DegreesToRadians(angle));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user