using System.Numerics; namespace AcDream.Core.World; /// /// One part of a mesh: a GfxObj id + its local transform in the owning /// entity's frame. Optionally carries a set of server-specified surface /// overrides () so the renderer can /// substitute textures at draw time without having to change the base /// Setup / GfxObj dat lookup — e.g. the Nullified Statue of /// a Drudge remaps the drudge mesh's flesh textures to stone textures /// and characters remap their armor piece textures to match the clothing /// item they're wearing. /// public readonly record struct MeshRef(uint GfxObjId, Matrix4x4 PartTransform) { /// /// /// Surface id (0x08XXXXXX)replacement OrigTextureId /// (0x05XXXXXX SurfaceTexture). When the renderer is about to /// bind a sub-mesh's texture, it consults this map. A hit means /// "use the base Surface's colors/flags/palette but swap its /// OrigTextureId for the value here." The renderer calls /// TextureCache.GetOrUploadWithOrigTextureOverride which caches /// the decoded result under a composite key so multiple entities can /// share the same override without redecoding. /// /// /// Null means "no overrides, use each sub-mesh's native surface as-is." /// /// /// Why not key by SurfaceTexture id directly? Because sub-meshes /// are keyed by Surface id (0x08) in the GfxObj; we have to resolve /// each one to its SurfaceTexture id at hydration time so the render /// hot path only does a single dict lookup. /// /// public IReadOnlyDictionary? SurfaceOverrides { get; init; } }