Code/HumanoidRetargeter/Core/Formats/Fbx/FbxMeshParts.cs

Utility class that parses FBX tokenized data to find names of mesh model instances that can be imported separately. It walks FBX node tree to identify Geometry nodes, finds connected Model nodes referencing those geometries, extracts their names, normalizes by splitting names, filters empties, and returns distinct names.

File Access
#nullable enable annotations

using System;
using System.Collections.Generic;
using System.Linq;

namespace HumanoidRetargeter.Core.Formats.Fbx;

/// <summary>Names of mesh instances that ModelDoc can import independently.</summary>
public static class FbxMeshParts
{
    public static IReadOnlyList<string> ReadNames(byte[] data)
    {
        var root = FbxTokenizer.Parse(data);
        var objects = root.Child("Objects");
        var connections = root.Child("Connections");
        if (objects is null || connections is null)
            return Array.Empty<string>();

        var geometries = objects.Children
            .Where(n => n.Name == "Geometry" && n.Properties.Count > 0
                && n.Properties[0] is long or int)
            .Select(n => n.Prop<long>(0)).ToHashSet();
        var models = connections.ChildrenNamed("C")
            .Where(n => n.Properties.Count >= 3 && n.Properties[0] is "OO"
                && n.Properties[1] is long or int && n.Properties[2] is long or int
                && geometries.Contains(n.Prop<long>(1)))
            .Select(n => n.Prop<long>(2)).ToHashSet();
        return objects.Children
            .Where(n => n.Name == "Model" && n.Properties.Count >= 2
                && n.Properties[0] is long or int && n.Properties[1] is string
                && models.Contains(n.Prop<long>(0)))
            .Select(n => FbxNode.SplitName(n.Prop<string>(1)).Name)
            .Where(n => !string.IsNullOrWhiteSpace(n))
            .Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
    }
}