mirror of
https://github.com/4sval/FModel.git
synced 2026-06-22 16:00:17 -05:00
poc
This commit is contained in:
parent
926cbec7eb
commit
569558640a
|
|
@ -1,15 +1,18 @@
|
|||
#version 330 core
|
||||
|
||||
layout (location = 0) in vec3 vPos;
|
||||
layout (location = 1) in vec3 vNormal;
|
||||
layout (location = 2) in vec2 vTexCoords;
|
||||
layout (location = 3) in vec4 vColor;
|
||||
layout (location = 4) in ivec4 vBoneIds;
|
||||
layout (location = 5) in vec4 vWeights;
|
||||
layout (location = 6) in mat4 vInstanceMatrix;
|
||||
layout (location = 1) in vec3 vPos;
|
||||
layout (location = 2) in vec3 vNormal;
|
||||
layout (location = 3) in vec2 vTexCoords;
|
||||
layout (location = 4) in vec4 vColor;
|
||||
layout (location = 5) in ivec4 vBoneIds;
|
||||
layout (location = 6) in vec4 vWeights;
|
||||
layout (location = 7) in mat4 vInstanceMatrix;
|
||||
|
||||
layout (location = 11) in vec3 vPosTarget;
|
||||
|
||||
uniform mat4 uView;
|
||||
uniform mat4 uProjection;
|
||||
uniform float morph_time;
|
||||
|
||||
out vec3 fPos;
|
||||
out vec3 fNormal;
|
||||
|
|
@ -18,9 +21,10 @@ out vec4 fColor;
|
|||
|
||||
void main()
|
||||
{
|
||||
gl_Position = uProjection * uView * vInstanceMatrix * vec4(vPos, 1.0);
|
||||
vec3 pos = mix(vPos, vPosTarget, morph_time);
|
||||
gl_Position = uProjection * uView * vInstanceMatrix * vec4(pos, 1.0);
|
||||
|
||||
fPos = vec3(vInstanceMatrix * vec4(vPos, 1.0));
|
||||
fPos = vec3(vInstanceMatrix * vec4(pos, 1.0));
|
||||
fNormal = mat3(transpose(inverse(vInstanceMatrix))) * vNormal;
|
||||
fTexCoords = vTexCoords;
|
||||
fColor = vColor;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#version 330 core
|
||||
|
||||
layout (location = 0) in vec3 vPos;
|
||||
layout (location = 1) in vec3 vNormal;
|
||||
layout (location = 6) in mat4 vInstanceMatrix;
|
||||
layout (location = 1) in vec3 vPos;
|
||||
layout (location = 2) in vec3 vNormal;
|
||||
layout (location = 7) in mat4 vInstanceMatrix;
|
||||
|
||||
uniform mat4 uView;
|
||||
uniform mat4 uProjection;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ public class Model : IDisposable
|
|||
private BufferObject<Matrix4x4> _matrixVbo;
|
||||
private VertexArrayObject<float, uint> _vao;
|
||||
|
||||
private uint _vertexSize = 8; // Position + Normal + UV
|
||||
private uint _vertexSize = 9; // VertexIndex + Position + Normal + UV
|
||||
private const uint _faceSize = 3; // just so we don't have to do .Length
|
||||
private readonly uint[] _facesIndex = { 1, 0, 2 };
|
||||
|
||||
|
|
@ -34,6 +34,7 @@ public class Model : IDisposable
|
|||
public uint[] Indices;
|
||||
public float[] Vertices;
|
||||
public Section[] Sections;
|
||||
public Morph[] Morphs;
|
||||
public readonly List<CSkelMeshBone> Skeleton;
|
||||
|
||||
public int TransformsCount;
|
||||
|
|
@ -65,18 +66,6 @@ public class Model : IDisposable
|
|||
HasBones = Skeleton != null;
|
||||
if (HasBones) _vertexSize += 8; // + BoneIds + BoneWeights
|
||||
|
||||
HasMorphTargets = morphTargets != null;
|
||||
if (HasMorphTargets)
|
||||
{
|
||||
var morph = morphTargets[0].Load<UMorphTarget>().MorphLODModels[0];
|
||||
foreach (var delta in morph.Vertices)
|
||||
{
|
||||
vertices[delta.SourceIdx].Position += delta.PositionDelta;
|
||||
}
|
||||
}
|
||||
|
||||
_vertexSize += 16; // + InstanceMatrix
|
||||
|
||||
var sections = lod.Sections.Value;
|
||||
Sections = new Section[sections.Length];
|
||||
Indices = new uint[sections.Sum(section => section.NumFaces * _faceSize)];
|
||||
|
|
@ -93,40 +82,41 @@ public class Model : IDisposable
|
|||
var count = 0;
|
||||
var i = face * _faceSize + f;
|
||||
var index = section.FirstIndex + i;
|
||||
var baseIndex = index * _vertexSize;
|
||||
var indice = lod.Indices.Value[index];
|
||||
|
||||
var vert = vertices[indice];
|
||||
Vertices[index * _vertexSize + count++] = vert.Position.X * Constants.SCALE_DOWN_RATIO;
|
||||
Vertices[index * _vertexSize + count++] = vert.Position.Z * Constants.SCALE_DOWN_RATIO;
|
||||
Vertices[index * _vertexSize + count++] = vert.Position.Y * Constants.SCALE_DOWN_RATIO;
|
||||
Vertices[index * _vertexSize + count++] = vert.Normal.X;
|
||||
Vertices[index * _vertexSize + count++] = vert.Normal.Z;
|
||||
Vertices[index * _vertexSize + count++] = vert.Normal.Y;
|
||||
Vertices[index * _vertexSize + count++] = vert.UV.U;
|
||||
Vertices[index * _vertexSize + count++] = vert.UV.V;
|
||||
|
||||
Vertices[baseIndex + count++] = indice;
|
||||
Vertices[baseIndex + count++] = vert.Position.X * Constants.SCALE_DOWN_RATIO;
|
||||
Vertices[baseIndex + count++] = vert.Position.Z * Constants.SCALE_DOWN_RATIO;
|
||||
Vertices[baseIndex + count++] = vert.Position.Y * Constants.SCALE_DOWN_RATIO;
|
||||
Vertices[baseIndex + count++] = vert.Normal.X;
|
||||
Vertices[baseIndex + count++] = vert.Normal.Z;
|
||||
Vertices[baseIndex + count++] = vert.Normal.Y;
|
||||
Vertices[baseIndex + count++] = vert.UV.U;
|
||||
Vertices[baseIndex + count++] = vert.UV.V;
|
||||
|
||||
if (HasVertexColors)
|
||||
{
|
||||
var color = lod.VertexColors[indice];
|
||||
Vertices[index * _vertexSize + count++] = color.R;
|
||||
Vertices[index * _vertexSize + count++] = color.G;
|
||||
Vertices[index * _vertexSize + count++] = color.B;
|
||||
Vertices[index * _vertexSize + count++] = color.A;
|
||||
Vertices[baseIndex + count++] = color.R;
|
||||
Vertices[baseIndex + count++] = color.G;
|
||||
Vertices[baseIndex + count++] = color.B;
|
||||
Vertices[baseIndex + count++] = color.A;
|
||||
}
|
||||
|
||||
if (HasBones)
|
||||
{
|
||||
var skelVert = (CSkelMeshVertex) vert;
|
||||
var weightsHash = skelVert.UnpackWeights();
|
||||
Vertices[index * _vertexSize + count++] = skelVert.Bone[0];
|
||||
Vertices[index * _vertexSize + count++] = skelVert.Bone[1];
|
||||
Vertices[index * _vertexSize + count++] = skelVert.Bone[2];
|
||||
Vertices[index * _vertexSize + count++] = skelVert.Bone[3];
|
||||
Vertices[index * _vertexSize + count++] = weightsHash[0];
|
||||
Vertices[index * _vertexSize + count++] = weightsHash[1];
|
||||
Vertices[index * _vertexSize + count++] = weightsHash[2];
|
||||
Vertices[index * _vertexSize + count++] = weightsHash[3];
|
||||
Vertices[baseIndex + count++] = skelVert.Bone[0];
|
||||
Vertices[baseIndex + count++] = skelVert.Bone[1];
|
||||
Vertices[baseIndex + count++] = skelVert.Bone[2];
|
||||
Vertices[baseIndex + count++] = skelVert.Bone[3];
|
||||
Vertices[baseIndex + count++] = weightsHash[0];
|
||||
Vertices[baseIndex + count++] = weightsHash[1];
|
||||
Vertices[baseIndex + count++] = weightsHash[2];
|
||||
Vertices[baseIndex + count++] = weightsHash[3];
|
||||
}
|
||||
|
||||
Indices[index] = i;
|
||||
|
|
@ -134,6 +124,16 @@ public class Model : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
HasMorphTargets = morphTargets != null;
|
||||
if (HasMorphTargets)
|
||||
{
|
||||
Morphs = new Morph[morphTargets.Length];
|
||||
for (var i = 0; i < Morphs.Length; i++)
|
||||
{
|
||||
Morphs[i] = new Morph(Vertices, _vertexSize, morphTargets[i].Load<UMorphTarget>());
|
||||
}
|
||||
}
|
||||
|
||||
AddInstance(transform ?? Transform.Identity);
|
||||
}
|
||||
|
||||
|
|
@ -156,23 +156,28 @@ public class Model : IDisposable
|
|||
_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); // normal
|
||||
_vao.VertexAttributePointer(2, 2, VertexAttribPointerType.Float, _vertexSize, 6); // uv
|
||||
_vao.VertexAttributePointer(3, 4, VertexAttribPointerType.Float, _vertexSize, 8); // color
|
||||
_vao.VertexAttributePointer(4, 4, VertexAttribPointerType.Int, _vertexSize, 12); // boneids
|
||||
_vao.VertexAttributePointer(5, 4, VertexAttribPointerType.Float, _vertexSize, 16); // boneweights
|
||||
_vao.VertexAttributePointer(6, 16, VertexAttribPointerType.Float, _vertexSize, 20); // instancematrix
|
||||
_vao.VertexAttributePointer(0, 1, VertexAttribPointerType.Int, _vertexSize, 0); // vertex index
|
||||
_vao.VertexAttributePointer(1, 3, VertexAttribPointerType.Float, _vertexSize, 1); // position
|
||||
_vao.VertexAttributePointer(2, 3, VertexAttribPointerType.Float, _vertexSize, 4); // normal
|
||||
_vao.VertexAttributePointer(3, 2, VertexAttribPointerType.Float, _vertexSize, 7); // uv
|
||||
_vao.VertexAttributePointer(4, 4, VertexAttribPointerType.Float, _vertexSize, 9); // color
|
||||
_vao.VertexAttributePointer(5, 4, VertexAttribPointerType.Int, _vertexSize, 13); // boneids
|
||||
_vao.VertexAttributePointer(6, 4, VertexAttribPointerType.Float, _vertexSize, 17); // boneweights
|
||||
|
||||
TransformsCount = Transforms.Count;
|
||||
var instanceMatrix = new Matrix4x4[TransformsCount];
|
||||
for (var i = 0; i < instanceMatrix.Length; i++)
|
||||
instanceMatrix[i] = Transforms[i].Matrix;
|
||||
_matrixVbo = new BufferObject<Matrix4x4>(_gl, instanceMatrix, BufferTargetARB.ArrayBuffer);
|
||||
_vao.BindInstancing();
|
||||
|
||||
Morphs[0].Setup(gl);
|
||||
_vao.Bind();
|
||||
_vao.VertexAttributePointer(11, 3, VertexAttribPointerType.Float, _vertexSize, 1); // target position
|
||||
_vao.Unbind();
|
||||
|
||||
for (int section = 0; section < Sections.Length; section++)
|
||||
{
|
||||
_vao.BindInstancing();
|
||||
Sections[section].Setup(_gl);
|
||||
}
|
||||
}
|
||||
|
|
@ -187,6 +192,7 @@ public class Model : IDisposable
|
|||
|
||||
_vao.Bind();
|
||||
shader.SetUniform("display_vertex_colors", DisplayVertexColors);
|
||||
Morphs[0].Bind(shader);
|
||||
for (int section = 0; section < Sections.Length; section++)
|
||||
{
|
||||
Sections[section].Bind(shader, (uint) TransformsCount);
|
||||
|
|
|
|||
68
FModel/Views/Snooper/Morph.cs
Normal file
68
FModel/Views/Snooper/Morph.cs
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
using System;
|
||||
using CUE4Parse.UE4.Assets.Exports.Animation;
|
||||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
using Silk.NET.OpenGL;
|
||||
|
||||
namespace FModel.Views.Snooper;
|
||||
|
||||
public class Morph : IDisposable
|
||||
{
|
||||
private uint _handle;
|
||||
private GL _gl;
|
||||
|
||||
private BufferObject<float> _vbo;
|
||||
|
||||
public readonly string Name;
|
||||
public float[] Vertices;
|
||||
|
||||
public float Value;
|
||||
|
||||
public Morph(float[] vertices, uint vertexSize, UMorphTarget morphTarget)
|
||||
{
|
||||
Name = morphTarget.Name;
|
||||
Vertices = (float[]) vertices.Clone();
|
||||
|
||||
bool TryFindVertex(uint index, out FVector positionDelta)
|
||||
{
|
||||
foreach (var vertex in morphTarget.MorphLODModels[0].Vertices)
|
||||
{
|
||||
if (vertex.SourceIdx == index)
|
||||
{
|
||||
positionDelta = vertex.PositionDelta;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
positionDelta = FVector.ZeroVector;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint i = 0; i < Vertices.Length; i += vertexSize)
|
||||
{
|
||||
if (!TryFindVertex((uint) Vertices[i + 0], out var positionDelta)) continue;
|
||||
|
||||
Vertices[i + 1] += positionDelta.X * Constants.SCALE_DOWN_RATIO;
|
||||
Vertices[i + 2] += positionDelta.Z * Constants.SCALE_DOWN_RATIO;
|
||||
Vertices[i + 3] += positionDelta.Y * Constants.SCALE_DOWN_RATIO;
|
||||
}
|
||||
}
|
||||
|
||||
public void Setup(GL gl)
|
||||
{
|
||||
_gl = gl;
|
||||
|
||||
_handle = _gl.CreateProgram();
|
||||
|
||||
_vbo = new BufferObject<float>(_gl, Vertices, BufferTargetARB.ArrayBuffer);
|
||||
}
|
||||
|
||||
public void Bind(Shader shader)
|
||||
{
|
||||
shader.SetUniform("morph_time", Value);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_vbo.Dispose();
|
||||
_gl.DeleteProgram(_handle);
|
||||
}
|
||||
}
|
||||
|
|
@ -316,6 +316,13 @@ public class SnimGui : IDisposable
|
|||
ImGui.BeginDisabled(!model.HasMorphTargets);
|
||||
if (ImGui.BeginTabItem("Shape Keys"))
|
||||
{
|
||||
for (int i = 0; i < model.Morphs.Length; i++)
|
||||
{
|
||||
ImGui.PushID(i);
|
||||
ImGui.Text(model.Morphs[i].Name);
|
||||
ImGui.DragFloat("Value", ref model.Morphs[i].Value, 0.01f, 0.0f, 1.0f, "%.2f", ImGuiSliderFlags.AlwaysClamp);
|
||||
ImGui.PopID();
|
||||
}
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
ImGui.EndDisabled();
|
||||
|
|
@ -343,37 +350,16 @@ public class SnimGui : IDisposable
|
|||
{
|
||||
ImGui.SetNextItemWidth(300);
|
||||
ImGui.ColorEdit4(section.TexturesLabels[0], ref section.DiffuseColor, ImGuiColorEditFlags.AlphaPreview | ImGuiColorEditFlags.AlphaBar);
|
||||
if (section.Textures[1] is { } normalMap) DrawTexture(normalMap);
|
||||
}
|
||||
// else
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < section.Textures.Length; i++)
|
||||
for (var i = 0;i < section.Textures.Length; i++)
|
||||
{
|
||||
if (section.Textures[i] is not {} texture)
|
||||
continue;
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.BeginGroup();
|
||||
ImGui.Image(texture.GetPointer(), new Vector2(88), Vector2.Zero, Vector2.One, Vector4.One, new Vector4(1, 1, 1, .5f));
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
ImGui.BeginTooltip();
|
||||
ImGui.Text($"Type: ({texture.Format}) {texture.Type}:{texture.Name}");
|
||||
ImGui.Text($"Texture: {texture.Path}");
|
||||
ImGui.Text($"Imported: {texture.ImportedWidth}x{texture.ImportedHeight}");
|
||||
ImGui.Text($"Mip Used: {texture.Width}x{texture.Height}");
|
||||
ImGui.Spacing();
|
||||
ImGui.TextDisabled(texture.Label);
|
||||
ImGui.EndTooltip();
|
||||
}
|
||||
|
||||
if (ImGui.IsItemClicked())
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(delegate
|
||||
{
|
||||
Clipboard.SetText(Utils.FixPath(texture.Path));
|
||||
texture.Label = "(?) Copied to Clipboard";
|
||||
});
|
||||
}
|
||||
DrawTexture(texture);
|
||||
|
||||
if (i == 3) // emissive, show color
|
||||
{
|
||||
|
|
@ -393,6 +379,33 @@ public class SnimGui : IDisposable
|
|||
ImGui.End();
|
||||
}
|
||||
|
||||
private void DrawTexture(Texture texture)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ImGui.BeginGroup();
|
||||
ImGui.Image(texture.GetPointer(), new Vector2(88), Vector2.Zero, Vector2.One, Vector4.One, new Vector4(1, 1, 1, .5f));
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
ImGui.BeginTooltip();
|
||||
ImGui.Text($"Type: ({texture.Format}) {texture.Type}:{texture.Name}");
|
||||
ImGui.Text($"Texture: {texture.Path}");
|
||||
ImGui.Text($"Imported: {texture.ImportedWidth}x{texture.ImportedHeight}");
|
||||
ImGui.Text($"Mip Used: {texture.Width}x{texture.Height}");
|
||||
ImGui.Spacing();
|
||||
ImGui.TextDisabled(texture.Label);
|
||||
ImGui.EndTooltip();
|
||||
}
|
||||
|
||||
if (ImGui.IsItemClicked())
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(delegate
|
||||
{
|
||||
Clipboard.SetText(Utils.FixPath(texture.Path));
|
||||
texture.Label = "(?) Copied to Clipboard";
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void Draw3DViewport(FramebufferObject framebuffer, Camera camera, IMouse mouse)
|
||||
{
|
||||
const float lookSensitivity = 0.1f;
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ namespace FModel.Views.Snooper;
|
|||
|
||||
public class VertexArrayObject<TVertexType, TIndexType> : IDisposable where TVertexType : unmanaged where TIndexType : unmanaged
|
||||
{
|
||||
private uint _handle;
|
||||
private GL _gl;
|
||||
private readonly uint _handle;
|
||||
private readonly GL _gl;
|
||||
|
||||
public VertexArrayObject(GL gl, BufferObject<TVertexType> vbo, BufferObject<TIndexType> ebo)
|
||||
{
|
||||
|
|
@ -43,19 +43,19 @@ public class VertexArrayObject<TVertexType, TIndexType> : IDisposable where TVer
|
|||
Bind();
|
||||
|
||||
var vec4Size = (uint) sizeof(Vector4);
|
||||
_gl.EnableVertexAttribArray(6);
|
||||
_gl.VertexAttribPointer(6, 4, VertexAttribPointerType.Float, false, 4 * vec4Size, (void*)0);
|
||||
_gl.EnableVertexAttribArray(7);
|
||||
_gl.VertexAttribPointer(7, 4, VertexAttribPointerType.Float, false, 4 * vec4Size, (void*)(1 * vec4Size));
|
||||
_gl.VertexAttribPointer(7, 4, VertexAttribPointerType.Float, false, 4 * vec4Size, (void*)0);
|
||||
_gl.EnableVertexAttribArray(8);
|
||||
_gl.VertexAttribPointer(8, 4, VertexAttribPointerType.Float, false, 4 * vec4Size, (void*)(2 * vec4Size));
|
||||
_gl.VertexAttribPointer(8, 4, VertexAttribPointerType.Float, false, 4 * vec4Size, (void*)(1 * vec4Size));
|
||||
_gl.EnableVertexAttribArray(9);
|
||||
_gl.VertexAttribPointer(9, 4, VertexAttribPointerType.Float, false, 4 * vec4Size, (void*)(3 * vec4Size));
|
||||
_gl.VertexAttribPointer(9, 4, VertexAttribPointerType.Float, false, 4 * vec4Size, (void*)(2 * vec4Size));
|
||||
_gl.EnableVertexAttribArray(10);
|
||||
_gl.VertexAttribPointer(10, 4, VertexAttribPointerType.Float, false, 4 * vec4Size, (void*)(3 * vec4Size));
|
||||
|
||||
_gl.VertexAttribDivisor(6, 1);
|
||||
_gl.VertexAttribDivisor(7, 1);
|
||||
_gl.VertexAttribDivisor(8, 1);
|
||||
_gl.VertexAttribDivisor(9, 1);
|
||||
_gl.VertexAttribDivisor(10, 1);
|
||||
|
||||
Unbind();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user