Fix torso-pitch aim ray: gyro-stabilized boresight from the mech torso
The aim/pick ray was the active RENDER EYE's view direction, which made a
mech unable to aim at a distant enemy:
(a) it inherited the mech BODY pitch -- on a slope the body tilts ~8 deg to
conform to terrain, so the boresight pointed that far DOWN and the pick
ray hit the ground ~50-100m short of the target (groundPicks, never
mechPicks); and
(b) in CHASE view (the default) it was the elevated behind-the-shoulder
camera, so the ray started over the mech's shoulder and flew high.
Fix (L4VIDRND DPLEyeRenderable::Execute, the BTSetAimCamera publish):
- LEVEL the boresight: drop the view-direction pitch and rebuild an upright
basis (world +Y up) -- the guns fire along the mech's gyro-stabilized
HORIZONTAL heading, not the terrain-pitched body. Reticle X still carries
the torso twist (BTTwistToReticleX); reticle Y any elevation.
- ANCHOR the ray origin at the mech's TORSO (myEntity->localToWorld
translation + ~5) instead of the render eye, so it is correct in BOTH the
chase (default) and cockpit views.
Verified end-to-end: solo, enemy 120m ahead, BOTH chase and cockpit view ->
[target] "MECH under boresight ... mechPicks=59 groundPicks=0" -> beam ->
*** DESTROYED. Also proved PickRayHit resolves a REPLICANT when aimed at it
(hit=1 at 757m, 2-node run).
mech4: BT_GOTO="enemy" test aid now chases the nearest peer of ANY instance
(solo dummy OR replicant), not just replicants.
Still open (locomotion, not aim/MP): BT_GOTO/BT_AUTODRIVE stall short of the
enemy, so an AUTOMATED 2-node kill via the real beam isn't demonstrated yet
(the FORCE_DMG hook still is). A human can now aim correctly in the default
view. Solo un-regressed; build clean; KB validator clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
bac45851ad
commit
0dfbb97dcc
@@ -5588,14 +5588,50 @@ void
|
||||
{
|
||||
extern void BTSetAimCamera(const float pos[3], const float xax[3],
|
||||
const float yax[3], const float zax[3]);
|
||||
// AIM BORESIGHT (task #48): the guns fire along the mech's
|
||||
// GYRO-STABILIZED horizontal heading, NOT the terrain-pitched
|
||||
// body/eye. Publishing the raw eye basis made a mech standing
|
||||
// on a slope (body pitched ~8 deg to conform to the ground) aim
|
||||
// its pick ray INTO the ground, short of a distant target
|
||||
// (mechPicks=0). Level the boresight: drop the view direction's
|
||||
// pitch and rebuild an upright basis (world +Y up). The reticle
|
||||
// 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;
|
||||
D3DXVec3Normalize(&zax, &zax);
|
||||
D3DXVECTOR3 xax;
|
||||
D3DXVec3Cross(&xax, &up, &zax);
|
||||
D3DXVec3Normalize(&xax, &xax);
|
||||
D3DXVECTOR3 yax;
|
||||
D3DXVec3Cross(&yax, &zax, &xax);
|
||||
const float p[3] = { pos.x, pos.y, pos.z };
|
||||
D3DXVECTOR3 fwdLevel(at.x - pos.x, 0.0f, at.z - pos.z);
|
||||
if (D3DXVec3LengthSq(&fwdLevel) > 1e-6f)
|
||||
{
|
||||
D3DXVec3Normalize(&fwdLevel, &fwdLevel);
|
||||
zax = D3DXVECTOR3(-fwdLevel.x, 0.0f, -fwdLevel.z); // back = -level fwd
|
||||
D3DXVECTOR3 wup(0.0f, 1.0f, 0.0f);
|
||||
D3DXVec3Cross(&xax, &wup, &zax);
|
||||
D3DXVec3Normalize(&xax, &xax);
|
||||
D3DXVec3Cross(&yax, &zax, &xax); // == world +Y
|
||||
}
|
||||
else
|
||||
{
|
||||
D3DXVec3Cross(&xax, &up, &zax);
|
||||
D3DXVec3Normalize(&xax, &xax);
|
||||
D3DXVec3Cross(&yax, &zax, &xax);
|
||||
}
|
||||
// ORIGIN: the guns fire from the MECH's torso, not the render
|
||||
// eye. In CHASE view the eye sits behind+above the mech, so a
|
||||
// ray from `pos` would start over the shoulder (and, being level,
|
||||
// fly above a ground target). Anchor the boresight at the mech's
|
||||
// XZ + a torso/gun height so the pick works in BOTH views (chase
|
||||
// is the default; cockpit toggles with V). In cockpit view this
|
||||
// is ~the eyepoint anyway.
|
||||
float p[3] = { pos.x, pos.y, pos.z };
|
||||
if (myEntity != 0)
|
||||
{
|
||||
p[0] = myEntity->localToWorld(3,0);
|
||||
p[1] = myEntity->localToWorld(3,1) + 5.0f; // feet -> torso/gun height
|
||||
p[2] = myEntity->localToWorld(3,2);
|
||||
}
|
||||
const float x3[3] = { xax.x, xax.y, xax.z };
|
||||
const float y3[3] = { yax.x, yax.y, yax.z };
|
||||
const float z3[3] = { zax.x, zax.y, zax.z };
|
||||
|
||||
Reference in New Issue
Block a user