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