fix(physics): restore standard tangent sign response
The left relative slingshot probe proved the spin projection, but its geometry did not distinguish the sign rule. A stopped-Wine probe on symmetric record 72 did: the binary uses the standard dot-product tangent for both spin and the opposing direction of the current tangential response. The earlier swapped-component interpretation happened to agree for vertical walls and a centered circle but selected the wrong sign on the right slingshot. Use `tv=(vx*nx+vy*ny)/length`, update spin with `tv*0.02*response_tangent`, and apply `-sign(tv)*abs(normal_velocity)*response_tangent`, retaining the binary's negative direction when tv is zero. Seal record 72's exact position, velocity, and `+5.46` Real48 spin in C and Rust. Keep the two-minute autoplay assertion focused on actual launch, press/release, target, bumper, and finite-state activity after the corrected trajectory. Test Plan: - stopped Wine 11.15 record-72 injection/trace -- matched position, velocity, and spin - `cargo test --workspace --all-targets --all-features` -- 124 passed - `cargo clippy --workspace --all-targets --all-features -- -D warnings` -- passed - `bash original/tools/test_reconstructed_c.sh` -- passed - `python3 original/tools/audit_reconstruction.py --require-complete` -- passed with zero incomplete or unclassified units - `rumdl check --flavor commonmark RECONSTRUCTION.md CHANGELOG.md` -- passed - `git diff --cached --check` -- passed
This commit is contained in:
@@ -191,23 +191,7 @@ static int32_t normal_velocity_checked(
|
||||
velocity_x, velocity_y, normal_x, normal_y, normal_length);
|
||||
}
|
||||
|
||||
static int32_t tangent_direction_unchecked(
|
||||
int32_t velocity_x,
|
||||
int32_t velocity_y,
|
||||
BorlandReal48 normal_x,
|
||||
BorlandReal48 normal_y,
|
||||
int32_t normal_length)
|
||||
{
|
||||
return negate_wrap(borland_real48_round_to_i32(borland_real48_divide(
|
||||
borland_real48_add(
|
||||
borland_real48_multiply(
|
||||
borland_i32_to_real48(velocity_x), normal_y),
|
||||
borland_real48_multiply(
|
||||
borland_i32_to_real48(velocity_y), normal_x)),
|
||||
borland_i32_to_real48(normal_length))));
|
||||
}
|
||||
|
||||
static int32_t spin_velocity_unchecked(
|
||||
static int32_t tangent_velocity_unchecked(
|
||||
int32_t velocity_x,
|
||||
int32_t velocity_y,
|
||||
BorlandReal48 normal_x,
|
||||
@@ -943,16 +927,9 @@ static void apply_collision_response(
|
||||
tdkpin_add_score_from_caller_frame(caller_bp, candidate->score);
|
||||
}
|
||||
int32_t length = candidate_normal_length(candidate);
|
||||
/* Raw 1000:ef19..f16a keeps the contact-direction and spin projections
|
||||
* separate. The swapped-component value selects the sign of the current
|
||||
* tangential response; the standard dot product updates retained spin. */
|
||||
int32_t tangent_direction = tangent_direction_unchecked(
|
||||
motion->velocity_x,
|
||||
motion->velocity_y,
|
||||
candidate->normal_x,
|
||||
candidate->normal_y,
|
||||
length);
|
||||
int32_t spin_projection = spin_velocity_unchecked(
|
||||
/* Raw 1000:ef19..f16a uses the standard dot-product tangent both to
|
||||
* oppose the current tangential motion and to update retained spin. */
|
||||
int32_t tangent_velocity = tangent_velocity_unchecked(
|
||||
motion->velocity_x,
|
||||
motion->velocity_y,
|
||||
candidate->normal_x,
|
||||
@@ -961,7 +938,7 @@ static void apply_collision_response(
|
||||
|
||||
BorlandReal48 spin_delta = borland_real48_multiply(
|
||||
borland_real48_multiply(
|
||||
borland_i32_to_real48(spin_projection),
|
||||
borland_i32_to_real48(tangent_velocity),
|
||||
g_real48_point_zero_two),
|
||||
candidate->response_tangent);
|
||||
BorlandReal48 discarded = borland_real48_divide(
|
||||
@@ -974,7 +951,8 @@ static void apply_collision_response(
|
||||
BorlandReal48 tangent_response = borland_real48_multiply(
|
||||
borland_i32_to_real48(absolute_wrap(candidate->normal_velocity)),
|
||||
candidate->response_tangent);
|
||||
if (tangent_direction < 0) {
|
||||
tangent_response = negate_real48(tangent_response);
|
||||
if (tangent_velocity < 0) {
|
||||
tangent_response = negate_real48(tangent_response);
|
||||
}
|
||||
int32_t projection = borland_real48_round_to_i32(borland_real48_add(
|
||||
@@ -982,7 +960,7 @@ static void apply_collision_response(
|
||||
borland_real48_multiply(motion->spin, g_real48_point_four),
|
||||
borland_real48_divide(
|
||||
borland_real48_multiply(
|
||||
borland_i32_to_real48(absolute_wrap(tangent_direction)),
|
||||
borland_i32_to_real48(absolute_wrap(tangent_velocity)),
|
||||
discarded),
|
||||
borland_i32_to_real48(motion->speed))),
|
||||
tangent_response));
|
||||
|
||||
Reference in New Issue
Block a user