From 31ff50ffd8483efc21ae51bacd282ec738240b7f Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Sun, 2 Feb 2025 13:39:37 -0600 Subject: [PATCH] feat: custom gltf --- .vscode/settings.json | 1 + src/BlitzKit.CLI/Functions/Mangler.cs | 53 +++++--- src/BlitzKit.CLI/Models/GLB.cs | 15 --- src/BlitzKit.CLI/Models/MonoGltf.cs | 166 ++++++++++++++++++++++++++ 4 files changed, 206 insertions(+), 29 deletions(-) delete mode 100644 src/BlitzKit.CLI/Models/GLB.cs create mode 100644 src/BlitzKit.CLI/Models/MonoGltf.cs diff --git a/.vscode/settings.json b/.vscode/settings.json index 4fc5125e1..0b275acf9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -201,6 +201,7 @@ "unwrapper", "Usmap", "vercel", + "Verts", "vickers", "vitepress", "Vovko", diff --git a/src/BlitzKit.CLI/Functions/Mangler.cs b/src/BlitzKit.CLI/Functions/Mangler.cs index 549a55bf0..7ec206eb2 100644 --- a/src/BlitzKit.CLI/Functions/Mangler.cs +++ b/src/BlitzKit.CLI/Functions/Mangler.cs @@ -1,9 +1,12 @@ using Blitzkit; using BlitzKit.CLI.Models; using BlitzKit.CLI.Utils; +using CommunityToolkit.HighPerformance; +using CommunityToolkit.HighPerformance.Helpers; using CUE4Parse_Conversion; using CUE4Parse_Conversion.Animations; using CUE4Parse_Conversion.Meshes; +using CUE4Parse_Conversion.Meshes.glTF; using CUE4Parse_Conversion.Textures; using CUE4Parse_Conversion.UEFormat.Enums; using CUE4Parse.UE4.Assets.Exports.Engine; @@ -11,6 +14,8 @@ using CUE4Parse.UE4.Assets.Exports.Material; using CUE4Parse.UE4.Assets.Exports.StaticMesh; using CUE4Parse.UE4.Assets.Exports.Texture; using CUE4Parse.UE4.Objects.UObject; +using CUE4Parse.UE4.Readers; +using CUE4Parse.UE4.Writers; using CUE4Parse.Utils; using Google.Protobuf.Collections; using Newtonsoft.Json.Linq; @@ -73,21 +78,41 @@ namespace BlitzKit.CLI.Functions var hullVisual = hull.GetObject("VisualData"); var hullMeshSettings = hullVisual.GetStruct("MeshSettings"); var hullMesh = hullMeshSettings.GetSoftObject("Mesh"); - MeshExporter hullMeshExporter = new( - hullMesh, - new() - { - MeshFormat = EMeshFormat.Gltf2, - ExportMaterials = true, - ExportMorphTargets = false, - LodFormat = ELodFormat.FirstLod, - TextureFormat = ETextureFormat.Jpeg, - SocketFormat = ESocketFormat.None, - Platform = ETexturePlatform.DesktopMobile, - } - ); - hullMeshExporter.TryWriteToDir(new("../../temp"), out _, out _); + + + + + MonoGltf hullGltf = new(tankId, hullMesh); + + // Gltf gltf = new(hullMesh.Name, hullLod0, null, new() { }); + // FArchiveWriter archiveWriter = new(); + + // gltf.Save(EMeshFormat.Gltf2, archiveWriter); + + // MeshExporter hullMeshExporter = new( + // hullMesh, + // new() + // { + // MeshFormat = EMeshFormat.Gltf2, + // ExportMaterials = true, + // ExportMorphTargets = false, + // LodFormat = ELodFormat.FirstLod, + // TextureFormat = ETextureFormat.Jpeg, + // SocketFormat = ESocketFormat.None, + // Platform = ETexturePlatform.DesktopMobile, + // } + // ); + + + + + // var hullLod0 = hullMeshExporter.MeshLods[0]; + // var hullMeshData = hullLod0.FileData; + + // File.WriteAllBytes($"../../temp/{tankId}.glb", hullMeshData); + + // hullMeshExporter.TryWriteToDir(new("../../temp"), out _, out _); return new() { Id = tankId }; } diff --git a/src/BlitzKit.CLI/Models/GLB.cs b/src/BlitzKit.CLI/Models/GLB.cs deleted file mode 100644 index 1c9f15b29..000000000 --- a/src/BlitzKit.CLI/Models/GLB.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace BlitzKit.CLI.Models -{ - public class GLB - { - public GLB(MappedUObject obj) - { - var staticMaterials = obj.GetArray("StaticMaterials"); - - foreach (var staticMaterial in staticMaterials) - { - Console.WriteLine(staticMaterial.GetAny("MaterialInterface")); - } - } - } -} diff --git a/src/BlitzKit.CLI/Models/MonoGltf.cs b/src/BlitzKit.CLI/Models/MonoGltf.cs new file mode 100644 index 000000000..e3155637a --- /dev/null +++ b/src/BlitzKit.CLI/Models/MonoGltf.cs @@ -0,0 +1,166 @@ +using System.Numerics; +using CUE4Parse_Conversion.Materials; +using CUE4Parse_Conversion.Meshes; +using CUE4Parse_Conversion.Meshes.glTF; +using CUE4Parse_Conversion.Meshes.PSK; +using CUE4Parse.UE4.Assets.Exports.StaticMesh; +using CUE4Parse.UE4.Objects.Core.Math; +using CUE4Parse.UE4.Objects.Meshes; +using SharpGLTF.Geometry; +using SharpGLTF.Geometry.VertexTypes; +using SharpGLTF.Materials; +using SharpGLTF.Scenes; +using SharpGLTF.Schema2; + +namespace BlitzKit.CLI.Models +{ + using VERTEX = VertexPositionNormalTangent; + + public class MonoGltf + { + public MonoGltf(string name, UStaticMesh staticMesh) + { + staticMesh.TryConvert(out var convertedMesh); + var lod = + convertedMesh.LODs.Find(lod => !lod.SkipLod) ?? throw new Exception("Failed to find lod0"); + + SceneBuilder sceneBuilder = new(name); + MeshBuilder meshBuilder = new(); + MaterialBuilder materialBuilder = new(name); + var primitive = meshBuilder.UsePrimitive(materialBuilder); + + foreach (var section in lod.Sections.Value) + { + for (int faceIndex = 0; faceIndex < section.NumFaces; faceIndex++) + { + var wedgeIndex = new int[3]; + for (var k = 0; k < wedgeIndex.Length; k++) + { + wedgeIndex[k] = lod.Indices.Value[section.FirstIndex + faceIndex * 3 + k]; + } + + var vertex1 = lod.Verts[wedgeIndex[0]]; + var vertex2 = lod.Verts[wedgeIndex[1]]; + var vertex3 = lod.Verts[wedgeIndex[2]]; + + var (v1, v2, v3) = PrepareTris(vertex1, vertex2, vertex3); + var (c1, c2, c3) = PrepareUVsAndTexCoords(lod, vertex1, vertex2, vertex3, wedgeIndex); + + primitive.AddTriangle((v1, c1), (v2, c2), (v3, c3)); + } + } + + sceneBuilder.AddRigidMesh(meshBuilder, Matrix4x4.Identity); + + var model = sceneBuilder.ToGltf2(); + + File.WriteAllBytes("../../temp/test.glb", model.WriteGLB()); + } + + private static (VERTEX, VERTEX, VERTEX) PrepareTris( + CMeshVertex vert1, + CMeshVertex vert2, + CMeshVertex vert3 + ) + { + VERTEX v1 = new( + SwapYZ(vert1.Position * 0.01f), + SwapYZAndNormalize((FVector)vert1.Normal), + SwapYZAndNormalize((Vector4)vert1.Tangent) + ); + VERTEX v2 = new( + SwapYZ(vert2.Position * 0.01f), + SwapYZAndNormalize((FVector)vert2.Normal), + SwapYZAndNormalize((Vector4)vert2.Tangent) + ); + VERTEX v3 = new( + SwapYZ(vert3.Position * 0.01f), + SwapYZAndNormalize((FVector)vert3.Normal), + SwapYZAndNormalize((Vector4)vert3.Tangent) + ); + + return (v1, v2, v3); + } + + public static FVector SwapYZ(FVector vec) + { + var res = new FVector(vec.X, vec.Z, vec.Y); + return res; + } + + public static FVector SwapYZAndNormalize(FVector vec) + { + var res = SwapYZ(vec); + res.Normalize(); + return res; + } + + public static Vector4 SwapYZAndNormalize(Vector4 vec) + { + return Vector4.Normalize(new Vector4(vec.X, vec.Z, vec.Y, vec.W)); + } + + public static ( + VertexColorXTextureX, + VertexColorXTextureX, + VertexColorXTextureX + ) PrepareUVsAndTexCoords( + CBaseMeshLod lod, + CMeshVertex vert1, + CMeshVertex vert2, + CMeshVertex vert3, + int[] indices + ) + { + return PrepareUVsAndTexCoords( + lod.VertexColors ?? new FColor[lod.NumVerts], + vert1, + vert2, + vert3, + lod.ExtraUV.Value, + indices + ); + } + + public static ( + VertexColorXTextureX, + VertexColorXTextureX, + VertexColorXTextureX + ) PrepareUVsAndTexCoords( + FColor[] colors, + CMeshVertex vert1, + CMeshVertex vert2, + CMeshVertex vert3, + FMeshUVFloat[][] uvs, + int[] indices + ) + { + var (uvs1, uvs2, uvs3) = PrepareUVs(vert1, vert2, vert3, uvs, indices); + var c1 = new VertexColorXTextureX((Vector4)colors[indices[0]] / 255, uvs1); + var c2 = new VertexColorXTextureX((Vector4)colors[indices[1]] / 255, uvs2); + var c3 = new VertexColorXTextureX((Vector4)colors[indices[2]] / 255, uvs3); + return (c1, c2, c3); + } + + private static (List, List, List) PrepareUVs( + CMeshVertex vert1, + CMeshVertex vert2, + CMeshVertex vert3, + FMeshUVFloat[][] uvs, + int[] indices + ) + { + var uvs1 = new List() { vert1.UV }; + var uvs2 = new List() { vert2.UV }; + var uvs3 = new List() { vert3.UV }; + foreach (var uv in uvs) + { + uvs1.Add(uv[indices[0]]); + uvs2.Add(uv[indices[1]]); + uvs3.Add(uv[indices[2]]); + } + + return (uvs1, uvs2, uvs3); + } + } +}