Cockpit: authentic eyepoint + canopy lattice render (task #55)
The first-person cockpit now shows by default and matches gameplay footage (verified on the Madcat). Two decomp-verified reconstructions: EYEPOINT (FUN_004579a8 + caller part_014.c:5525, FUN_004c22c4): - eye offset = siteeyepoint GetBaseOffset (not GetSegmentToEntity, not the upright hack), parented on the PARENT segment DCS (btl4vid.cpp) - live view = affine INVERSE of the eye world matrix (L4VIDRND Execute) -- replaces the hand-rolled LookAtRH whose +Z-forward/+Y-up row guess aimed some mechs into the canopy; combine order fixed to baseOffset * R - chase camera basis + aim boresight re-expressed for the inverse convention (row2 = back); boresight now derives from the view matrix (the stale rows aimed the pick ray at the sky = no target, no discharge) CANOPY (*_COP.BGF, dpl_Punchize geogroups): - every shell is an open strut lattice (38-59% boundary edges, all 12 mechs); rendered single-sided with per-face INWARD winding (l/r torso patches are mirrored, so no global winding works) the struts are the dark frame and the openings show the world - frame colour = the 'softer' ramp near its dark end (texture-less unlit ramp; BLXSKIN.BMF has no texture -- the old "punch texels" theory was wrong) - scoped by filename (meshIsCop); wrong drop-punch + view-cut paths removed - BT_FORCE_MODEL=<name> forces the player mech for per-mech bring-up KB: new context/cockpit-view.md topic; punch split corrected in bgf-format; gotchas 14 (LookAt axis guess) + 15 (per-patch edge namespaces); env gates + eye/punch addresses in decomp-reference. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
7b0b4f64ab
commit
abaa145b6f
@@ -5451,8 +5451,16 @@ DPLEyeRenderable::DPLEyeRenderable(
|
||||
//D3DXVec3Scale(&dir, &dir, 50);
|
||||
//D3DXVec3Subtract(&pos, &pos, &dir);
|
||||
|
||||
// AUTHENTIC VIEW = inverse(eyeWorld) (decomp FUN_004c22c4 @part_013.c:11788,
|
||||
// FUN_0040b244 = affine inverse) -- NOT a LookAt with a hand-picked forward axis.
|
||||
// The look/up axes fall out of the eye's OWN basis via the inverse, so every mech
|
||||
// aims out the windshield regardless of its siteeyepoint axis convention (the old
|
||||
// +Z-forward/+Y-up LookAt guess is why the view aimed into the canopy for some
|
||||
// mechs). mat4 = eyeLocal * parentWorld = the eye WORLD matrix; pos/at/up are
|
||||
// retained only for the aim-boresight feed below.
|
||||
D3DXMATRIX eyeW = mat4.ToD3DMatrix();
|
||||
D3DXMATRIX view;
|
||||
D3DXMatrixLookAtRH(&view,&pos,&at,&up);
|
||||
D3DXMatrixInverse(&view, NULL, &eyeW);
|
||||
|
||||
//myDevice->SetTransform(D3DTS_VIEW, &view);
|
||||
|
||||
@@ -5528,14 +5536,16 @@ void
|
||||
s_oldEyeSway = gBTEyeSwayX;
|
||||
oldLocalToWorld = myEntity->localToWorld;
|
||||
|
||||
// AUTHENTIC combine order (decomp FUN_004579a8 @part_007.c:9305-9316):
|
||||
// eyeLocal = baseOffset(myOrientationMatrix) * R(EyepointRotation), R applied
|
||||
// FIRST in the eye's own local space. (Was R * Orient -- inverted.)
|
||||
camMatrix = myOrientationMatrix;
|
||||
if (myEyepointRotation)
|
||||
{
|
||||
oldEyepointRotation = *myEyepointRotation;
|
||||
camMatrix = *myEyepointRotation;
|
||||
oldEyepointRotation = *myEyepointRotation;
|
||||
Matrix4x4 rotation; rotation = *myEyepointRotation;
|
||||
camMatrix *= rotation;
|
||||
}
|
||||
else
|
||||
camMatrix = Matrix4x4::Identity;
|
||||
camMatrix *= myOrientationMatrix;
|
||||
|
||||
myRenderer->GetMatrixStack()->Push();
|
||||
Matrix4x4 mat4;
|
||||
@@ -5589,14 +5599,31 @@ void
|
||||
pos.x += drot._11 * gBTEyeSwayX; pos.z += drot._13 * gBTEyeSwayX;
|
||||
at.x += drot._11 * gBTEyeSwayX; at.z += drot._13 * gBTEyeSwayX;
|
||||
|
||||
// AUTHENTIC VIEW = inverse(eyeWorld) (decomp FUN_004c22c4 @part_013.c:11788, affine
|
||||
// inverse FUN_0040b244) -- the live per-frame path. Replaces the hand-rolled LookAt
|
||||
// that assumed +Z=forward/+Y=up (which mis-framed the cockpit); the look/up axes now
|
||||
// fall out of the eye's own basis. pos/at/up above are kept only for the aim-boresight.
|
||||
D3DXMATRIX eyeW = mat4.ToD3DMatrix();
|
||||
D3DXMATRIX view;
|
||||
D3DXMatrixLookAtRH(&view,&pos,&at,&up);
|
||||
D3DXMatrixInverse(&view, NULL, &eyeW);
|
||||
|
||||
// EYE POSITION CHECK + 'too far back' diagnostic (task #55).
|
||||
D3DXVECTOR3 eyeFwdW(-view._13, -view._23, -view._33); // D3D view -Z = world look dir
|
||||
{
|
||||
const char *ef = getenv("BT_EYE_FWD"); // push eye forward k units along its look dir
|
||||
if (ef && *ef && myRenderer->mCamera == this)
|
||||
{
|
||||
float k = (float)atof(ef);
|
||||
eyeW._41 += k*eyeFwdW.x; eyeW._42 += k*eyeFwdW.y; eyeW._43 += k*eyeFwdW.z;
|
||||
D3DXMatrixInverse(&view, NULL, &eyeW);
|
||||
}
|
||||
}
|
||||
if (dbgEyeExec < 8)
|
||||
{
|
||||
DEBUG_STREAM << "[EYE] view set: pos=(" << pos.x << "," << pos.y << "," << pos.z
|
||||
<< ") at=(" << at.x << "," << at.y << "," << at.z
|
||||
<< ") up=(" << up.x << "," << up.y << "," << up.z << ")\n" << std::flush;
|
||||
DEBUG_STREAM << "[EYECHK] eyeW=(" << eyeW._41 << "," << eyeW._42 << "," << eyeW._43
|
||||
<< ") fwd=(" << eyeFwdW.x << "," << eyeFwdW.y << "," << eyeFwdW.z
|
||||
<< ") ent=(" << myEntity->localToWorld(3,0) << "," << myEntity->localToWorld(3,1)
|
||||
<< "," << myEntity->localToWorld(3,2) << ")\n" << std::flush;
|
||||
++dbgEyeExec;
|
||||
}
|
||||
|
||||
@@ -5627,11 +5654,17 @@ void
|
||||
// X still carries the torso twist (BTTwistToReticleX); the reticle
|
||||
// Y carries any aim elevation. Falls back to the raw basis only
|
||||
// if the view is (degenerately) near-vertical.
|
||||
D3DXVECTOR3 zax = pos - at;
|
||||
// Derive the boresight from the AUTHORITATIVE view matrix
|
||||
// (eyeFwdW = the world look direction from the inverse view),
|
||||
// not the old LookAt at/pos rows -- those assumed row2=look,
|
||||
// which the authentic inverse-view convention inverted (task
|
||||
// #56 follow-through; the stale rows aimed the pick ray at
|
||||
// the sky = no target, no discharge).
|
||||
D3DXVECTOR3 zax = -eyeFwdW; // back = -look
|
||||
D3DXVec3Normalize(&zax, &zax);
|
||||
D3DXVECTOR3 xax;
|
||||
D3DXVECTOR3 yax;
|
||||
D3DXVECTOR3 fwdLevel(at.x - pos.x, 0.0f, at.z - pos.z);
|
||||
D3DXVECTOR3 fwdLevel(eyeFwdW.x, 0.0f, eyeFwdW.z);
|
||||
if (D3DXVec3LengthSq(&fwdLevel) > 1e-6f)
|
||||
{
|
||||
D3DXVec3Normalize(&fwdLevel, &fwdLevel);
|
||||
|
||||
Reference in New Issue
Block a user