Formats/Fbx/FbxMaterialColor.cs
#nullable enable annotations
using System;
using System.Linq;
namespace HumanoidHandRetargeter.Formats.Fbx;
using Vector3 = System.Numerics.Vector3;
/// <summary>Authored FBX colors, independent of material and texture names.</summary>
public static class FbxMaterialColor
{
public static Vector3? Read(FbxNode material)
{
var properties = material.Child("Properties70")?.Children;
var color = properties?.FirstOrDefault(p => p.Properties.FirstOrDefault() is "DiffuseColor")
?? properties?.FirstOrDefault(p => p.Properties.FirstOrDefault() is "Diffuse");
if (color is null || color.Properties.Count < 7)
return null;
var value = new Vector3(color.Prop<float>(4), color.Prop<float>(5), color.Prop<float>(6));
// The legacy Diffuse property already includes DiffuseFactor.
var factor = properties?.FirstOrDefault(p => p.Properties.FirstOrDefault() is "DiffuseFactor");
if (color.Properties[0] is "DiffuseColor" && factor?.Properties.Count >= 5)
value *= factor.Prop<float>(4);
return float.IsFinite(value.X) && float.IsFinite(value.Y) && float.IsFinite(value.Z)
? Vector3.Clamp(value, Vector3.Zero, Vector3.One) : null;
}
public static bool HasVertexColors(FbxNode geometry)
=> geometry.ChildrenNamed("LayerElementColor").Any(layer =>
layer.Child("Colors")?.Properties.FirstOrDefault() is double[] colors
&& colors.Where((_, i) => i % 4 != 3).Any(c => Math.Abs(c - 1) > 1e-6));
}