Extract model loading functionality out
This commit is contained in:
		
							parent
							
								
									e313ca58a7
								
							
						
					
					
						commit
						b6a65fc10b
					
				| 
						 | 
				
			
			@ -164,23 +164,18 @@ public partial class Mission : Node3D
 | 
			
		|||
 | 
			
		||||
			// Let's try and place an object :)
 | 
			
		||||
			var modelName = modelNameProp.modelName + ".bin";
 | 
			
		||||
			var objPath = _installPaths.GetObjectPath(_campaignName, modelName);
 | 
			
		||||
 | 
			
		||||
			var pos = brush.position.ToGodotVec3();
 | 
			
		||||
			var rawRot = brush.angle;
 | 
			
		||||
			var rot = new Vector3(rawRot.Y, rawRot.Z, rawRot.X) * 360 / ushort.MaxValue;
 | 
			
		||||
			var scale = scaleProp == null ? Vector3.One : scaleProp.scale.ToGodotVec3(false);
 | 
			
		||||
			var model = new Model
 | 
			
		||||
			var model = ModelLoader.LoadModel(_installPaths, _campaignName, modelName);
 | 
			
		||||
			if (model != null)
 | 
			
		||||
			{
 | 
			
		||||
				Position = pos,
 | 
			
		||||
				RotationDegrees = rot,
 | 
			
		||||
				Scale = scale,
 | 
			
		||||
			};
 | 
			
		||||
			if (objPath != null)
 | 
			
		||||
			{
 | 
			
		||||
				model.BuildModel("", objPath);
 | 
			
		||||
				model.Position = pos;
 | 
			
		||||
				model.RotationDegrees = rot;
 | 
			
		||||
				model.Scale = scale;
 | 
			
		||||
				AddChild(model);
 | 
			
		||||
			}
 | 
			
		||||
			AddChild(model);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,107 @@
 | 
			
		|||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using Godot;
 | 
			
		||||
using KeepersCompound.LGS;
 | 
			
		||||
 | 
			
		||||
namespace KeepersCompound.TMV;
 | 
			
		||||
 | 
			
		||||
public static class ModelLoader
 | 
			
		||||
{
 | 
			
		||||
    public static MeshInstance3D LoadModel(ResourcePathManager pathManager, string campaignName, string modelName)
 | 
			
		||||
    {
 | 
			
		||||
        var modelPath = pathManager.GetObjectPath(campaignName, modelName);
 | 
			
		||||
        if (modelPath == null)
 | 
			
		||||
        {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        var modelFile = new ModelFile(modelPath);
 | 
			
		||||
        if (modelFile == null)
 | 
			
		||||
        {
 | 
			
		||||
            GD.Print($"Failed to load model file: {modelPath}");
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // TODO: Remove this disgusting hack. Not only is it a hack, it doesn't support custom models
 | 
			
		||||
        var baseDir = Path.GetDirectoryName(modelPath);
 | 
			
		||||
        var options = new EnumerationOptions
 | 
			
		||||
        {
 | 
			
		||||
            MatchCasing = MatchCasing.CaseInsensitive,
 | 
			
		||||
            RecurseSubdirectories = true,
 | 
			
		||||
        };
 | 
			
		||||
        var materials = new List<StandardMaterial3D>();
 | 
			
		||||
        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;
 | 
			
		||||
                var colour = new Color(r / 255.0f, g / 255.0f, b / 255.0f, 1.0f);
 | 
			
		||||
                materials.Add(new StandardMaterial3D
 | 
			
		||||
                {
 | 
			
		||||
                    AlbedoColor = colour
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var surfaceDataMap = new Dictionary<int, MeshSurfaceData>();
 | 
			
		||||
        foreach (var poly in modelFile.Polygons)
 | 
			
		||||
        {
 | 
			
		||||
            var vertices = new List<Vector3>();
 | 
			
		||||
            var normal = modelFile.Normals[poly.Normal].ToGodotVec3();
 | 
			
		||||
            var uvs = new List<Vector2>();
 | 
			
		||||
            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);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!surfaceDataMap.ContainsKey(poly.Data))
 | 
			
		||||
            {
 | 
			
		||||
                surfaceDataMap.Add(poly.Data, new MeshSurfaceData());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            surfaceDataMap[poly.Data].AddPolygon(vertices, normal, uvs, uvs);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var mesh = new ArrayMesh();
 | 
			
		||||
        foreach (var (materialId, surfaceData) in surfaceDataMap)
 | 
			
		||||
        {
 | 
			
		||||
            var array = surfaceData.BuildSurfaceArray();
 | 
			
		||||
            var surfaceIdx = mesh.GetSurfaceCount();
 | 
			
		||||
            mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, array);
 | 
			
		||||
            for (var i = 0; i < materials.Count; i++)
 | 
			
		||||
            {
 | 
			
		||||
                var m = modelFile.Materials[i];
 | 
			
		||||
                if (m.Slot == materialId)
 | 
			
		||||
                {
 | 
			
		||||
                    mesh.SurfaceSetMaterial(surfaceIdx, materials[i]);
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var pos = -modelFile.Header.Center.ToGodotVec3();
 | 
			
		||||
        var meshInstance = new MeshInstance3D { Mesh = mesh, Position = pos };
 | 
			
		||||
        return meshInstance;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue