Skip to content

Commit

Permalink
uv map poc
Browse files Browse the repository at this point in the history
  • Loading branch information
4sval committed Oct 24, 2022
1 parent 023b68f commit 29f556d
Show file tree
Hide file tree
Showing 8 changed files with 203 additions and 242 deletions.
2 changes: 1 addition & 1 deletion FModel/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ private async void OnLoaded(object sender, RoutedEventArgs e)
#if DEBUG
await _threadWorkerView.Begin(cancellationToken =>
_applicationView.CUE4Parse.Extract(cancellationToken,
"fortnitegame/Content/Accessories/FORT_Backpacks/Backpack_F_MED_FNCS_S20/Meshes/F_MED_FNCS_S20_Pack.uasset"));
"FortniteGame/Content/Environments/Artemis/Sets/Seven/Village/Meshes/S_Seven_Village_Wall_01A_Window02.uasset"));
#endif
}

Expand Down
2 changes: 1 addition & 1 deletion FModel/Resources/default.frag
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ in vec4 fColor;
struct Material {
sampler2D diffuseMap;
sampler2D normalMap;
sampler2D specularMap;
sampler2D emissionMap;

bool useSpecularMap;
sampler2D specularMap;

bool hasDiffuseColor;
vec4 diffuseColor;
Expand Down
8 changes: 5 additions & 3 deletions FModel/Views/Snooper/Cube.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using CUE4Parse.UE4.Assets.Exports;
using CUE4Parse.UE4.Assets.Exports.Material;
using CUE4Parse.UE4.Assets.Exports.Material;

namespace FModel.Views.Snooper;

Expand Down Expand Up @@ -62,8 +61,11 @@ public Cube(UMaterialInterface unrealMaterial) : base(unrealMaterial.Name, unrea
-1, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f
};

Materials = new Material[1];
Materials[0] = new Material(1, unrealMaterial);

Sections = new Section[1];
Sections[0] = new Section(0, Indices.Length, 0, unrealMaterial);
Sections[0] = new Section(0, Indices.Length, 0, Materials[0]);

AddInstance(Transform.Identity);
}
Expand Down
147 changes: 147 additions & 0 deletions FModel/Views/Snooper/Material.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
using System;
using CUE4Parse_Conversion.Textures;
using CUE4Parse.UE4.Assets.Exports.Material;
using CUE4Parse.UE4.Assets.Exports.Texture;
using FModel.Settings;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Mathematics;

namespace FModel.Views.Snooper;

public class Material : IDisposable
{
private int _handle;

private Vector3 _ambientLight;

public readonly CMaterialParams2 Parameters;
public readonly int UvNumber;

public Texture[] Diffuse;
public Texture[] Normals;
public Texture[] SpecularMasks;
public Texture Emissive;

public Vector4 DiffuseColor;
public Vector4 EmissionColor;
public bool HasSpecularMap;
public bool HasDiffuseColor;

public Material()
{
DiffuseColor = Vector4.Zero;
EmissionColor = Vector4.Zero;
}

public Material(int numUvs, UMaterialInterface unrealMaterial) : this()
{
UvNumber = numUvs;
Parameters = new CMaterialParams2();
SwapMaterial(unrealMaterial);
}

public void SwapMaterial(UMaterialInterface unrealMaterial)
{
unrealMaterial.GetParams(Parameters);
}

public void Setup(Cache cache)
{
_handle = GL.CreateProgram();

int index;
var platform = UserSettings.Default.OverridedPlatform;
void Add(Texture[] array, UTexture2D original)
{
var guid = original.LightingGuid;
if (cache.TryGetTexture(guid, out var texture))
{
array[index++] = texture;
}
else if (original.GetFirstMip() is { } mip)
{
TextureDecoder.DecodeTexture(mip, original.Format, original.isNormalMap, platform, out var data, out _);

var t = new Texture(data, mip.SizeX, mip.SizeY, original);
cache.AddTexture(guid, t);
array[index++] = t;
}
}

index = 0;
Diffuse = new Texture[UvNumber];
foreach (var d in Parameters.GetDiffuseTextures())
if (index < UvNumber && d is UTexture2D original)
Add(Diffuse, original);

index = 0;
Normals = new Texture[UvNumber];
foreach (var n in Parameters.GetNormalsTextures())
if (index < UvNumber && n is UTexture2D original)
Add(Normals, original);

index = 0;
SpecularMasks = new Texture[UvNumber];
foreach (var s in Parameters.GetSpecularMasksTextures())
if (index < UvNumber && s is UTexture2D original)
Add(SpecularMasks, original);

// diffuse light is based on normal map, so increase ambient if no normal map
_ambientLight = new Vector3(Normals[0] == null ? 1.0f : 0.2f);
HasSpecularMap = SpecularMasks[0] != null;
HasDiffuseColor = DiffuseColor != Vector4.Zero;
}

public void Render(Shader shader)
{
var unit = 0;

for (var i = 0; i < Diffuse.Length; i++)
{
shader.SetUniform("material.diffuseMap", unit);
Diffuse[i]?.Bind(TextureUnit.Texture0 + unit++);
}

for (var i = 0; i < Normals.Length; i++)
{
shader.SetUniform("material.normalMap", unit);
Normals[i]?.Bind(TextureUnit.Texture0 + unit++);
}

for (var i = 0; i < SpecularMasks.Length; i++)
{
shader.SetUniform("material.specularMap", unit);
SpecularMasks[i]?.Bind(TextureUnit.Texture0 + unit++);
}

shader.SetUniform("material.useSpecularMap", HasSpecularMap);

shader.SetUniform("material.hasDiffuseColor", HasDiffuseColor);
shader.SetUniform("material.diffuseColor", DiffuseColor);

shader.SetUniform("material.emissionColor", EmissionColor);

shader.SetUniform("material.metallic_value", 1f);
shader.SetUniform("material.roughness_value", 0f);

shader.SetUniform("light.ambient", _ambientLight);
}

public void Dispose()
{
for (int i = 0; i < Diffuse.Length; i++)
{
Diffuse[i]?.Dispose();
}
for (int i = 0; i < Normals.Length; i++)
{
Normals[i]?.Dispose();
}
for (int i = 0; i < SpecularMasks.Length; i++)
{
SpecularMasks[i]?.Dispose();
}
Emissive?.Dispose();
GL.DeleteProgram(_handle);
}
}
41 changes: 33 additions & 8 deletions FModel/Views/Snooper/Model.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using CUE4Parse.UE4.Assets.Exports.Animation;
using CUE4Parse.UE4.Objects.UObject;
using CUE4Parse_Conversion.Meshes.PSK;
using CUE4Parse.UE4.Assets;
using CUE4Parse.UE4.Assets.Exports.Material;
using OpenTK.Graphics.OpenGL4;

