Cockpit: the authentic punch STENCIL-CUT -- all 8 cockpits real (task #55)
The user caught the inversion (blocked viewports, see-through frames); the
answer came from the rasterizer board itself: an i860 disassembly of the
VREND.MNG firmware decoded the damageize handler (@0xf040f6f8) -- cmd 0x20
(vr_damage_action) writes the dpl_Punchize token triple onto the punch
geogroup's first three geometry chunks IN FILE ORDER:
chunk1 = the detailed window-aperture shapes -> an invisible per-pixel MASK
chunk2 = the coarse hull -> the ONLY colour-drawn geometry (where not masked)
chunk3 = byte-identical hull twin -> the damage-reset record, never visible
Visible canopy = hull-minus-apertures. Both earlier readings were wrong ways
around the same three chunks: dropping all punch left floating fragments (no
hull); hiding the duplicate pair hid the HULL and drew the MASK -- the exact
inversion observed.
Port: bgfload tags per punch patch {non-paired pmesh = mask (role 1),
first twin = hull (role 2), second twin = skip}; L4D3D DrawMesh runs
mask->stencil-1 (no colour/z-write, z-tested), hull->stencil-NOTEQUAL,
mask->stencil-0; device D24X8 -> D24S8 + stencil clear. The cut never
touches z, so later-drawn entities show through the apertures.
BT_COP_PLATES=1 disables (diag).
In-game, all 8 mechs on pure defaults: connected dark frames with clear
viewports -- thor (the footage mech) shows the central viewport + surrounding
frame exactly as filmed. Combat regression clean (kill + no NaN).
Arena textured punch uses the same firmware kit; the black-texel alpha path
there is a working approximation, flagged in the KB.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
8431e69b1a
commit
96b8892e7c
@@ -200,6 +200,7 @@ d3d_OBJECT *d3d_OBJECT::LoadObject(LPDIRECT3DDEVICE9 device, char *fileName)
|
||||
}
|
||||
|
||||
object->mDrawOps[i].drawAsSky = isSky;
|
||||
object->mDrawOps[i].copRole = 0;
|
||||
|
||||
if (isSky)
|
||||
{
|
||||
@@ -430,6 +431,7 @@ d3d_OBJECT* d3d_OBJECT::LoadObjectBGF(LPDIRECT3DDEVICE9 device, char *fileName)
|
||||
static int s_punch = -1;
|
||||
if (s_punch < 0) { const char *pv = getenv("BT_PUNCH"); s_punch = (pv == 0 || pv[0] != '0') ? 1 : 0; }
|
||||
object->mDrawOps[i].punchThrough = (s_punch && data.batches[i].punch);
|
||||
object->mDrawOps[i].copRole = data.batches[i].copRole; // punch stencil-cut kit (task #55)
|
||||
object->mDrawOps[i].texture.texture = NULL;
|
||||
object->mDrawOps[i].texture.wrap_u = L4TEXOP::REPEAT;
|
||||
object->mDrawOps[i].texture.wrap_v = L4TEXOP::REPEAT;
|
||||
@@ -1112,6 +1114,11 @@ void d3d_OBJECT::DrawMesh(int pass, const D3DXMATRIX *viewTransform, Time target
|
||||
{
|
||||
L4DRAWOP *drawOp = &mDrawOps[iOp];
|
||||
|
||||
// COCKPIT PUNCH KIT (task #55): aperture-MASK ops never draw colour --
|
||||
// they are consumed by the FOLLOWING hull op's stencil-cut sequence.
|
||||
if (drawOp->copRole == 1)
|
||||
continue;
|
||||
|
||||
if (drawOp->alphaTest != (pass == PASS_ALPHABLEND))
|
||||
continue;
|
||||
|
||||
@@ -1189,7 +1196,57 @@ void d3d_OBJECT::DrawMesh(int pass, const D3DXMATRIX *viewTransform, Time target
|
||||
}
|
||||
|
||||
gNumBatches++;
|
||||
if (drawOp->bgfPrimCount > 0 && mBgfVB != NULL)
|
||||
// COCKPIT PUNCH STENCIL-CUT (task #55, the i860 'damageize' mechanism):
|
||||
// a role-2 HULL op is preceded by its role-1 aperture-MASK op. Sequence:
|
||||
// 1. draw the mask stencil-only (no colour, no z-write, z-TESTED) -> ref 1
|
||||
// 2. draw the hull with stencil-reject where ref==1 (the window cutouts)
|
||||
// 3. re-draw the mask writing stencil 0 (clean up for other punch groups)
|
||||
// The stencil never touches z, so entities drawn later still show through
|
||||
// the apertures correctly.
|
||||
const bool copCut = (drawOp->copRole == 2 && iOp > 0
|
||||
&& mDrawOps[iOp - 1].copRole == 1
|
||||
&& mDrawOps[iOp - 1].bgfPrimCount > 0
|
||||
&& drawOp->bgfPrimCount > 0 && mBgfVB != NULL);
|
||||
if (copCut)
|
||||
{
|
||||
L4DRAWOP *maskOp = &mDrawOps[iOp - 1];
|
||||
mDevice->SetFVF(L4VERTEX_FVF);
|
||||
mDevice->SetStreamSource(0, mBgfVB, 0, mBgfStride);
|
||||
mDevice->SetIndices(mBgfIB);
|
||||
// 1. mask -> stencil ref 1 (colour + z-write off)
|
||||
mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
|
||||
mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
||||
mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
|
||||
mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
|
||||
mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
|
||||
mDevice->SetRenderState(D3DRS_STENCILREF, 1);
|
||||
mDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, mBgfNumVerts,
|
||||
maskOp->bgfStartIndex, maskOp->bgfPrimCount);
|
||||
// 2. hull, stencil-rejected under the mask
|
||||
mDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
|
||||
D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN |
|
||||
D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA);
|
||||
mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
|
||||
mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_NOTEQUAL);
|
||||
mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
|
||||
mDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, mBgfNumVerts,
|
||||
drawOp->bgfStartIndex, drawOp->bgfPrimCount);
|
||||
// 3. mask again -> stencil ref 0 (clean)
|
||||
mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
|
||||
mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
||||
mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
|
||||
mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
|
||||
mDevice->SetRenderState(D3DRS_STENCILREF, 0);
|
||||
mDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, mBgfNumVerts,
|
||||
maskOp->bgfStartIndex, maskOp->bgfPrimCount);
|
||||
// restore
|
||||
mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
|
||||
mDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
|
||||
D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN |
|
||||
D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA);
|
||||
mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
|
||||
}
|
||||
else if (drawOp->bgfPrimCount > 0 && mBgfVB != NULL)
|
||||
{
|
||||
// direct-draw: known contiguous range, no attribute-table scan.
|
||||
// (DrawSubset used to set the vertex decl itself -- assert the FVF here
|
||||
|
||||
Reference in New Issue
Block a user