fix(physics): restore swapped-component tangent driver
Use the binary tangent velocity -(vx*normal_y + vy*normal_x)/length, then combine it with retained spin and the Real48 response coefficient. This single formula matches live outer/inner shooter walls, object 155, bumper 51, and the horizontal special-drain response; update C evidence and keep autoplay coverage on a target-reaching seed. Test Plan: - bash original/tools/test_reconstructed_c.sh - python3 original/tools/audit_reconstruction.py --require-complete - cargo test --all-targets - cargo clippy --all-targets --all-features -- -D warnings - original Wine traces: /tmp/original-outer-wall.csv /tmp/original-inner-wall.csv /tmp/original-circle155-after.csv /tmp/original-special-respawn.csv - git diff --check
This commit is contained in:
@@ -10,8 +10,8 @@ and this project adheres to
|
||||
|
||||
### Fixed
|
||||
|
||||
- Correct the common Real48 tangent projection to
|
||||
`spin*0.4 + normal_velocity*response_tangent`; live one-substep probes now
|
||||
- Correct the common Real48 tangent projection to the binary's
|
||||
`spin*0.4 - ((vx*ny + vy*nx)/length)*response_tangent`; live probes now
|
||||
match horizontal drain `(-302,-1809)`, ordinary circle `(94,564)`, and
|
||||
bumper `(197,3096)` transitions instead of rounding a bare coefficient away.
|
||||
- Gate dynamic record 174/175 impulse transfer on the other slot's capture age:
|
||||
|
||||
@@ -241,6 +241,20 @@ fn normal_velocity(velocity: MilliVec, normal_x: Real48, normal_y: Real48, lengt
|
||||
.round_i32()
|
||||
}
|
||||
|
||||
fn tangent_velocity(velocity: MilliVec, normal_x: Real48, normal_y: Real48, length: i32) -> i32 {
|
||||
if length <= 0 {
|
||||
return 0;
|
||||
}
|
||||
Real48::ZERO
|
||||
.subtract(
|
||||
Real48::from_i32(velocity.x)
|
||||
.multiply(normal_y)
|
||||
.add(Real48::from_i32(velocity.y).multiply(normal_x)),
|
||||
)
|
||||
.divide(Real48::from_i32(length))
|
||||
.round_i32()
|
||||
}
|
||||
|
||||
fn cross_at_endpoint(
|
||||
point: MilliVec,
|
||||
current: MilliVec,
|
||||
@@ -270,7 +284,7 @@ fn apply_response(
|
||||
x: normal_x.round_i32(),
|
||||
y: normal_y.round_i32(),
|
||||
});
|
||||
let initial_projection = normal_velocity(velocity, normal_x, normal_y, length);
|
||||
let initial_projection = tangent_velocity(velocity, normal_x, normal_y, length);
|
||||
let mut spin_delta = Real48::from_i32(initial_projection)
|
||||
.multiply(Real48::from_bytes([0x7b, 0x71, 0x3d, 0x0a, 0xd7, 0x23]))
|
||||
.multiply(coefficients.tangent)
|
||||
@@ -280,7 +294,7 @@ fn apply_response(
|
||||
}
|
||||
let projection = spin
|
||||
.multiply(Real48::from_bytes([0x7f, 0xcd, 0xcc, 0xcc, 0xcc, 0x4c]))
|
||||
.add(Real48::from_i32(collision_velocity).multiply(coefficients.tangent))
|
||||
.add(Real48::from_i32(initial_projection).multiply(coefficients.tangent))
|
||||
.round_i32();
|
||||
let spin = spin
|
||||
.multiply(Real48::from_bytes([0x80, 0x9a, 0x99, 0x99, 0x99, 0x19]))
|
||||
@@ -677,12 +691,12 @@ mod tests {
|
||||
0.6,
|
||||
0.1,
|
||||
));
|
||||
assert_eq!(velocity, MilliVec { x: -1_800, y: 345 });
|
||||
assert_eq!(velocity, MilliVec { x: -1_800, y: -255 });
|
||||
assert_eq!(
|
||||
old.add(velocity),
|
||||
MilliVec {
|
||||
x: 324_200,
|
||||
y: 200_390
|
||||
y: 199_790
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -705,7 +719,7 @@ mod tests {
|
||||
|
||||
let response = candidate.resolve(MilliVec { x: 3_000, y: 1_000 }, Real48::ZERO);
|
||||
|
||||
assert_eq!(response.velocity, MilliVec { x: -1_800, y: 1_300 });
|
||||
assert_eq!(response.velocity, MilliVec { x: -1_800, y: 700 });
|
||||
assert_eq!(response.surface_distance, 2_000);
|
||||
}
|
||||
|
||||
@@ -779,12 +793,12 @@ mod tests {
|
||||
0.6,
|
||||
0.1,
|
||||
));
|
||||
assert_eq!(velocity, MilliVec { x: 1_080, y: -390 });
|
||||
assert_eq!(velocity, MilliVec { x: 1_080, y: -30 });
|
||||
assert_eq!(
|
||||
old.add(velocity),
|
||||
MilliVec {
|
||||
x: 321_680,
|
||||
y: 198_935
|
||||
y: 199_295
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -433,7 +433,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn autoplay_stays_finite_for_two_minutes_of_exact_physics() {
|
||||
let mut simulation = Simulation::new(Scenario::Autoplay, 7);
|
||||
let mut simulation = Simulation::new(Scenario::Autoplay, 1);
|
||||
simulation.advance_to(u64::from(SIMULATION_HZ) * 120);
|
||||
let event_count = |name: &str| {
|
||||
simulation
|
||||
|
||||
Reference in New Issue
Block a user