using System.Collections.Generic; using System.IO; using Godot; 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 materials = new List(); foreach (var material in modelFile.Materials) { if (material.Type == 0) { var paths = Directory.GetFiles(baseDir, material.Name, options); if (paths.IsEmpty()) continue; materials.Add(new StandardMaterial3D { AlbedoTexture = TextureLoader.LoadTexture(paths[0]) }); } else { var b = (material.Handle) & 0xff; var g = (material.Handle >> 8) & 0xff; var r = (material.Handle >> 16) & 0xff; GD.Print($"Handle: {material.Handle}, R: {r}, G: {g}, B: {b}"); var colour = new Color(r / 255.0f, g / 255.0f, b / 255.0f, 1.0f); materials.Add(new StandardMaterial3D { AlbedoColor = colour }); } } var mesh = new ArrayMesh(); 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 { uvs.Add(Vector2.Zero); } } var surfaceData = new MeshSurfaceData(); surfaceData.AddPolygon(vertices, normal, uvs, uvs); var array = surfaceData.BuildSurfaceArray(); mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, array); for (var i = 0; i < materials.Count; i++) { var m = modelFile.Materials[i]; if (m.Slot == poly.Data) { mesh.SurfaceSetMaterial(poly.Index, materials[i]); break; } } } var meshInstance = new MeshInstance3D { Mesh = mesh }; AddChild(meshInstance); } }