using System.Numerics; using MshLib; namespace NResUI.Rendering.Inspection; /// /// CPU-документ меша: общая модель данных для viewport и inspector до загрузки в OpenGL. /// Здесь хранятся ссылки на исходные MSH-компоненты и уже удобные для UI metadata. /// public sealed class MeshDocument { /// Путь к MSH/NRes ресурсу, из которого построен документ. public required string SourcePath { get; init; } /// Тип MSH по набору компонентов. Сейчас inspector поддерживает только обычный Model. public required MshType MeshType { get; init; } /// Список pieces из 0x01. Каждый piece сам выбирает slot для state/LOD. public IReadOnlyList Pieces { get; init; } = []; /// Материалы, пришедшие из WEA. Текстуры резолвятся отдельно, потому что это уже UI/OpenGL слой. public IReadOnlyList Materials { get; init; } = []; /// Нефатальные проблемы загрузки: отсутствующие optional-компоненты, WEA/material/texture misses. public IReadOnlyList Warnings { get; init; } = []; /// Количество известных model states в 0x01 таблице. public int ModelStateCount { get; init; } = Msh0x01.StateCount; /// Количество LOD-уровней на каждый state в 0x01 таблице. public int LodCount { get; init; } = Msh0x01.MaxLodCount; /// Сырые MSH-потоки, нужные для перестройки GPU-мешей при смене state/LOD. public MshModelGeometry? MshModelGeometry { get; init; } } /// /// Информация об одном piece/node из 0x01. /// Важно: state/LOD не глобальны, поэтому этот объект хранит собственную slot-таблицу. /// public sealed class MeshPieceInfo { public required int Id { get; init; } public required string Name { get; init; } public required int ParentId { get; init; } public required NodeFlags Flags { get; init; } public required IReadOnlyList GeometrySlotsByStateAndLod { get; init; } public required IReadOnlyList Batches { get; init; } public required Matrix4x4 LocalTransform { get; init; } public required Matrix4x4 MeshSpaceTransform { get; init; } public required Vector3 BoundsMin { get; init; } public required Vector3 BoundsMax { get; init; } public int FallbackKeyframeIndex { get; init; } = -1; public bool HasRestPose { get; init; } /// /// Возвращает geometry slot 0x02 для пары state/LOD именно этого piece. /// 0xFFFF означает, что piece в такой комбинации не должен рендериться. /// public ushort ResolveSlotIndex(int state, int lod) { var index = state * Msh0x01.MaxLodCount + lod; return index >= 0 && index < GeometrySlotsByStateAndLod.Count ? GeometrySlotsByStateAndLod[index] : ushort.MaxValue; } } /// /// Inspector metadata для batch 0x0D. Геометрия остается в MshModelGeometry, здесь только диапазоны и флаги. /// public sealed class MeshBatchInfo { public required int BatchIndex { get; init; } public required int MaterialId { get; init; } public string? MaterialName { get; init; } public required BatchFlags Flags { get; init; } public required uint IndexStart { get; init; } public required int IndexCount { get; init; } public required uint BaseVertex { get; init; } public required int VertexCount { get; init; } public required int TriangleCount { get; init; } public IReadOnlyList Warnings { get; init; } = []; } /// Материал из WEA по id. Это еще не ViewportMaterial и не OpenGL texture. public sealed class MeshMaterialInfo { public required int Id { get; init; } public required string Name { get; init; } public string? TextureName { get; init; } public bool HasTexture => TextureName != null; }