From 375192e795c80db0838c7d7bf0d9be09bff6e127 Mon Sep 17 00:00:00 2001 From: chazmm Date: Sun, 6 Sep 2026 22:12:09 +0100 Subject: [PATCH] Filter offboard board contacts by native body-part collision groups --- crates/skate-game/src/physics/frame.rs | 1 - crates/skate-game/src/physics/offboard/mod.rs | 1 - .../src/physics/offboard/runtime.rs | 2 - .../skate-game/src/physics/offboard/trace.rs | 50 ------------------- .../src/physics/solve/assembly_contacts.rs | 24 ++++++--- 5 files changed, 17 insertions(+), 61 deletions(-) delete mode 100644 crates/skate-game/src/physics/offboard/trace.rs diff --git a/crates/skate-game/src/physics/frame.rs b/crates/skate-game/src/physics/frame.rs index 3f96c9ef..deb27f81 100644 --- a/crates/skate-game/src/physics/frame.rs +++ b/crates/skate-game/src/physics/frame.rs @@ -148,7 +148,6 @@ pub(super) fn advance( //All consumers of the preceding output have completed this frame's input. super::player_input::reset_outputs(&mut skater.player_input.physical); physics.finish_skater(skater)?; - super::offboard::trace::record(physics, skater); let simulation = physics.settings.step.simulation; skater.player_input.update_dynamic_normal( &physics.board, diff --git a/crates/skate-game/src/physics/offboard/mod.rs b/crates/skate-game/src/physics/offboard/mod.rs index 47eaf259..d63f5aff 100644 --- a/crates/skate-game/src/physics/offboard/mod.rs +++ b/crates/skate-game/src/physics/offboard/mod.rs @@ -14,4 +14,3 @@ pub(crate) mod runtime; pub(crate) mod settings; pub(crate) mod skeleton_air; pub(crate) mod skeleton_ground; -pub(crate) mod trace; diff --git a/crates/skate-game/src/physics/offboard/runtime.rs b/crates/skate-game/src/physics/offboard/runtime.rs index 3785060f..643c6924 100644 --- a/crates/skate-game/src/physics/offboard/runtime.rs +++ b/crates/skate-game/src/physics/offboard/runtime.rs @@ -10,7 +10,6 @@ use skate_core::point_graph::PointGraph; use skate_data::{animation_metadata::AnimationMetadata, collections::Collections}; pub(crate) struct Runtime { - pub trace: super::trace::Trace, pub air_state: skate_core::player::offboard::air_state::State, pub air_prediction: Option, pub air_blend_curve: PointGraph<8>, @@ -149,7 +148,6 @@ impl Runtime { pub(crate) fn load(data: &Collections, metadata: &AnimationMetadata) -> Result { let settings = super::settings::Settings::load(data, metadata)?; Ok(Self { - trace: Default::default(), air_state: Default::default(), air_prediction: None, air_blend_curve: settings.air_blend_curve, diff --git a/crates/skate-game/src/physics/offboard/trace.rs b/crates/skate-game/src/physics/offboard/trace.rs deleted file mode 100644 index 26a32036..00000000 --- a/crates/skate-game/src/physics/offboard/trace.rs +++ /dev/null @@ -1,50 +0,0 @@ -//! Opt-in observations of user-controlled dismounts; never modifies simulation. -use crate::physics::{GamePhysics, SkaterRuntime}; - -pub(crate) struct Trace { - enabled: bool, - was_offboard: bool, - remaining: u32, - captures: u32, -} -impl Default for Trace { - fn default() -> Self { - Self { - enabled: std::env::var_os("SKATE_OFFBOARD_TRACE").is_some(), - was_offboard: false, - remaining: 0, - captures: 0, - } - } -} -pub(crate) fn record(physics: &GamePhysics, skater: &mut SkaterRuntime) { - let p = &skater.player_input.processed; - let trace = &mut skater.offboard.trace; - if !trace.enabled { return; } - let offboard = p.category_2512 == 500; - if offboard && !trace.was_offboard && trace.remaining == 0 && trace.captures < 3 { - trace.remaining = 600; - trace.captures += 1; - } - trace.was_offboard = offboard; - if trace.remaining == 0 { return; } - trace.remaining -= 1; - let motion = skater.offboard.controller.output(); - let s = &skater.animated_skeleton; - let a = &skater.animation_input.fields; - eprintln!( - "OFFBOARD_TRACE tick={} state={} clip={:?} flags={:08x}/{:08x}/{:08x}/{:08x}/{:08x} root={:?} root_velocity={:?} controller={:?} velocity={:?} up={:?} com_target={:?} com={:?} pose_error={:?} extra_error={:?} contact={:x} contact_pos={:?} contact_normal={:?} cadence={} anim_velocity={:?} anim_motion={:?} anim_time={} override_time={} hand={} board_target={:?} board={:?} bail={:?}", - physics.ticks, p.state_2508, skater.animation.motion.animation.current_name, - p.flags_2468, p.flags_2472, p.flags_2476, p.flags_2480, p.flags_2484, - s.roots.animation_to_world[3], skater.skeleton_input.root_velocity, - motion.physical_frame[3], motion.velocity, motion.animation_frame[1], - s.board_frames.com_frame[3], skater.skeleton.record.centre_of_mass, - skater.collision_maximum_error, skater.collision_extra_displacements, - skater.offboard.retained_contact.flags, skater.offboard.retained_contact.position, - skater.offboard.retained_contact.normal, a.cadence_end_percent, - s.motion.velocity_world, a.animation_translation, a.animation_time, - a.animation_physics_blend_seconds, skater.offboard.possession.selected_hand_424, - s.board_frames.animation_target[3], crate::physics::solve::deck_frame(&physics.board)[3], - skater.wipeout.state.reasons, - ); -} diff --git a/crates/skate-game/src/physics/solve/assembly_contacts.rs b/crates/skate-game/src/physics/solve/assembly_contacts.rs index 1f5dc933..28f990a9 100644 --- a/crates/skate-game/src/physics/solve/assembly_contacts.rs +++ b/crates/skate-game/src/physics/solve/assembly_contacts.rs @@ -22,12 +22,19 @@ pub(super) fn append( if board_group > 7 || collision.assembly_group > 7 { return Err("Skater assembly collision requires its original group-table extension".into()); } - if group_pair_allowed(board_group, collision.assembly_group) { + { for a in board { for b in rider { let CollisionBody::Attached(part) = b.body else { unreachable!() }; + // The per-part group is independently assigned in Biped mode: + // hands5, legs17, torso18 and the two controller capsules20. + // Using assembly6 here makes the carried board collide with + // its own hand drive and the capsules that feed root correction. + if !group_pair_allowed(board_group, collision.parts[part].part_group) { + continue; + } //Serialized volume+212 is source Volume+84 group. //Stock board child constructors leave that field zero. if !group_pair_allowed(0, collision.parts[part].volume_group) { @@ -57,12 +64,15 @@ pub(super) fn append( } fn group_pair_allowed(a: u32, b: u32) -> bool { - match (a, b) { - (0, 0 | 2..=7) | (2..=7, 0) => true, - (4, 5) | (5, 4) => false, - (4..=7, 4..=7) => true, - _ => false, - } + // Single-player21x21 bitmap constructed by82765EF0 through the + // Island.flags==3 branch. One allowed bit per column, inverted from the + // native culling bits. Keep special Biped groups instead of truncating to8. + const ALLOWED: [u32; 21] = [ + 0x1876fd, 0, 0x120001, 1, 0x79d1, 0x1079e1, 0x1079f1, + 0x279f1, 0x1676f0, 0x7101, 0x5101, 0x1008f0, 0x1d77f1, + 0x233f1, 0xa57f1, 0, 0x1000, 0x6184, 0x1100, 0x5001, 0x1965, + ]; + b < 21 && ALLOWED.get(a as usize).is_some_and(|row| row & (1 << b) != 0) } fn append_pair(contacts: &mut Vec, a: &BoardWorldVolume, b: &BoardWorldVolume) {