using System; using System.Collections.Generic; using System.IO; using Godot; using Godot.Collections; using KeepersCompound.LGS; using KeepersCompound.TMV.UI; namespace KeepersCompound.TMV; public partial class Model : Node3D { public override void _Ready() { var modelSelector = GetNode("%ModelSelector") as ModelSelector; modelSelector.LoadModel += BuildModel; } private void BuildModel(string rootPath, string modelPath) { foreach (var node in GetChildren()) { node.QueueFree(); } var modelFile = new ModelFile(modelPath); if (modelFile == null) { GD.Print($"Failed to load model file: {modelPath}"); return; } // TODO: Remove this disgusting hack var baseDir = ProjectSettings.GlobalizePath($"user://objects/tmp"); var options = new EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive, RecurseSubdirectories = true, }; var textures = new List(); foreach (var material in modelFile.Materials) { var paths = Directory.GetFiles(baseDir, material.Name, options); if (paths.IsEmpty()) continue; var texture = TextureLoader.LoadTexture(paths[0]); var saveName = material.Name.GetBaseName() + ".png"; texture.GetImage().SavePng(ProjectSettings.GlobalizePath($"user://debug/{saveName}")); textures.Add(texture); } var mat = new StandardMaterial3D { AlbedoTexture = textures[0] }; // TODO: Support multiple materials and colour based materials var surfaceData = new MeshSurfaceData(); foreach (var poly in modelFile.Polygons) { var vertices = new List(); var normal = modelFile.Normals[poly.Normal].ToGodotVec3(); var uvs = new List(); for (var i = 0; i < poly.VertexCount; i++) { var vertex = modelFile.Vertices[poly.VertexIndices[i]]; vertices.Add(vertex.ToGodotVec3()); if (i < poly.UvIndices.Length) { var uv = modelFile.Uvs[poly.UvIndices[i]]; uvs.Add(new Vector2(uv.X, uv.Y)); } else { var uv = (i % 4) switch { 0 => new Vector2(0, 0), 1 => new Vector2(0, 1), 2 => new Vector2(1, 0), 3 => new Vector2(1, 1), _ => throw new NotImplementedException(), }; uvs.Add(uv); } } surfaceData.AddPolygon(vertices, normal, uvs, uvs); } var array = surfaceData.BuildSurfaceArray(); var mesh = new ArrayMesh(); mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, array); mesh.SurfaceSetMaterial(0, mat); var meshInstance = new MeshInstance3D { Mesh = mesh }; AddChild(meshInstance); } }