Aim coordinates: route all conversions through the true NDC (fixes the
sideways lock offset) The windowed present stretches the fixed 800x600 backbuffer into the client area while the projection's aspect follows the CLIENT (resize rebuild) -- so the dpl2d/reticle frame, the client frame and NDC only coincide for a backbuffer-shaped window. The mouse mapping and the square-frame ray shortcut (cx = rx*tanHalfFov) were exact at screen centre and drifted outward with a side-flipped sign: aiming left of the enemy locked as if right of it (user report). - BTSetAimProjection now publishes BOTH proj scales (P11 carries the aspect) + the backbuffer size (the dpl2d frame). NOTE: GetViewport at the loop top holds the PREVIOUS frame's last pass viewport (gauge passes shrink it) -> use the renderer's own GetWidth/GetHeight. - BTGetAimRay / BTProjectToReticle convert reticle <-> NDC per axis (ndc_x = rx * vh/vw; camera x = ndc_x/P11) -- exact for any window shape and FOV. - New BTClientToReticle undoes the present stretch for the mouse (client px -> viewport px -> reticle coords); mech4 uses it instead of the raw client-height mapping. - 1Hz aim telemetry in the [target] log (hits/noRay/noPick): verified 100% pick hit rate once the projection is live (the pre-visibility mission-load seconds report noRay -- that was the "flicker"). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
9666dc5b5e
commit
cf9f56044e
@@ -1272,17 +1272,17 @@ void
|
||||
pCur(&cp) && pStc(wnd, &cp) && pCr(wnd, &rc) &&
|
||||
rc.right > rc.left && rc.bottom > rc.top)
|
||||
{
|
||||
const float w = (float)(rc.right - rc.left);
|
||||
const float h = (float)(rc.bottom - rc.top);
|
||||
const float hh = h * 0.5f;
|
||||
float rx = ((float)cp.x - w * 0.5f) / hh;
|
||||
float ry = ((float)cp.y - h * 0.5f) / hh;
|
||||
// clamp to the visible frame (aspect-wide in x)
|
||||
const float xmax = (w / h);
|
||||
if (rx < -xmax) rx = -xmax;
|
||||
if (rx > xmax) rx = xmax;
|
||||
if (ry < -1.0f) ry = -1.0f;
|
||||
if (ry > 1.0f) ry = 1.0f;
|
||||
// client px -> reticle coords through the RENDERER
|
||||
// (it undoes the backbuffer->client present stretch;
|
||||
// a raw client-height mapping is only exact for a
|
||||
// backbuffer-shaped window and skews the pick
|
||||
// sideways otherwise).
|
||||
extern void BTClientToReticle(float mx, float my,
|
||||
float cw, float ch, float *rx, float *ry);
|
||||
float rx = 0.0f, ry = 0.0f;
|
||||
BTClientToReticle((float)cp.x, (float)cp.y,
|
||||
(float)(rc.right - rc.left),
|
||||
(float)(rc.bottom - rc.top), &rx, &ry);
|
||||
gBTAimX = rx;
|
||||
gBTAimY = ry;
|
||||
}
|
||||
@@ -2311,15 +2311,25 @@ void
|
||||
// resolves damage to the zone under the crosshair (aimed fire).
|
||||
Entity *hotTarget = 0; // mech under the crosshair NOW
|
||||
Point3D hotPoint; // picked world point on its hull
|
||||
static int gAimNoRay = 0, gAimNoPick = 0, gAimHits = 0; // 1Hz diagnostics
|
||||
{
|
||||
extern int BTGetAimRay(float rx, float ry, float outStart[3], float outDir[3]);
|
||||
float rs[3], rd[3];
|
||||
if (BTGetAimRay(gBTAimX, gBTAimY, rs, rd) && gEnemyMech != 0)
|
||||
if (!BTGetAimRay(gBTAimX, gBTAimY, rs, rd))
|
||||
{
|
||||
++gAimNoRay;
|
||||
}
|
||||
else if (gEnemyMech != 0)
|
||||
{
|
||||
Point3D rayStart(rs[0], rs[1], rs[2]);
|
||||
Vector3D rayDir(rd[0], rd[1], rd[2]);
|
||||
if (((Mech *)gEnemyMech)->PickRayHit(rayStart, rayDir, 4000.0f, &hotPoint))
|
||||
{
|
||||
hotTarget = gEnemyMech;
|
||||
++gAimHits;
|
||||
}
|
||||
else
|
||||
++gAimNoPick;
|
||||
}
|
||||
|
||||
// The Reticle struct (the mech's TargetReticle attribute): position,
|
||||
@@ -2396,7 +2406,10 @@ void
|
||||
: (designated ? " designated (off-crosshair)" : " no target"))
|
||||
<< " range=" << range
|
||||
<< (range <= kWeaponRange ? " IN RANGE" : "")
|
||||
<< " [hits=" << gAimHits << " noRay=" << gAimNoRay
|
||||
<< " noPick=" << gAimNoPick << "]"
|
||||
<< "\n" << std::flush;
|
||||
gAimHits = 0; gAimNoRay = 0; gAimNoPick = 0;
|
||||
}
|
||||
|
||||
// --- FIRING (bring-up): on the trigger, with a target in range and the
|
||||
|
||||
Reference in New Issue
Block a user