namespace Sandbox.Services; /// /// Extracted metadata for a model package. Shared DTO (website + game engine). /// public class ModelMetaData : BaseMetaData { /// Per-LOD stats, LOD0 (full detail) first. public List Lods { get; set; } = new(); public int Meshes { get; set; } public int Bones { get; set; } public int Animations { get; set; } public int Hitboxes { get; set; } public int BodyGroups { get; set; } public int MaterialGroups { get; set; } /// Compiler's total pool-size hint - a rough memory footprint for the model. public int MemorySize { get; set; } /// Whether the model ships a physics/collision mesh (embedded or referenced). public bool HasCollision { get; set; } /// Distinct material paths used by the model. public List Materials { get; set; } = new(); /// Model bounds, stored as a "x,y,z" string. Use to convert. public string BoundsMin { get; set; } /// public string BoundsMax { get; set; } public class LodInfo { public long Triangles { get; set; } public long DrawCalls { get; set; } } public override void GetAutoTags( HashSet tags ) { SetTag( tags, "haslods", Lods.Count > 1 ); SetTag( tags, "hascollision", HasCollision ); SetTag( tags, "hasbones", Bones > 0 ); SetTag( tags, "hasanims", Animations > 0 ); SetTag( tags, "hashitboxes", Hitboxes > 0 ); } const int SizeCategory = 49; const int SizeTiny = 50, SizeSmall = 51, SizeMedium = 52, SizeLarge = 53, SizeHuge = 54, SizeMassive = 55; const int TriangleCategory = 227; const int TriLow = 228, TriMedium = 229, TriHigh = 230, TriVeryHigh = 231; static readonly int[] ManagedCategories = { SizeCategory, SizeTiny, SizeSmall, SizeMedium, SizeLarge, SizeHuge, SizeMassive, TriangleCategory, TriLow, TriMedium, TriHigh, TriVeryHigh, }; public override void UpdateCategories( List categories ) { // Drop any buckets we own so a re-index never leaves a stale one behind. categories.RemoveAll( id => ManagedCategories.Contains( id ) ); var triangles = Lods.FirstOrDefault()?.Triangles ?? 0; int? tri = triangles switch { <= 0 => null, < 1_000 => TriLow, < 10_000 => TriMedium, < 50_000 => TriHigh, _ => TriVeryHigh, }; if ( tri is not null ) { categories.Add( TriangleCategory ); categories.Add( tri.Value ); } // Physical size bucket from the largest bounding-box dimension (units). var min = BoundsMin.ToMetaVector(); var max = BoundsMax.ToMetaVector(); var size = MathF.Max( MathF.Max( max.X - min.X, max.Y - min.Y ), max.Z - min.Z ); int? sizeBucket = size switch { <= 0f => null, < 16f => SizeTiny, < 64f => SizeSmall, < 256f => SizeMedium, < 1024f => SizeLarge, < 4096f => SizeHuge, _ => SizeMassive, }; if ( sizeBucket is not null ) { categories.Add( SizeCategory ); categories.Add( sizeBucket.Value ); } } }