namespace FModel.Views.Snooper;
Expand All @@ -31,12 +33,14 @@ public class Model : IDisposable
public uint[] Indices;
public float[] Vertices;
public Section[] Sections;
public readonly Morph[] Morphs;
public Material[] Materials;
public readonly List<CSkelMeshBone> Skeleton;

public int TransformsCount;
public readonly List<Transform> Transforms;

public readonly Morph[] Morphs;

public bool Show;
public bool IsSetup;
public bool IsSelected;
Expand All @@ -52,10 +56,11 @@ protected Model(string name, string type)
Show = true;
}

public Model(string name, string type, CStaticMesh staticMesh) : this(name, type, staticMesh.LODs[0], staticMesh.LODs[0].Verts) {}
public Model(string name, string type, CStaticMesh staticMesh, Transform transform) : this(name, type, staticMesh.LODs[0], staticMesh.LODs[0].Verts, null, transform) {}
public Model(string name, string type, CSkeletalMesh skeletalMesh) : this(name, type, skeletalMesh.LODs[0], skeletalMesh.LODs[0].Verts, skeletalMesh.RefSkeleton) {}
public Model(string name, string type, FPackageIndex[] morphTargets, CSkeletalMesh skeletalMesh) : this(name, type, skeletalMesh)
public Model(string name, string type, ResolvedObject[] materials, CStaticMesh staticMesh) : this(name, type, materials, staticMesh, Transform.Identity) {}
public Model(string name, string type, ResolvedObject[] materials, CStaticMesh staticMesh, Transform transform) : this(name, type, materials, staticMesh.LODs[0], staticMesh.LODs[0].Verts, transform) {}
public Model(string name, string type, ResolvedObject[] materials, CSkeletalMesh skeletalMesh) : this(name, type, materials, skeletalMesh, Transform.Identity) {}
public Model(string name, string type, ResolvedObject[] materials, CSkeletalMesh skeletalMesh, Transform transform) : this(name, type, materials, skeletalMesh.LODs[0], skeletalMesh.LODs[0].Verts, transform, skeletalMesh.RefSkeleton) {}
public Model(string name, string type, ResolvedObject[] materials, FPackageIndex[] morphTargets, CSkeletalMesh skeletalMesh) : this(name, type, materials, skeletalMesh)
{
if (morphTargets is not { Length: > 0 })
return;
Expand All @@ -68,8 +73,15 @@ public Model(string name, string type, FPackageIndex[] morphTargets, CSkeletalMe
}
}

