feat(render): IndoorDrawPlan.ShellPass — every visible cell, no drawable filter (R1)

Pure port of retail DrawCells membership: reverse cell_draw_list, per-slice. Pins the
grey regression — a cell in OrderedVisibleCells is never dropped from the shell pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-06 21:59:26 +02:00
parent 2ec8f41200
commit bff1955066
2 changed files with 76 additions and 0 deletions

View file

@ -0,0 +1,30 @@
// IndoorDrawPlan.cs
//
// Pure (GL-free) port of the membership half of retail PView::DrawCells (0x5a4840):
// the reverse cell_draw_list iterated per portal_view slice. EVERY visible cell with a
// non-empty view is included — there is NO "drawable" filter. Dropping cells without a
// clip-slot was the grey-walls bug (the cell's sealed shell never drew → clear color showed).
using System.Collections.Generic;
namespace AcDream.App.Rendering;
public readonly record struct CellDrawEntry(uint CellId, IReadOnlyList<ViewPolygon> Slices);
public static class IndoorDrawPlan
{
/// <summary>Reverse OrderedVisibleCells (far→near), each visible cell with its view
/// slices. Mirrors DrawCells' shell/object loops. Cells whose view is empty are skipped
/// (they are not actually visible); no other cell is ever dropped.</summary>
public static List<CellDrawEntry> ShellPass(PortalVisibilityFrame frame)
{
var result = new List<CellDrawEntry>(frame.OrderedVisibleCells.Count);
for (int i = frame.OrderedVisibleCells.Count - 1; i >= 0; i--)
{
uint cellId = frame.OrderedVisibleCells[i];
if (!frame.CellViews.TryGetValue(cellId, out var view) || view.IsEmpty)
continue;
result.Add(new CellDrawEntry(cellId, view.Polygons));
}
return result;
}
}