fix(physics): match live tangent response transitions

Correct the common projection to spin*0.4 + normal_velocity*response_tangent and seal line/circle behavior against current Wine one-substep traces. Preserve record-two's in-response special-respawn continuation, producing the live (16698,21191)/(-302,-1809) state after publishing (17000,23000)/(0,3040), and update the readable C evidence.

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
- rumdl check original/C_RECONSTRUCTION_FINAL_AUDIT.md tdkpin-rs/CHANGELOG.md tdkpin-rs/RECONSTRUCTION.md tdkpin-rs/README.md
- live Wine record 2 trace: /tmp/original-special-respawn.csv
- live Wine object 155 trace: /tmp/original-circle155-after.csv
- git diff --check
This commit is contained in:
2026-08-23 19:42:23 +02:00
parent 06d1010431
commit 3dce159965
8 changed files with 107 additions and 26 deletions
+16 -16
View File
@@ -280,7 +280,7 @@ fn apply_response(
}
let projection = spin
.multiply(Real48::from_bytes([0x7f, 0xcd, 0xcc, 0xcc, 0xcc, 0x4c]))
.subtract(coefficients.tangent)
.add(Real48::from_i32(collision_velocity).multiply(coefficients.tangent))
.round_i32();
let spin = spin
.multiply(Real48::from_bytes([0x80, 0x9a, 0x99, 0x99, 0x99, 0x19]))
@@ -662,7 +662,7 @@ mod tests {
}
#[test]
fn outer_shooter_wall_matches_the_zero_spin_c_response() {
fn outer_shooter_wall_matches_the_live_tangent_response() {
let old = MilliVec {
x: 326_000,
y: 200_045,
@@ -677,12 +677,12 @@ mod tests {
0.6,
0.1,
));
assert_eq!(velocity, MilliVec { x: -1_800, y: 45 });
assert_eq!(velocity, MilliVec { x: -1_800, y: 345 });
assert_eq!(
old.add(velocity),
MilliVec {
x: 324_200,
y: 200_090
y: 200_390
}
);
}
@@ -705,7 +705,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_000 });
assert_eq!(response.velocity, MilliVec { x: -1_800, y: 1_300 });
assert_eq!(response.surface_distance, 2_000);
}
@@ -764,7 +764,7 @@ mod tests {
}
#[test]
fn inner_shooter_wall_matches_the_zero_spin_c_response() {
fn inner_shooter_wall_matches_the_live_tangent_response() {
let old = MilliVec {
x: 320_600,
y: 199_325,
@@ -779,12 +779,12 @@ mod tests {
0.6,
0.1,
));
assert_eq!(velocity, MilliVec { x: 1_080, y: -210 });
assert_eq!(velocity, MilliVec { x: 1_080, y: -390 });
assert_eq!(
old.add(velocity),
MilliVec {
x: 321_680,
y: 199_115
y: 198_935
}
);
}
@@ -855,7 +855,7 @@ mod tests {
}
#[test]
fn ordinary_circle_matches_the_zero_spin_c_response() {
fn ordinary_circle_matches_the_live_zero_spin_response() {
let old = MilliVec {
x: 183_000,
y: 70_090,
@@ -871,18 +871,18 @@ mod tests {
0.1,
0.0,
));
assert_eq!(velocity, MilliVec { x: 0, y: 564 });
assert_eq!(velocity, MilliVec { x: 94, y: 564 });
assert_eq!(
old.add(velocity),
MilliVec {
x: 183_000,
x: 183_094,
y: 70_654
}
);
}
#[test]
fn bumper_circle_matches_the_zero_spin_c_response() {
fn bumper_circle_matches_the_live_zero_spin_response() {
let old = MilliVec {
x: 165_000,
y: 172_015,
@@ -898,18 +898,18 @@ mod tests {
0.1,
0.4,
));
assert_eq!(velocity, MilliVec { x: 0, y: 3_096 });
assert_eq!(velocity, MilliVec { x: 197, y: 3_096 });
assert_eq!(
old.add(velocity),
MilliVec {
x: 165_000,
x: 165_197,
y: 175_111
}
);
}
#[test]
fn retained_spin_reproduces_the_live_circle_tangent() {
fn retained_spin_adds_to_the_live_circle_tangent() {
let response = circle_collision_response(
MilliVec {
x: 183_000,
@@ -922,7 +922,7 @@ mod tests {
Real48::from_i32(-235),
)
.expect("live probe enters object 155");
assert_eq!(response.velocity, MilliVec { x: 94, y: 564 });
assert_eq!(response.velocity, MilliVec { x: 188, y: 564 });
}
#[test]