mirror of
https://github.com/4sval/FModel.git
synced 2026-04-20 00:27:43 -05:00
morph tangent + cull facing
This commit is contained in:
parent
76a9f88eee
commit
174401ec42
|
|
@ -1 +1 @@
|
|||
Subproject commit 59b004c355647a22c0ad7945443d0de509ecdaf1
|
||||
Subproject commit db65a8e98518cfaef7fa935b28a8f83e9a2f39d0
|
||||
|
|
@ -9,7 +9,8 @@ layout (location = 6) in vec4 vColor;
|
|||
layout (location = 7) in vec4 vBoneIds;
|
||||
layout (location = 8) in vec4 vBoneWeights;
|
||||
layout (location = 9) in mat4 vInstanceMatrix;
|
||||
layout (location = 13) in vec3 vMorphTarget;
|
||||
layout (location = 13) in vec3 vMorphTargetPos;
|
||||
layout (location = 14) in vec3 vMorphTargetTangent;
|
||||
|
||||
//const int MAX_BONES = 0;
|
||||
//const int MAX_BONE_INFLUENCE = 0;
|
||||
|
|
@ -28,7 +29,8 @@ out vec4 fColor;
|
|||
|
||||
void main()
|
||||
{
|
||||
vec4 pos = vec4(mix(vPos, vMorphTarget, uMorphTime), 1.0);
|
||||
vec4 pos = vec4(mix(vPos, vMorphTargetPos, uMorphTime), 1.0);
|
||||
vec3 tangent = mix(vTangent, vMorphTargetTangent, uMorphTime);
|
||||
// for(int i = 0 ; i < MAX_BONE_INFLUENCE; i++)
|
||||
// {
|
||||
// if(vBoneIds[i] == -1) continue;
|
||||
|
|
@ -45,7 +47,7 @@ void main()
|
|||
|
||||
fPos = vec3(vInstanceMatrix * pos);
|
||||
fNormal = mat3(transpose(inverse(vInstanceMatrix))) * vNormal;
|
||||
fTangent = mat3(transpose(inverse(vInstanceMatrix))) * vTangent;
|
||||
fTangent = mat3(transpose(inverse(vInstanceMatrix))) * tangent;
|
||||
fTexCoords = vTexCoords;
|
||||
fTexLayer = vTexLayer;
|
||||
fColor = vColor;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ public class Grid : IDisposable
|
|||
|
||||
public void Render(Matrix4x4 viewMatrix, Matrix4x4 projMatrix, float near, float far)
|
||||
{
|
||||
GL.Disable(EnableCap.CullFace);
|
||||
GL.Disable(EnableCap.DepthTest);
|
||||
_vao.Bind();
|
||||
|
||||
|
|
@ -55,6 +56,7 @@ public class Grid : IDisposable
|
|||
|
||||
GL.DrawArrays(PrimitiveType.Triangles, 0, Indices.Length);
|
||||
GL.Enable(EnableCap.DepthTest);
|
||||
GL.Enable(EnableCap.CullFace);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ public class Model : IDisposable
|
|||
public float[] Vertices;
|
||||
public Section[] Sections;
|
||||
public Material[] Materials;
|
||||
public bool bMirrored;
|
||||
|
||||
public bool HasSkeleton => Skeleton is { IsLoaded: true };
|
||||
public readonly Skeleton Skeleton;
|
||||
|
|
@ -106,6 +107,7 @@ public class Model : IDisposable
|
|||
{
|
||||
var hasCustomUvs = lod.ExtraUV.IsValueCreated;
|
||||
UvCount = hasCustomUvs ? Math.Max(lod.NumTexCoords, numLods) : lod.NumTexCoords;
|
||||
bMirrored = lod.IsMirrored;
|
||||
|
||||
Materials = new Material[materials.Length];
|
||||
for (int m = 0; m < Materials.Length; m++)
|
||||
|
|
@ -252,7 +254,8 @@ public class Model : IDisposable
|
|||
_morphVbo = new BufferObject<float>(Morphs[morph].Vertices, BufferTarget.ArrayBuffer);
|
||||
}
|
||||
_vao.Bind();
|
||||
_vao.VertexAttributePointer(13, 3, VertexAttribPointerType.Float, 3, 0); // morph position
|
||||
_vao.VertexAttributePointer(13, 3, VertexAttribPointerType.Float, Morph.VertexSize, 0); // morph position
|
||||
_vao.VertexAttributePointer(14, 3, VertexAttribPointerType.Float, Morph.VertexSize, 0); // morph tangent
|
||||
_vao.Unbind();
|
||||
}
|
||||
|
||||
|
|
@ -267,6 +270,7 @@ public class Model : IDisposable
|
|||
|
||||
public void Render(Shader shader)
|
||||
{
|
||||
if (bMirrored) GL.Disable(EnableCap.CullFace);
|
||||
if (IsSelected)
|
||||
{
|
||||
GL.Enable(EnableCap.StencilTest);
|
||||
|
|
@ -292,6 +296,7 @@ public class Model : IDisposable
|
|||
GL.StencilFunc(StencilFunction.Always, 0, 0xFF);
|
||||
GL.Disable(EnableCap.StencilTest);
|
||||
}
|
||||
if (bMirrored) GL.Enable(EnableCap.CullFace);
|
||||
}
|
||||
|
||||
public void SimpleRender(Shader shader)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ public class Morph : IDisposable
|
|||
{
|
||||
private int _handle;
|
||||
|
||||
private readonly int _vertexSize = 3; // Position
|
||||
public static readonly int VertexSize = 6; // Position + Tangent
|
||||
|
||||
public readonly string Name;
|
||||
public readonly float[] Vertices;
|
||||
|
|
@ -17,37 +17,45 @@ public class Morph : IDisposable
|
|||
public Morph(float[] vertices, int vertexSize, UMorphTarget morphTarget)
|
||||
{
|
||||
Name = morphTarget.Name;
|
||||
Vertices = new float[vertices.Length / vertexSize * _vertexSize];
|
||||
Vertices = new float[vertices.Length / vertexSize * VertexSize];
|
||||
|
||||
bool TryFindVertex(uint index, out FVector positionDelta)
|
||||
bool TryFindVertex(uint index, out FVector positionDelta, out FVector tangentDelta)
|
||||
{
|
||||
foreach (var vertex in morphTarget.MorphLODModels[0].Vertices)
|
||||
{
|
||||
if (vertex.SourceIdx == index)
|
||||
{
|
||||
positionDelta = vertex.PositionDelta;
|
||||
tangentDelta = vertex.TangentZDelta;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
positionDelta = FVector.ZeroVector;
|
||||
tangentDelta = FVector.ZeroVector;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < vertices.Length; i += vertexSize)
|
||||
{
|
||||
var count = 0;
|
||||
var baseIndex = i / vertexSize * _vertexSize;
|
||||
if (TryFindVertex((uint) vertices[i + 0], out var positionDelta))
|
||||
var baseIndex = i / vertexSize * VertexSize;
|
||||
if (TryFindVertex((uint) vertices[i + 0], out var positionDelta, out var tangentDelta))
|
||||
{
|
||||
Vertices[baseIndex + count++] = vertices[i + 1] + positionDelta.X * Constants.SCALE_DOWN_RATIO;
|
||||
Vertices[baseIndex + count++] = vertices[i + 2] + positionDelta.Z * Constants.SCALE_DOWN_RATIO;
|
||||
Vertices[baseIndex + count++] = vertices[i + 3] + positionDelta.Y * Constants.SCALE_DOWN_RATIO;
|
||||
Vertices[baseIndex + count++] = vertices[i + 7] + tangentDelta.X * Constants.SCALE_DOWN_RATIO;
|
||||
Vertices[baseIndex + count++] = vertices[i + 8] + tangentDelta.Z * Constants.SCALE_DOWN_RATIO;
|
||||
Vertices[baseIndex + count++] = vertices[i + 9] + tangentDelta.Y * Constants.SCALE_DOWN_RATIO;
|
||||
}
|
||||
else
|
||||
{
|
||||
Vertices[baseIndex + count++] = vertices[i + 1];
|
||||
Vertices[baseIndex + count++] = vertices[i + 2];
|
||||
Vertices[baseIndex + count++] = vertices[i + 3];
|
||||
Vertices[baseIndex + count++] = vertices[i + 7];
|
||||
Vertices[baseIndex + count++] = vertices[i + 8];
|
||||
Vertices[baseIndex + count++] = vertices[i + 9];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ public class Section : IDisposable
|
|||
public Section(int index, int facesCount, int firstFaceIndex, Material material) : this(index, facesCount, firstFaceIndex)
|
||||
{
|
||||
material.IsUsed = true;
|
||||
Show = !material.Parameters.IsNull && !material.Parameters.IsTransparent;
|
||||
Show = !material.Parameters.IsNull && !material.Parameters.IsTranslucent;
|
||||
}
|
||||
|
||||
public void Setup()
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ public class Skybox : IDisposable
|
|||
|
||||
public void Render(Matrix4x4 viewMatrix, Matrix4x4 projMatrix)
|
||||
{
|
||||
GL.Disable(EnableCap.CullFace);
|
||||
GL.DepthFunc(DepthFunction.Lequal);
|
||||
|
||||
_vao.Bind();
|
||||
|
|
@ -101,6 +102,7 @@ public class Skybox : IDisposable
|
|||
GL.DrawArrays(PrimitiveType.Triangles, 0, 36);
|
||||
|
||||
GL.DepthFunc(DepthFunction.Less);
|
||||
GL.Enable(EnableCap.CullFace);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
|
|||
|
|
@ -285,6 +285,7 @@ public class Renderer : IDisposable
|
|||
else if (m.TryConvert(out var mesh))
|
||||
{
|
||||
model = new Model(m, mesh, t);
|
||||
model.bMirrored = actor.GetOrDefault("bMirrored", model.bMirrored);
|
||||
if (actor.TryGetValue(out FPackageIndex baseMaterial, "BaseMaterial") &&
|
||||
actor.TryGetAllValues(out FPackageIndex[] textureData, "TextureData"))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using CUE4Parse.UE4.Assets.Exports.Material;
|
|||
using CUE4Parse.UE4.Assets.Exports.Texture;
|
||||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
using CUE4Parse.UE4.Objects.Core.Misc;
|
||||
using FModel.Extensions;
|
||||
using FModel.Views.Snooper.Models;
|
||||
using ImGuiNET;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
|
|
@ -265,17 +266,23 @@ public class Material : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
public void ImGuiBaseProperties(string id)
|
||||
{
|
||||
if (ImGui.BeginTable(id, 2, ImGuiTableFlags.SizingStretchProp))
|
||||
{
|
||||
Layout("Blend", Parameters.BlendMode.GetDescription(), true, true);
|
||||
Layout("Shading", Parameters.ShadingModel.GetDescription(), true, true);
|
||||
ImGui.EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
public void ImGuiDictionaries<T>(string id, Dictionary<string, T> dictionary, bool center = false, bool wrap = false)
|
||||
{
|
||||
if (ImGui.BeginTable(id, 2))
|
||||
{
|
||||
foreach ((string key, T value) in dictionary.Reverse())
|
||||
{
|
||||
SnimGui.Layout(key, true);
|
||||
var text = $"{value:N}";
|
||||
if (center) ImGui.SetCursorPosX(ImGui.GetCursorPosX() + (ImGui.GetColumnWidth() - ImGui.CalcTextSize(text).X) / 2);
|
||||
if (wrap) ImGui.TextWrapped(text); else ImGui.Text(text);
|
||||
SnimGui.TooltipCopy(text);
|
||||
Layout(key, value, center, wrap);
|
||||
}
|
||||
ImGui.EndTable();
|
||||
}
|
||||
|
|
@ -363,6 +370,15 @@ public class Material : IDisposable
|
|||
};
|
||||
}
|
||||
|
||||
private void Layout<T>(string key, T value, bool center = false, bool wrap = false)
|
||||
{
|
||||
SnimGui.Layout(key, true);
|
||||
var text = $"{value:N}";
|
||||
if (center) ImGui.SetCursorPosX(ImGui.GetCursorPosX() + (ImGui.GetColumnWidth() - ImGui.CalcTextSize(text).X) / 2);
|
||||
if (wrap) ImGui.TextWrapped(text); else ImGui.Text(text);
|
||||
SnimGui.TooltipCopy(text);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
for (int i = 0; i < Diffuse.Length; i++)
|
||||
|
|
|
|||
|
|
@ -430,6 +430,7 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio
|
|||
{
|
||||
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}");
|
||||
|
|
@ -591,6 +592,13 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio
|
|||
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
|
||||
if (ImGui.CollapsingHeader("Properties"))
|
||||
{
|
||||
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
|
||||
if (ImGui.TreeNode("Base"))
|
||||
{
|
||||
material.ImGuiBaseProperties("base");
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
|
||||
if (ImGui.TreeNode("Scalars"))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ public class Snooper : GameWindow
|
|||
|
||||
GL.ClearColor(OpenTK.Mathematics.Color4.Black);
|
||||
GL.Enable(EnableCap.Blend);
|
||||
GL.Enable(EnableCap.CullFace);
|
||||
GL.Enable(EnableCap.DepthTest);
|
||||
GL.Enable(EnableCap.Multisample);
|
||||
GL.StencilOp(StencilOp.Keep, StencilOp.Replace, StencilOp.Replace);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user