Skip to content

Commit

Permalink
Fix compound collider
Browse files Browse the repository at this point in the history
  • Loading branch information
janhohenheim committed Aug 19, 2024
1 parent eb347cb commit 08ca297
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 28 deletions.
22 changes: 13 additions & 9 deletions src/interaction/hold/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ pub(super) fn update_object(
)>,

q_collider_ancestor: Query<&Children, With<AncestorMarker<ColliderMarker>>>,
q_collider: Query<(&Position, &Rotation, &Collider), Without<Sensor>>,
q_collider: Query<(&Transform, &Collider), Without<Sensor>>,
) {
let max_error = 0.3048; // 12 inches in the source engine
for (actor, _config, grab, _shadow, holding, actor_position, actor_rotation) in
Expand All @@ -77,9 +77,12 @@ pub(super) fn update_object(
let _actor_to_prop_pitch = actor_pitch.clamp(clamp_pitch.min, clamp_pitch.max);
let forward = Transform::from_rotation(actor_rotation.0).forward();
let compound_collider =
rigid_body_compound_collider(prop, *actor_position, &q_collider_ancestor, &q_collider);
rigid_body_compound_collider(prop, &q_collider_ancestor, &q_collider);
let Some(compound_collider) = compound_collider else {
error!("Held prop does not have a collider in its hierarchy. Ignoring.");
continue;
};
let radial = collide_get_extent(&compound_collider, Vec3::ZERO, prop_rotation.0, -forward);
info!("radial: {:?}", radial);

let _target_rotation = preferred_rotation
.map(|preferred| preferred.0)
Expand All @@ -92,18 +95,19 @@ pub(super) fn update_object(
/// but we can only do that for convex shapes in parry. Notably, compound shapes
/// made of convex shapes are not supported.\
/// So, we instead just cast a ray in the direction and get the hit point.
/// Since the original code multiplies the directoin by the dot product of
/// the direction and the support point, it looks like the result is the same.
fn collide_get_extent(collider: &Collider, origin: Vec3, rotation: Quat, dir: Dir3) -> Vec3 {
const TRANSLATION: Vec3 = Vec3::ZERO;
// We cast from inside the collider, so we don't care about a max TOI
const MAX_TOI: f32 = f32::INFINITY;
// Needs to be false to not just get the origin back
const SOLID: bool = false;
info!(
"translation: {:?}, rotation: {:?}, origin: {:?}, dir: {:?}",
TRANSLATION, rotation, origin, dir
);
info!("collider: {:?}", collider);
let hit = collider.cast_ray(TRANSLATION, rotation, origin, dir.into(), MAX_TOI, SOLID);
let (toi, _normal) = hit.expect("Casting a ray from inside a collider did not hit the collider itself. This seems like a bug in Avian.");
let (toi, _normal) = hit.expect(
"Casting a ray from inside a collider did not hit the collider itself.\n\
This means the compound collider we constructed is malformed.\n\
This is a bug. Please report it on `avian_pickup`s GitHub page.",
);
dir * toi
}
43 changes: 24 additions & 19 deletions src/math.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,42 @@
use avian3d::{prelude::*, sync::ancestor_marker::AncestorMarker};
use bevy::prelude::*;
use dynamics::rigid_body;

pub(crate) const METERS_PER_INCH: f32 = 0.0254;

pub(crate) fn rigid_body_compound_collider(
rigid_body: Entity,
origin: Position,
q_collider_ancestor: &Query<&Children, With<AncestorMarker<ColliderMarker>>>,
q_collider: &Query<(&Position, &Rotation, &Collider), Without<Sensor>>,
) -> Collider {
q_collider: &Query<(&Transform, &Collider), Without<Sensor>>,
) -> Option<Collider> {
let mut colliders = Vec::new();
rigid_body_compound_collider_recursive(
rigid_body,
q_collider_ancestor,
q_collider,
&mut colliders,
origin,
);
Collider::compound(colliders)
if let Ok((&_transform, col)) = q_collider.get(rigid_body) {
colliders.push((Vec3::ZERO, Quat::IDENTITY, col.clone()));
}
if let Ok(children) = q_collider_ancestor.get(rigid_body) {
for child in children.iter() {
rigid_body_compound_collider_recursive(
*child,
q_collider_ancestor,
q_collider,
&mut colliders,
);
}
}
if colliders.is_empty() {
None
} else {
Some(Collider::compound(colliders))
}
}

fn rigid_body_compound_collider_recursive(
candidate: Entity,
q_collider_ancestor: &Query<&Children, With<AncestorMarker<ColliderMarker>>>,
q_collider: &Query<(&Position, &Rotation, &Collider), Without<Sensor>>,
colliders: &mut Vec<(Position, Rotation, Collider)>,
origin: Position,
q_collider: &Query<(&Transform, &Collider), Without<Sensor>>,
colliders: &mut Vec<(Vec3, Quat, Collider)>,
) {
if let Ok((&pos, &rot, col)) = q_collider.get(candidate) {
let pos = pos.0 - origin.0;
colliders.push((pos.into(), rot, col.clone()));
if let Ok((&transform, col)) = q_collider.get(candidate) {
colliders.push((transform.translation, transform.rotation, col.clone()));
}
if let Ok(children) = q_collider_ancestor.get(candidate) {
for child in children.iter() {
Expand All @@ -39,7 +45,6 @@ fn rigid_body_compound_collider_recursive(
q_collider_ancestor,
q_collider,
colliders,
origin,
);
}
}
Expand Down

0 comments on commit 08ca297

Please sign in to comment.