diff --git a/CUE4Parse b/CUE4Parse index db65a8e9..7d4cd465 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit db65a8e98518cfaef7fa935b28a8f83e9a2f39d0 +Subproject commit 7d4cd4656e2ebf97caea2d010e20b033612e88ca diff --git a/FModel/Views/Snooper/Lights/Light.cs b/FModel/Views/Snooper/Lights/Light.cs index 374a304a..f64e0cf6 100644 --- a/FModel/Views/Snooper/Lights/Light.cs +++ b/FModel/Views/Snooper/Lights/Light.cs @@ -75,6 +75,8 @@ public void Setup() public void Render(Shader shader) { + GL.Disable(EnableCap.CullFace); + _vao.Bind(); Icon?.Bind(TextureUnit.Texture0); @@ -82,6 +84,8 @@ public void Render(Shader shader) shader.SetUniform("uColor", Color); GL.DrawArrays(PrimitiveType.Triangles, 0, Indices.Length); + + GL.Enable(EnableCap.CullFace); } public virtual void Render(int i, Shader shader) diff --git a/FModel/Views/Snooper/Models/Model.cs b/FModel/Views/Snooper/Models/Model.cs index 9957667d..777a75cf 100644 --- a/FModel/Views/Snooper/Models/Model.cs +++ b/FModel/Views/Snooper/Models/Model.cs @@ -47,7 +47,7 @@ public class Model : IDisposable public float[] Vertices; public Section[] Sections; public Material[] Materials; - public bool bMirrored; + public bool TwoSided; public bool HasSkeleton => Skeleton is { IsLoaded: true }; public readonly Skeleton Skeleton; @@ -107,7 +107,7 @@ private Model(UObject export, ResolvedObject[] materials, FPackageIndex skeleton { var hasCustomUvs = lod.ExtraUV.IsValueCreated; UvCount = hasCustomUvs ? Math.Max(lod.NumTexCoords, numLods) : lod.NumTexCoords; - bMirrored = lod.IsMirrored; + TwoSided = lod.IsTwoSided; Materials = new Material[materials.Length]; for (int m = 0; m < Materials.Length; m++) @@ -182,7 +182,8 @@ private Model(UObject export, ResolvedObject[] materials, FPackageIndex skeleton for (var s = 0; s < Sections.Length; s++) { var section = lod.Sections.Value[s]; - Sections[s] = new Section(section.MaterialIndex, section.NumFaces * _faceSize, section.FirstIndex, Materials[section.MaterialIndex]); + Sections[s] = new Section(section.MaterialIndex, section.NumFaces * _faceSize, section.FirstIndex); + if (section.IsValid) Sections[s].SetupMaterial(Materials[section.MaterialIndex]); } AddInstance(transform ?? Transform.Identity); @@ -262,31 +263,34 @@ public void Setup(Options options) for (int section = 0; section < Sections.Length; section++) { if (!Show) Show = Sections[section].Show; - Sections[section].Setup(); } IsSetup = true; } - public void Render(Shader shader) + public void Render(Shader shader, bool outline = false) { - if (bMirrored) GL.Disable(EnableCap.CullFace); + if (outline) GL.Disable(EnableCap.DepthTest); + if (TwoSided) GL.Disable(EnableCap.CullFace); if (IsSelected) { GL.Enable(EnableCap.StencilTest); - GL.StencilFunc(StencilFunction.Always, 1, 0xFF); + GL.StencilFunc(outline ? StencilFunction.Notequal : StencilFunction.Always, 1, 0xFF); } _vao.Bind(); shader.SetUniform("uMorphTime", MorphTime); - shader.SetUniform("uUvCount", UvCount); - shader.SetUniform("uHasVertexColors", HasVertexColors); + if (!outline) + { + shader.SetUniform("uUvCount", UvCount); + shader.SetUniform("uHasVertexColors", HasVertexColors); + } GL.PolygonMode(MaterialFace.FrontAndBack, Wireframe ? PolygonMode.Line : PolygonMode.Fill); foreach (var section in Sections) { if (!section.Show) continue; - Materials[section.MaterialIndex].Render(shader); + if (!outline) Materials[section.MaterialIndex].Render(shader); GL.DrawElementsInstanced(PrimitiveType.Triangles, section.FacesCount, DrawElementsType.UnsignedInt, section.FirstFaceIndexPtr, TransformsCount); } _vao.Unbind(); @@ -296,41 +300,24 @@ public void Render(Shader shader) GL.StencilFunc(StencilFunction.Always, 0, 0xFF); GL.Disable(EnableCap.StencilTest); } - if (bMirrored) GL.Enable(EnableCap.CullFace); + if (TwoSided) GL.Enable(EnableCap.CullFace); + if (outline) GL.Enable(EnableCap.DepthTest); } public void SimpleRender(Shader shader) { - _vao.Bind(); - shader.SetUniform("uMorphTime", MorphTime); - foreach (var section in Sections) - { - if (!section.Show) continue; - GL.DrawElementsInstanced(PrimitiveType.Triangles, section.FacesCount, DrawElementsType.UnsignedInt, section.FirstFaceIndexPtr, TransformsCount); - } - _vao.Unbind(); - } - - public void Outline(Shader shader) - { - GL.Enable(EnableCap.StencilTest); - GL.Disable(EnableCap.DepthTest); - GL.StencilFunc(StencilFunction.Notequal, 1, 0xFF); + if (TwoSided) GL.Disable(EnableCap.CullFace); _vao.Bind(); shader.SetUniform("uMorphTime", MorphTime); - - GL.PolygonMode(MaterialFace.FrontAndBack, Wireframe ? PolygonMode.Line : PolygonMode.Fill); foreach (var section in Sections) { if (!section.Show) continue; - GL.DrawElementsInstancedBaseInstance(PrimitiveType.Triangles, section.FacesCount, DrawElementsType.UnsignedInt, section.FirstFaceIndexPtr, TransformsCount, SelectedInstance); + GL.DrawElementsInstanced(PrimitiveType.Triangles, section.FacesCount, DrawElementsType.UnsignedInt, section.FirstFaceIndexPtr, TransformsCount); } _vao.Unbind(); - GL.StencilFunc(StencilFunction.Always, 0, 0xFF); - GL.Enable(EnableCap.DepthTest); - GL.Disable(EnableCap.StencilTest); + if (TwoSided) GL.Enable(EnableCap.CullFace); } public bool TrySave(out string label, out string savedFilePath) @@ -364,11 +351,6 @@ public void Dispose() } } - for (int section = 0; section < Sections.Length; section++) - { - Sections[section].Dispose(); - } - GL.DeleteProgram(_handle); } } diff --git a/FModel/Views/Snooper/Models/Section.cs b/FModel/Views/Snooper/Models/Section.cs index a9435285..e39d24b4 100644 --- a/FModel/Views/Snooper/Models/Section.cs +++ b/FModel/Views/Snooper/Models/Section.cs @@ -1,13 +1,10 @@ using System; using FModel.Views.Snooper.Shading; -using OpenTK.Graphics.OpenGL4; namespace FModel.Views.Snooper.Models; -public class Section : IDisposable +public class Section { - private int _handle; - public readonly int MaterialIndex; public readonly int FacesCount; public readonly int FirstFaceIndex; @@ -24,19 +21,9 @@ public Section(int index, int facesCount, int firstFaceIndex) Show = true; } - public Section(int index, int facesCount, int firstFaceIndex, Material material) : this(index, facesCount, firstFaceIndex) + public void SetupMaterial(Material material) { material.IsUsed = true; Show = !material.Parameters.IsNull && !material.Parameters.IsTranslucent; } - - public void Setup() - { - _handle = GL.CreateProgram(); - } - - public void Dispose() - { - GL.DeleteProgram(_handle); - } } diff --git a/FModel/Views/Snooper/Renderer.cs b/FModel/Views/Snooper/Renderer.cs index 9b6425ff..d0123da8 100644 --- a/FModel/Views/Snooper/Renderer.cs +++ b/FModel/Views/Snooper/Renderer.cs @@ -145,7 +145,7 @@ public void Render() if (Options.TryGetModel(out var selected) && selected.Show) { _outline.Render(viewMatrix, CameraOp.Position, projMatrix); - selected.Outline(_outline); + selected.Render(_outline, true); } // picking pass (dedicated FBO, binding to 0 afterward) @@ -285,7 +285,8 @@ private void WorldMesh(UObject actor, Transform transform) else if (m.TryConvert(out var mesh)) { model = new Model(m, mesh, t); - model.bMirrored = actor.GetOrDefault("bMirrored", model.bMirrored); + model.TwoSided = actor.GetOrDefault("bMirrored", staticMeshComp.GetOrDefault("bDisallowMeshPaintPerInstance", model.TwoSided)); + if (actor.TryGetValue(out FPackageIndex baseMaterial, "BaseMaterial") && actor.TryGetAllValues(out FPackageIndex[] textureData, "TextureData")) { @@ -322,6 +323,7 @@ private void WorldMesh(UObject actor, Transform transform) } } } + if (staticMeshComp.TryGetValue(out FPackageIndex[] overrideMaterials, "OverrideMaterials")) { var max = model.Sections.Length - 1; @@ -333,6 +335,7 @@ private void WorldMesh(UObject actor, Transform transform) model.Materials[model.Sections[j].MaterialIndex].SwapMaterial(unrealMaterial); } } + Options.Models[guid] = model; } diff --git a/FModel/Views/Snooper/Shading/Material.cs b/FModel/Views/Snooper/Shading/Material.cs index 5a9b9c40..49e74068 100644 --- a/FModel/Views/Snooper/Shading/Material.cs +++ b/FModel/Views/Snooper/Shading/Material.cs @@ -73,8 +73,8 @@ public void Setup(Options options, int uvCount) if (uvCount < 1 || Parameters.IsNull) { Diffuse = new[] { new Texture(new FLinearColor(1f, 0f, 0f, 1f)) }; - Normals = new[] { new Texture(new FLinearColor(0.498f, 0.498f, 0.996f, 1f))}; - SpecularMasks = new Texture[1]; + Normals = new[] { new Texture(new FLinearColor(0.498f, 0.498f, 0.996f, 1f)) }; + SpecularMasks = new [] { new Texture(new FLinearColor(1f, 0.5f, 0.5f, 1f)) }; Emissive = new Texture[1]; DiffuseColor = new[] { new Vector4(0.5f) }; EmissiveColor = new[] { Vector4.One }; diff --git a/FModel/Views/Snooper/SnimGui.cs b/FModel/Views/Snooper/SnimGui.cs index 0f3adfac..7845fa9e 100644 --- a/FModel/Views/Snooper/SnimGui.cs +++ b/FModel/Views/Snooper/SnimGui.cs @@ -430,13 +430,16 @@ private void DrawDetails(Snooper s) { Layout("Entity");ImGui.Text($" : ({model.Type}) {model.Name}"); Layout("Guid");ImGui.Text($" : {s.Renderer.Options.SelectedModel.ToString(EGuidFormats.UniqueObjectGuid)}"); - Layout("Mirrored");ImGui.Text($" : {model.bMirrored}"); if (model.HasSkeleton) { Layout("Skeleton");ImGui.Text($" : {model.Skeleton.RefSkel.Name}"); Layout("Bones");ImGui.Text($" : x{model.Skeleton.RefSkel.BoneTree.Length}"); Layout("Sockets");ImGui.Text($" : x{model.Skeleton.Sockets.Length}"); } + else + { + Layout("Two Sided");ImGui.Text($" : {model.TwoSided}"); + } ImGui.EndTable(); }