3.1 KiB
Issue #178 — retail EnvCell shell culling (2026-08-28)
Outcome
The Phase A8 CullMode.Landblock -> CullMode.None workaround is removed
from both production EnvCell draw paths. Constructed cell-shell batches now
use retail's clockwise cull state instead of drawing every ordinary shell
face twice. No PAK rebuild is required: the package already contains the
authored sides_type and the correctly expanded index geometry; this change
selects the correct GPU state when that geometry is drawn.
The source and installed-DAT gates are complete. The owner visual gate passed 2026-08-28 (“Ok looks good”) at the requested interior matrix; #178 is closed.
Retail oracle
The misleading detail is that DatReaderWriter.Enums.CullMode is used for
the CellStruct polygon's sides_type; its values are not direct GPU cull
states.
D3DPolyRender::ConstructMesh @ 0x0059DFA0expandssides_type0 as the positive face, type 1 as that face plus a reversed copy, and type 2 as the positive and negative surfaces. Its polygon fan is[0, i-1, i]; the reversed copy is[i, i-1, 0].D3DPolyRender::RenderMeshSubset @ 0x0059CA10draws the constructed mesh withD3DCULL_CWon the ordinary path.RenderDeviceD3D::DrawEnvCell @ 0x0059F170uses that constructed-mesh route. The immediate-mode exception for a type-1 polygon does not apply to the EnvCell mesh.
MeshExtractor.PrepareCellStructMeshData already reproduces retail's fan and
the required reversed geometry. The render policy therefore must be
clockwise culling for every constructed shell batch; mapping DAT value 0 to
None was the obsolete workaround, while mapping it to the generic
Landblock render state would cull the opposite side.
Installed-DAT catalog
A8CellAudit cell-winding-catalog scanned the installed DATs:
- 772 environments and 3,168 CellStructs
- 38,189 polygons and 70,091 generated fan triangles
- 37,843
Landblock(0)polygons and 346None(1)polygons - no unknown or unsupported
sides_typevalues - no missing polygon vertices
Vertex-normal orientation was recorded as a diagnostic, not treated as a contract: CellStruct vertex normals may be smoothed rather than geometric, and retail submits the identical authored fan.
Implementation and gates
EnvCellRenderer.ResolveRetailCellShellCullModedocuments and enforces the constructed-mesh policy in both the main and shadow-receiver draw paths.- Hermetic extraction tests pin the exact type-0 fan and type-1 reversed-face expansion.
- Renderer tests pin all four source enum values to the retail clockwise constructed-mesh state.
- Installed-DAT audit: passed.
- Canonical Release gate: 16,321 passed, 0 skipped, 0 failed across 14 test assemblies; Release build completed with 0 warnings and 0 errors.
Owner visual acceptance
In Holtburg buildings and the Facility Hub, rotate the camera through walls, floors, ceilings, ramps, and stairs from their ordinary playable sides. Nothing should vanish at any camera angle. Acceptance of that matrix closes #178. The owner accepted this matrix on 2026-08-28 (“Ok looks good”).