Files
doom-dm/Engine/Asset/Mesh/Loader/ObjMeshLoader.cs
2024-12-04 22:35:04 +03:00

90 lines
3.3 KiB
C#

using System.Globalization;
using OpenTK.Mathematics;
namespace Engine.Asset.Mesh.Loader;
public class ObjMeshLoader : IMeshLoader
{
private static readonly ObjMeshLoader Instance = new();
public static Mesh Load(string path, MeshLoaderParameters parameters = MeshLoaderParameters.Default)
=> Instance.LoadMesh(path, parameters);
public Mesh LoadMesh(string path, MeshLoaderParameters parameters = MeshLoaderParameters.Default)
{
var mesh = new Mesh();
var tempVertices = new List<Vector3>();
var tempNormals = new List<Vector3>();
var tempUVs = new List<Vector2>();
var index = 0u;
var loadNormals = parameters.HasFlag(MeshLoaderParameters.LoadNormals);
var loadUVs = parameters.HasFlag(MeshLoaderParameters.LoadUVs);
using var reader = new StreamReader(path);
while (reader.ReadLine() is { } line)
{
var parts = line.Split(' ', StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 0 || parts[0].StartsWith('#'))
continue;
switch (parts[0])
{
case "v":
tempVertices.Add(new Vector3(
float.Parse(parts[1], CultureInfo.InvariantCulture),
float.Parse(parts[2], CultureInfo.InvariantCulture),
float.Parse(parts[3], CultureInfo.InvariantCulture)
));
break;
case "vt" when loadUVs:
tempUVs.Add(new Vector2(
float.Parse(parts[1], CultureInfo.InvariantCulture),
float.Parse(parts[2], CultureInfo.InvariantCulture)
));
break;
case "vn" when loadNormals:
tempNormals.Add(new Vector3(
float.Parse(parts[1], CultureInfo.InvariantCulture),
float.Parse(parts[2], CultureInfo.InvariantCulture),
float.Parse(parts[3], CultureInfo.InvariantCulture)
));
break;
case "f":
for (var i = 1; i <= 3; i++)
{
var faceComponents = parts[i].Split('/');
var meshVertex = new Mesh.Vertex
{
Position = tempVertices[int.Parse(faceComponents[0]) - 1]
};
if (loadUVs && faceComponents.Length > 1 && faceComponents[1] != "")
{
meshVertex.Uv = tempUVs[int.Parse(faceComponents[1]) - 1];
}
if (loadNormals && faceComponents.Length > 2 && faceComponents[2] != "")
{
meshVertex.Normal = tempNormals[int.Parse(faceComponents[2]) - 1];
}
mesh.VerticesInternal.Add(meshVertex);
mesh.IndicesInternal.Add(index++);
}
break;
}
}
if (parameters.HasFlag(MeshLoaderParameters.Optimize))
mesh = IMeshLoader.Optimize(mesh);
return mesh;
}
}