acdream/src/AcDream.Core/World/MeshRef.cs
Erik 749e8ceeb1 fix(rendering): bound portal resource lifetime
Separate logical ownership, render publication, and GPU retirement across live entities, landblocks, particles, textures, mesh arenas, portal/UI teardown, and per-frame scratch storage. Add bounded DAT/texture caches, upload budgets, three-frame fence retirement, exact-incarnation appearance reconciliation, frame pacing, and extensive lifetime conformance coverage.\n\nThe seven-destination connected route now cuts peak working/private memory roughly in half, returns Caul to 125-153 FPS locally, and produces no WER or AMD reset.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>
2026-07-18 21:35:16 +02:00

38 lines
1.7 KiB
C#

using System.Numerics;
namespace AcDream.Core.World;
/// <summary>
/// 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 (<see cref="SurfaceOverrides"/>) so the renderer can
/// substitute textures at draw time without having to change the base
/// <c>Setup</c> / <c>GfxObj</c> 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.
/// </summary>
public readonly record struct MeshRef(uint GfxObjId, Matrix4x4 PartTransform)
{
/// <summary>
/// <para>
/// <b>Surface id (0x08XXXXXX)</b> → <b>replacement OrigTextureId
/// (0x05XXXXXX SurfaceTexture)</b>. 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
/// <c>OrigTextureId</c> for the value here." The renderer calls
/// the owning renderer resolves an owner-scoped composite. Equivalent
/// live entities may share it, and the final owner releases it.
/// </para>
/// <para>
/// Null means "no overrides, use each sub-mesh's native surface as-is."
/// </para>
/// <para>
/// <b>Why not key by SurfaceTexture id directly?</b> 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.
/// </para>
/// </summary>
public IReadOnlyDictionary<uint, uint>? SurfaceOverrides { get; init; }
}