public Model(string name, string type, CBaseMeshLod lod, CMeshVertex[] vertices, List<CSkelMeshBone> skeleton = null, Transform transform = null) : this(name, type)
private Model(string name, string type, ResolvedObject[] materials, CBaseMeshLod lod, CMeshVertex[] vertices, Transform transform, List<CSkelMeshBone> skeleton = null) : this(name, type)
{
Materials = new Material[materials.Length];
for (int m = 0; m < Materials.Length; m++)
{
if (materials[m].TryLoad(out var material) && material is UMaterialInterface unrealMaterial)
Materials[m] = new Material(1, unrealMaterial); // lod.NumTexCoords
}

if (lod.VertexColors is { Length: > 0})
{
HasVertexColors = true;
Expand All @@ -91,7 +103,7 @@ public Model(string name, string type, CBaseMeshLod lod, CMeshVertex[] vertices,
for (var s = 0; s < sections.Length; s++)
{
var section = sections[s];
Sections[s] = new Section(section.MaterialName, section.MaterialIndex, section.NumFaces * _faceSize, section.FirstIndex, section);
Sections[s] = new Section(section.MaterialIndex, section.NumFaces * _faceSize, section.FirstIndex, Materials[section.MaterialIndex]);
for (uint face = 0; face < section.NumFaces; face++)
{
foreach (var f in _facesIndex)
Expand Down Expand Up @@ -141,7 +153,7 @@ public Model(string name, string type, CBaseMeshLod lod, CMeshVertex[] vertices,
}
}

AddInstance(transform ?? Transform.Identity);
AddInstance(transform);
}

public void AddInstance(Transform transform) => Transforms.Add(transform);
Expand Down Expand Up @@ -185,6 +197,13 @@ public void Setup(Cache cache)
_vao.BindInstancing(); // VertexAttributePointer 7, 8, 9, 10
}

{ // setup all materials for use in different UV channels
for (var i = 0; i < Materials.Length; i++)
{
Materials[i].Setup(cache);
}
}

if (HasMorphTargets)
{
for (uint morph = 0; morph < Morphs.Length; morph++)
Expand Down Expand Up @@ -265,10 +284,16 @@ public void Dispose()
Morphs[morph].Dispose();
}
}

for (int material = 0; material < Materials.Length; material++)
{
Materials[material]?.Dispose();
}
for (int section = 0; section < Sections.Length; section++)
{
Sections[section].Dispose();
}

GL.DeleteProgram(_handle);
}
}
16 changes: 8 additions & 8 deletions FModel/Views/Snooper/Renderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public void Swap(UMaterialInstance unrealMaterial)
if (!Cache.TryGetModel(Settings.SelectedModel, out var model) ||
!Settings.TryGetSection(model, out var section)) return;

section.SwapMaterial(unrealMaterial);
section.Material.SwapMaterial(unrealMaterial);
Settings.SwapMaterial(false);
}

Expand Down Expand Up @@ -111,7 +111,7 @@ private Camera LoadStaticMesh(UStaticMesh original)
if (!original.TryConvert(out var mesh))
return null;

Cache.AddModel(guid, new Model(original.Name, original.ExportType, mesh));
Cache.AddModel(guid, new Model(original.Name, original.ExportType, original.Materials, mesh));
Settings.SelectModel(guid);
return SetupCamera(mesh.BoundingBox *= Constants.SCALE_DOWN_RATIO);
}
Expand All @@ -121,7 +121,7 @@ private Camera LoadSkeletalMesh(USkeletalMesh original)
var guid = Guid.NewGuid();
if (Cache.HasModel(guid) || !original.TryConvert(out var mesh)) return null;

Cache.AddModel(guid, new Model(original.Name, original.ExportType, original.MorphTargets, mesh));
Cache.AddModel(guid, new Model(original.Name, original.ExportType, original.Materials, original.MorphTargets, mesh));
Settings.SelectModel(guid);
return SetupCamera(mesh.BoundingBox *= Constants.SCALE_DOWN_RATIO);
}
Expand Down Expand Up @@ -175,7 +175,7 @@ private Camera LoadWorld(CancellationToken cancellationToken, UWorld original)
}
else if (m.TryConvert(out var mesh))
{
model = new Model(m.Name, m.ExportType, mesh, transform);
model = new Model(m.Name, m.ExportType, m.Materials, mesh, transform);

if (actor.TryGetAllValues(out FPackageIndex[] textureData, "TextureData"))
{
Expand All @@ -186,13 +186,13 @@ private Camera LoadWorld(CancellationToken cancellationToken, UWorld original)

if (textureDataIdx.TryGetValue(out FPackageIndex diffuse, "Diffuse") &&
diffuse.Load() is UTexture2D diffuseTexture)
model.Sections[j].Parameters.Diffuse = diffuseTexture;
model.Sections[j].Material.Parameters.Textures["Diffuse"] = diffuseTexture;
if (textureDataIdx.TryGetValue(out FPackageIndex normal, "Normal") &&
normal.Load() is UTexture2D normalTexture)
model.Sections[j].Parameters.Normal = normalTexture;
model.Sections[j].Material.Parameters.Textures["Normals"] = normalTexture;
if (textureDataIdx.TryGetValue(out FPackageIndex specular, "Specular") &&
specular.Load() is UTexture2D specularTexture)
model.Sections[j].Parameters.Specular = specularTexture;
model.Sections[j].Material.Parameters.Textures["SpecularMasks"] = specularTexture;
}
}
if (staticMeshComp.TryGetValue(out FPackageIndex[] overrideMaterials, "OverrideMaterials"))
Expand All @@ -202,7 +202,7 @@ private Camera LoadWorld(CancellationToken cancellationToken, UWorld original)
{
if (j > max) break;
if (overrideMaterials[j].Load() is not UMaterialInterface unrealMaterial) continue;
model.Sections[j].SwapMaterial(unrealMaterial);
model.Sections[j].Material.SwapMaterial(unrealMaterial);
}
}

Expand Down
Loading

0 comments on commit 29f556d

Please sign in to comment.