Editor/Core/Import/ObjMaterials.cs
#nullable enable annotations
namespace HumanoidRigger;
using Vector3=System.Numerics.Vector3;
internal static class ObjMaterials
{
public static IEnumerable<SourceMaterial> Read(string path)
{
SourceMaterial? current=null;
foreach(string line in File.ReadLines(path))
{
var words=ObjImporter.Words(line.Split('#')[0]);if(words.Length==0)continue;
if(words[0]=="newmtl"){if(current is not null)yield return current;current=new(){Name=string.Join(" ",words.Skip(1)),DoubleSided=true};continue;}
if(current is null)continue;
switch(words[0])
{
case "Kd":if(words.Length>=4)current.ColorFactor=new Vector3(ObjImporter.Number(words[1]),ObjImporter.Number(words[2]),ObjImporter.Number(words[3]));break;
case "d":case "Tr":
if(words.Length>=2){float alpha=ObjImporter.Number(words[^1]);current.OpacityFactor=Math.Clamp(words[0]=="Tr"?1-alpha:alpha,0,1);current.Translucent=current.OpacityFactor<.999f;}break;
case "map_Kd":current.ColorTexture=Texture();break;
case "map_Bump":case "map_bump":case "bump":case "norm":current.NormalTexture=Texture();break;
case "map_Pr":current.RoughnessTexture=Texture();break;
case "map_Pm":current.MetalnessTexture=Texture();break;
case "map_Ke":current.EmissiveTexture=Texture();break;
case "map_d":current.OpacityTexture=Texture();current.Translucent=true;break;
}
string Texture()
{
int i=1;
while(i<words.Length&&words[i].StartsWith('-'))
{
string option=words[i++];int count=option is "-s" or "-o" or "-t"?3:option=="-mm"?2:1;
for(int n=0;n<count&&i<words.Length;n++)
{if(option is "-s" or "-o" or "-t"&&!float.TryParse(words[i],System.Globalization.NumberStyles.Float,System.Globalization.CultureInfo.InvariantCulture,out _))break;i++;}
}
if(i>=words.Length)throw new FormatException("MTL texture has no filename.");
return ModelImporter.DependencyPath(path,string.Join(" ",words.Skip(i)).Trim('"'));
}
}
if(current is not null)yield return current;
}
}