View: the INI viewangle is the HORIZONTAL field -- authentic 60x47 frustum (task #55)
Community reports said the camera looked too far back and the cockpit frames were never this revealed; the user's hypothesis (our projection widens the view) was exactly right. The original Tesla projection call, preserved in a comment at DPLRenderer::SetView, is dpl_SetViewProjection(view, -1, -aspect, +1, +aspect, 1/tan(viewangle/2)) i.e. BTDPL.INI's viewangle=60.0 is the HORIZONTAL field of view with the vertical derived by aspect: the pod's frustum was 60 x 46.8 deg at 4:3. The port fed the 60 to D3DXMatrixPerspectiveFovRH as the VERTICAL fov -> 75 x 60 at 4:3 (worse on widescreen): the world rendered ~25% farther away and far more canopy was visible than the pod ever showed. Fix: BTFovYFromHorizontal(viewangle, aspect) at all five projection sites (main, per-frame resize, sky pass, WM_SIZE rebuild, fallback) -- the horizontal field stays the authentic 60 deg at any window shape. The aim boresight reads the live projection (gBTAimP22) and adapts; combat re-verified (kill chain, no NaN). Cockpits now show the frames at the pod's framing: viewports dominant, frames at the periphery. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
96b8892e7c
commit
27959990ea
@@ -147,6 +147,19 @@ Raptor / Firestarter / Blackjack have `_COP` meshes, SKLs and gauge configs but
|
||||
names: `avatar bhk1 loki madcat owens sunder thor vulture` (+ variants ava1/lok1/lok2/mad1/mad2/
|
||||
own1/snd1/thr1/vul1/blkhawk).
|
||||
|
||||
## The authentic view field (FOV) — viewangle is HORIZONTAL [T1]
|
||||
|
||||
`BTDPL.INI [dpl_defaults] viewangle=60.0` is the **horizontal** field of view: the original Tesla
|
||||
call (preserved in the DPLRenderer::SetView comment, L4VIDEO.cpp) is
|
||||
`dpl_SetViewProjection(view, -1, -aspect, +1, +aspect, 1/tan(viewangle/2))` — horizontal
|
||||
half-extent 1.0, vertical scaled by aspect. Authentic frustum at 4:3 = **60° × 46.8°**. The
|
||||
port had fed the 60 to D3DX as the VERTICAL fov (75° × 60° at 4:3, worse on widescreen) — the
|
||||
world read ~25% farther away ("camera too far back" reports) and the canopy frames were
|
||||
massively over-revealed. Fixed (`BTFovYFromHorizontal`, all 5 projection sites incl. sky +
|
||||
resize): the horizontal field stays 60° at any window shape. The aim/pick feed reads the live
|
||||
projection (`gBTAimP22`) so targeting adapts automatically (combat re-verified). Credit: a
|
||||
user-community report ("frames were never this revealed") + the resolution/FOV hypothesis.
|
||||
|
||||
## Diagnostics / env gates
|
||||
|
||||
`BT_FORCE_MODEL=<name>` (force the player mech: madcat/owens/sunder/…; btl4mssn.cpp),
|
||||
|
||||
+35
-11
@@ -111,6 +111,23 @@ static float gBTAimCamY[3] = {0, 1, 0}; // camera up (LookAtRH yaxis)
|
||||
static float gBTAimCamZ[3] = {0, 0, 1}; // camera BACK (LookAtRH zaxis; view dir = -Z)
|
||||
static float gBTAimP11 = 0.0f; // proj._11 (x scale; carries the aspect)
|
||||
static float gBTAimP22 = 0.0f; // proj._22 (y scale = 1/tan(fovY/2))
|
||||
|
||||
// AUTHENTIC VIEW FIELD (task #55 FOV fix): the INI 'viewangle' (BTDPL.INI
|
||||
// [dpl_defaults] viewangle=60.0) is the HORIZONTAL field of view -- the
|
||||
// original Tesla call (kept in the comment at DPLRenderer::SetView below) is
|
||||
// dpl_SetViewProjection(view, -1, -aspect, +1, +aspect, 1/tan(viewangle/2))
|
||||
// i.e. horizontal half-extent 1.0 at plane distance 1/tan(viewangle/2), with
|
||||
// the VERTICAL extent scaled by aspect. Our port fed the 60 to D3DX as the
|
||||
// VERTICAL fov -> ~75x60 deg instead of the pod's 60x46.8 (4:3): the world
|
||||
// read ~25%% farther away ("camera too far back") and the cockpit canopy was
|
||||
// massively over-revealed. Derive fovY from the horizontal angle at the live
|
||||
// aspect so the horizontal field stays the authentic 60 at any window shape.
|
||||
static float BTFovYFromHorizontal(float viewAngleDeg, float aspect)
|
||||
{
|
||||
if (aspect <= 0.0f)
|
||||
aspect = 4.0f / 3.0f;
|
||||
return 2.0f * atanf(tanf(viewAngleDeg * 0.5f * (PI / 180.0f)) / aspect);
|
||||
}
|
||||
static float gBTAimVpW = 0.0f; // D3D viewport (backbuffer) size --
|
||||
static float gBTAimVpH = 0.0f; // the dpl2d frame's pixel space
|
||||
static int gBTAimCamValid = 0;
|
||||
@@ -4132,8 +4149,11 @@ void
|
||||
// Use the matching RH projection so the mech becomes visible.
|
||||
// BT (task #20): honor the live window aspect if the window has been resized
|
||||
// (gWindowAspect, top of file; set by L4NotifyWindowResized on WM_SIZE).
|
||||
D3DXMatrixPerspectiveFovRH(&mProjectionMatrix, viewAngle * (PI/180.0f),
|
||||
gWindowAspect > 0.0f ? gWindowAspect : (float)x_size / (float)y_size, clipNear, clipFar);
|
||||
{
|
||||
const float projAspect = gWindowAspect > 0.0f ? gWindowAspect : (float)x_size / (float)y_size;
|
||||
D3DXMatrixPerspectiveFovRH(&mProjectionMatrix,
|
||||
BTFovYFromHorizontal(viewAngle, projAspect), projAspect, clipNear, clipFar);
|
||||
}
|
||||
//mProjectionMatrix(0, 0) *= -1;
|
||||
|
||||
mDecalEpsilon = 0.0000005f;
|
||||
@@ -7371,7 +7391,7 @@ void DPLRenderer::ExecuteImplementation(RendererComplexity, RendererOrigin::Inte
|
||||
{
|
||||
appliedAspect = gWindowAspect;
|
||||
D3DXMatrixPerspectiveFovRH(&mProjectionMatrix,
|
||||
viewAngle * (PI / 180.0f), appliedAspect, clipNear, clipFar);
|
||||
BTFovYFromHorizontal(viewAngle, appliedAspect), appliedAspect, clipNear, clipFar);
|
||||
mDecalProjectionMatrix = mProjectionMatrix;
|
||||
mDecalProjectionMatrix._33 -= mDecalEpsilon;
|
||||
mDevice->SetTransform(D3DTS_PROJECTION, &mProjectionMatrix);
|
||||
@@ -7669,9 +7689,11 @@ void DPLRenderer::ExecuteImplementation(RendererComplexity, RendererOrigin::Inte
|
||||
mDevice->SetRenderState(D3DRS_FOGSTART, *((DWORD*)(¤tFogNear)));
|
||||
mDevice->SetRenderState(D3DRS_FOGEND, *((DWORD*)(¤tFogFar)));
|
||||
D3DXMATRIX skyProj;
|
||||
D3DXMatrixPerspectiveFovRH(&skyProj, viewAngle * (PI / 180.0f),
|
||||
gWindowAspect > 0.0f ? gWindowAspect : (float)x_size / (float)y_size,
|
||||
clipNear, 9000.0f);
|
||||
{
|
||||
const float skyAspect = gWindowAspect > 0.0f ? gWindowAspect : (float)x_size / (float)y_size;
|
||||
D3DXMatrixPerspectiveFovRH(&skyProj,
|
||||
BTFovYFromHorizontal(viewAngle, skyAspect), skyAspect, clipNear, 9000.0f);
|
||||
}
|
||||
mDevice->SetTransform(D3DTS_PROJECTION, &skyProj);
|
||||
}
|
||||
else
|
||||
@@ -8564,8 +8586,8 @@ void
|
||||
<< viewAngle << ")\n" << std::flush;
|
||||
return; // projection not built yet; the builder below picks it up
|
||||
}
|
||||
D3DXMatrixPerspectiveFovRH(&mProjectionMatrix, viewAngle * (PI / 180.0f),
|
||||
gWindowAspect, clipNear, clipFar);
|
||||
D3DXMatrixPerspectiveFovRH(&mProjectionMatrix,
|
||||
BTFovYFromHorizontal(viewAngle, gWindowAspect), gWindowAspect, clipNear, clipFar);
|
||||
mDecalProjectionMatrix = mProjectionMatrix;
|
||||
mDecalProjectionMatrix._33 -= mDecalEpsilon;
|
||||
if (mDevice != NULL)
|
||||
@@ -8611,9 +8633,11 @@ void
|
||||
viewRatio = (float)tan(viewAngle * 0.5f * (PI / 180.0f));
|
||||
|
||||
D3DXMatrixIdentity(&mProjectionMatrix);
|
||||
D3DXMatrixPerspectiveFovRH(&mProjectionMatrix, viewAngle * (PI / 180.0f),
|
||||
gWindowAspect > 0.0f ? gWindowAspect : (float)x_size / (float)y_size,
|
||||
clipNear, clipFar);
|
||||
{
|
||||
const float fbAspect = gWindowAspect > 0.0f ? gWindowAspect : (float)x_size / (float)y_size;
|
||||
D3DXMatrixPerspectiveFovRH(&mProjectionMatrix,
|
||||
BTFovYFromHorizontal(viewAngle, fbAspect), fbAspect, clipNear, clipFar);
|
||||
}
|
||||
|
||||
mDecalEpsilon = 0.0000005f;
|
||||
mDecalProjectionMatrix = mProjectionMatrix;
|
||||
|
||||
Reference in New Issue
Block a user