Filter offboard board contacts by native body-part collision groups

This commit is contained in:
chazmm committed 2026-09-06 22:12:09 +01:00
1 parent e98cf7badb
commit 375192e795
5 files changed
+17 -61

No files matched your search

-1
View File
@@ -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,
@@ -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;
@@ -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<skate_core::player::offboard::air_prediction::Prediction>,
pub air_blend_curve: PointGraph<8>,
@@ -149,7 +148,6 @@ impl Runtime {
pub(crate) fn load(data: &Collections, metadata: &AnimationMetadata) -> Result<Self, String> {
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,
@@ -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,
);
}
@@ -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<BoardCollision>, a: &BoardWorldVolume, b: &BoardWorldVolume) {