Skip to content

Commit

Permalink
Use shape cast for more accuracy
Browse files Browse the repository at this point in the history
  • Loading branch information
janhohenheim committed Aug 21, 2024
1 parent 0d8b2fb commit 6cb677d
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 21 deletions.
2 changes: 1 addition & 1 deletion examples/full_setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn main() {
DefaultPlugins,
WorldInspectorPlugin::new(),
PhysicsPlugins::default(),
//PhysicsDebugPlugin::default(),
PhysicsDebugPlugin::default(),
AvianPickupPlugin::default(),
))
.add_systems(Startup, setup)
Expand Down
52 changes: 32 additions & 20 deletions src/interaction/hold/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,19 +133,48 @@ pub(super) fn update_object(
// actor's origins if possible instead.
let max_distance = preferred_distance.max(min_distance);

let terrain_hit = spatial_query.cast_ray(
let Some(actor_space_rotation) = preferred_rotation
.map(|preferred| preferred.0)
.or_else(|| pre_pickup_rotation.map(|pre| pre.0))
else {
error!("Held prop does not have a preferred or pre-pickup rotation. Ignoring.");
continue;
};
// orient the prop wrt the actor
// The 2013 code uses the non-clamped code here, resulting in the prop
// rotating when looking further up than the clamp allows.
// Looks weird imo, so we use the clamped rotation.
let clamped_actor_transform = actor_transform.with_rotation(clamped_rotation);
let target_rotation =
prop_rotation_from_actor_space(actor_space_rotation, clamped_actor_transform);

shadow.target_rotation = target_rotation;

// The cast needs to be longer to account for the fact that
// the prop might hit terrain with the side that is not facing
// the player. We are assuming the prop has the same radius
// "behind" it as it has in front of it. Also add a bit of
// padding to be safe.
let max_cast_toi = max_distance + min_distance + 0.5;

let terrain_hit = spatial_query.cast_shape(
&prop_collider,
actor_transform.translation,
target_rotation,
forward,
max_distance,
max_cast_toi,
true,
&config.terrain_filter,
);
let distance = if let Some(terrain_hit) = terrain_hit {
let fraction = terrain_hit.time_of_impact / max_distance;
info!("fraction: {}", fraction);
if fraction < 0.5 {
info!("min distance");
min_distance
} else {
max_distance
info!("far terrain hit");
max_distance.min(terrain_hit.time_of_impact)
}
} else {
max_distance
Expand All @@ -155,23 +184,6 @@ pub(super) fn update_object(
// distance
let target_position = actor_transform.translation + forward * distance;
shadow.target_position = target_position;

let Some(actor_space_rotation) = preferred_rotation
.map(|preferred| preferred.0)
.or_else(|| pre_pickup_rotation.map(|pre| pre.0))
else {
error!("Held prop does not have a preferred or pre-pickup rotation. Ignoring.");
continue;
};
// orient the prop wrt the actor
// The 2013 code uses the non-clamped code here, resulting in the prop
// rotating when looking further up than the clamp allows.
// Looks weird imo, so we use the clamped rotation.
let clamped_actor_transform = actor_transform.with_rotation(clamped_rotation);
let target_rotation =
prop_rotation_from_actor_space(actor_space_rotation, clamped_actor_transform);

shadow.target_rotation = target_rotation;
}
}

Expand Down

0 comments on commit 6cb677d

Please sign in to comment.