Skip to content

Commit

Permalink
add agent_radius to aabb obstacles
Browse files Browse the repository at this point in the history
  • Loading branch information
nickydonna committed Sep 11, 2024
1 parent efabded commit 9eaca93
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 47 deletions.
8 changes: 2 additions & 6 deletions examples/demo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,8 @@ fn life_of_obstacle(
if cachable.remove(&entity) {
commands.entity(entity).remove::<CachableObstacle>();
}
} else {
if example_settings.cache_enabled {
if cachable.insert(entity) {
commands.entity(entity).insert(CachableObstacle);
}
}
} else if example_settings.cache_enabled && cachable.insert(entity) {
commands.entity(entity).insert(CachableObstacle);
}
}
}
Expand Down
43 changes: 43 additions & 0 deletions examples/helpers/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use vleue_navigator::prelude::*;
pub enum UiSettings {
Simplify,
MergeSteps,
AgentRadius,
Cache,
}

Expand All @@ -14,6 +15,8 @@ pub enum UiSettingsButtons {
SimplifyDec,
MergeStepsInc,
MergeStepsDec,
AgentRadiusInc,
AgentRadiusDec,
ToggleCache,
}

Expand Down Expand Up @@ -137,6 +140,36 @@ pub fn setup_settings<const WITH_CACHE: bool>(mut commands: Commands) {
button(" - ", UiSettingsButtons::MergeStepsDec, parent);
button(" + ", UiSettingsButtons::MergeStepsInc, parent);
});
parent
.spawn(NodeBundle { ..default() })
.with_children(|parent| {
parent.spawn((
TextBundle {
text: Text::from_sections(
[("Agent Radius: ", 30.0), ("{}", 30.0)].into_iter().map(
|(text, font_size): (&str, f32)| {
TextSection::new(
text,
TextStyle {
font_size,
..default()
},
)
},
),
),
style: Style {
margin: UiRect::all(Val::Px(12.0)),
..default()
},
..default()
}
.with_text_justify(JustifyText::Right),
UiSettings::AgentRadius,
));
button(" - ", UiSettingsButtons::AgentRadiusDec, parent);
button(" + ", UiSettingsButtons::AgentRadiusInc, parent);
});
if WITH_CACHE {
parent
.spawn((
Expand Down Expand Up @@ -187,6 +220,9 @@ pub fn display_settings(
UiSettings::MergeSteps => {
text.sections[1].value = format!("{}", settings.merge_steps)
}
UiSettings::AgentRadius => {
text.sections[1].value = format!("{}", settings.agent_radius)
}
UiSettings::Cache => (),
}
}
Expand All @@ -196,6 +232,7 @@ pub fn display_settings(
match param {
UiSettings::Simplify => (),
UiSettings::MergeSteps => (),
UiSettings::AgentRadius => (),
UiSettings::Cache => {
*color = if example_settings.cache_enabled {
palettes::tailwind::GREEN_400.into()
Expand Down Expand Up @@ -233,6 +270,12 @@ pub fn update_settings<const STEP: u32>(
UiSettingsButtons::MergeStepsInc => {
settings.merge_steps = (settings.merge_steps + 1).min(5);
}
UiSettingsButtons::AgentRadiusDec => {
settings.agent_radius = (settings.agent_radius - 0.5).max(0.0);
}
UiSettingsButtons::AgentRadiusInc => {
settings.agent_radius = (settings.agent_radius + 0.5).min(10.0);
}
UiSettingsButtons::ToggleCache => {
example_settings.cache_enabled = !example_settings.cache_enabled;
}
Expand Down
1 change: 1 addition & 0 deletions src/obstacles/aabb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ impl ObstacleSource for Aabb {
obstacle_transform: &GlobalTransform,
navmesh_transform: &Transform,
(up, _shift): (Dir3, f32),
agent_radius: f32,
) -> Vec<Vec2> {
let transform = obstacle_transform.compute_transform();
let world_to_mesh = world_to_mesh(navmesh_transform);
Expand Down
10 changes: 7 additions & 3 deletions src/obstacles/avian2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@ impl ObstacleSource for Collider {
obstacle_transform: &GlobalTransform,
navmesh_transform: &Transform,
up: (Dir3, f32),
agent_radius: f32,
) -> Vec<Vec2> {
self.shape_scaled()
.as_typed_shape()
.get_polygon(obstacle_transform, navmesh_transform, up)
self.shape_scaled().as_typed_shape().get_polygon(
obstacle_transform,
navmesh_transform,
up,
agent_radius,
)
}
}

Expand Down
11 changes: 8 additions & 3 deletions src/obstacles/avian3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@ impl ObstacleSource for Collider {
obstacle_transform: &GlobalTransform,
navmesh_transform: &Transform,
up: (Dir3, f32),
agent_radius: f32,
) -> Vec<Vec2> {
self.shape_scaled()
.as_typed_shape()
.get_polygon(obstacle_transform, navmesh_transform, up)
self.shape_scaled().as_typed_shape().get_polygon(
obstacle_transform,
navmesh_transform,
up,
agent_radius,
)
}
}

Expand All @@ -32,6 +36,7 @@ trait InnerObstacleSource {
obstacle_transform: &GlobalTransform,
navmesh_transform: &Transform,
up: (Dir3, f32),
agent_radius: f32,
) -> Vec<Vec2>;
}

Expand Down
13 changes: 10 additions & 3 deletions src/obstacles/cached.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,19 @@ impl<T: ObstacleSource> ObstacleSource for CachedObstacle<T> {
obstacle_transform: &GlobalTransform,
navmesh_transform: &Transform,
up: (Dir3, f32),
agent_radius: f32,
) -> Vec<Vec2> {
self.polygon
.get_or_init(|| {
T::get_polygon(&self.source, obstacle_transform, navmesh_transform, up)
.into_iter()
.collect::<Vec<_>>()
T::get_polygon(
&self.source,
obstacle_transform,
navmesh_transform,
up,
agent_radius,
)
.into_iter()
.collect::<Vec<_>>()
})
.clone()
}
Expand Down
1 change: 1 addition & 0 deletions src/obstacles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ pub trait ObstacleSource: Component + Clone {
obstacle_transform: &GlobalTransform,
navmesh_transform: &Transform,
up: (Dir3, f32),
agent_radius: f32,
) -> Vec<Vec2>;
}
50 changes: 22 additions & 28 deletions src/obstacles/primitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ impl ObstacleSource for PrimitiveObstacle {
obstacle_transform: &GlobalTransform,
navmesh_transform: &Transform,
(up, _shift): (Dir3, f32),
agent_radius: f32,
) -> Vec<Vec2> {
let transform = obstacle_transform.compute_transform();
let world_to_mesh = world_to_mesh(navmesh_transform);
Expand All @@ -94,36 +95,32 @@ impl ObstacleSource for PrimitiveObstacle {
let to_navmesh = |v: Vec3| world_to_mesh.transform_point3(v).xy();

match self {
PrimitiveObstacle::Rectangle(primitive) => vec![
to_navmesh(to_world(vec2(
-primitive.half_size.x,
-primitive.half_size.y,
))),
to_navmesh(to_world(vec2(
-primitive.half_size.x,
primitive.half_size.y,
))),
to_navmesh(to_world(vec2(primitive.half_size.x, primitive.half_size.y))),
to_navmesh(to_world(vec2(
primitive.half_size.x,
-primitive.half_size.y,
))),
],
PrimitiveObstacle::Rectangle(primitive) => {
let x = primitive.half_size.x + agent_radius;
let y = primitive.half_size.y + agent_radius;
vec![
to_navmesh(to_world(vec2(-x, -y))),
to_navmesh(to_world(vec2(-x, y))),
to_navmesh(to_world(vec2(x, y))),
to_navmesh(to_world(vec2(x, -y))),
]
}
PrimitiveObstacle::Circle(primitive) => {
copypasta::ellipse_inner(vec2(primitive.radius, primitive.radius), RESOLUTION)
let with_radius = primitive.radius + agent_radius;
copypasta::ellipse_inner(vec2(with_radius, with_radius), RESOLUTION)
.map(|v| to_navmesh(to_world(v)))
.collect()
}
PrimitiveObstacle::Ellipse(primitive) => {
copypasta::ellipse_inner(primitive.half_size, RESOLUTION)
copypasta::ellipse_inner(primitive.half_size + agent_radius, RESOLUTION)
.map(|v| to_navmesh(to_world(v)))
.collect()
}
PrimitiveObstacle::CircularSector(primitive) => {
let mut arc = copypasta::arc_2d_inner(
0.0,
primitive.arc.angle() as f64,
primitive.arc.radius,
primitive.arc.radius + agent_radius,
RESOLUTION,
)
.map(|v| to_navmesh(to_world(v)))
Expand All @@ -134,7 +131,7 @@ impl ObstacleSource for PrimitiveObstacle {
PrimitiveObstacle::CircularSegment(primitive) => copypasta::arc_2d_inner(
0.0,
primitive.arc.angle() as f64,
primitive.arc.radius,
primitive.arc.radius + agent_radius,
RESOLUTION,
)
.map(|v| to_navmesh(to_world(v)))
Expand All @@ -143,7 +140,7 @@ impl ObstacleSource for PrimitiveObstacle {
let mut points = copypasta::arc_2d_inner(
0.0,
std::f64::consts::PI,
primitive.radius,
primitive.radius + agent_radius,
RESOLUTION,
)
.map(|v| to_navmesh(to_world(v + primitive.half_length * Vec2::Y)))
Expand All @@ -152,7 +149,7 @@ impl ObstacleSource for PrimitiveObstacle {
copypasta::arc_2d_inner(
0.0,
std::f64::consts::PI,
primitive.radius,
primitive.radius + agent_radius,
RESOLUTION,
)
.map(|v| {
Expand All @@ -167,21 +164,18 @@ impl ObstacleSource for PrimitiveObstacle {
PrimitiveObstacle::RegularPolygon(primitive) => (0..=primitive.sides)
.map(|p| {
copypasta::single_circle_coordinate(
primitive.circumcircle.radius,
primitive.circumcircle.radius + agent_radius,
primitive.sides as u32,
p,
)
})
.map(|v| to_navmesh(to_world(v)))
.collect(),
PrimitiveObstacle::Rhombus(primitive) => {
let x = primitive.half_diagonals.x + agent_radius;
let y = primitive.half_diagonals.y + agent_radius;
[(1.0, 0.0), (0.0, 1.0), (-1.0, 0.0), (0.0, -1.0)]
.map(|(sign_x, sign_y)| {
Vec2::new(
primitive.half_diagonals.x * sign_x,
primitive.half_diagonals.y * sign_y,
)
})
.map(|(sign_x, sign_y)| Vec2::new(x * sign_x, y * sign_y))
.into_iter()
.map(|v| to_navmesh(to_world(v)))
.collect()
Expand Down
11 changes: 7 additions & 4 deletions src/updater.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ pub struct NavMeshSettings {
///
/// if feature `detailed-layers` is enabled, it's also used for path finding to change the traversal cost of this layer.
pub scale: Vec2,
/// Agent radius used to increase the size of obstacles so that path can avoid them
pub agent_radius: f32,
}

impl Default for NavMeshSettings {
Expand All @@ -108,6 +110,7 @@ impl Default for NavMeshSettings {
layer: None,
stitches: vec![],
scale: Vec2::ONE,
agent_radius: 0.0,
}
}
}
Expand Down Expand Up @@ -157,9 +160,9 @@ fn build_navmesh<T: ObstacleSource>(
let up = (mesh_transform.forward(), settings.upward_shift);
let base = if settings.cached.is_none() {
let mut base = settings.fixed;
let obstacle_polys = cached_obstacles
.iter()
.map(|(transform, obstacle)| obstacle.get_polygon(transform, &mesh_transform, up));
let obstacle_polys = cached_obstacles.iter().map(|(transform, obstacle)| {
obstacle.get_polygon(transform, &mesh_transform, up, settings.agent_radius)
});
base.add_obstacles(obstacle_polys);
if settings.simplify != 0.0 {
base.simplify(settings.simplify);
Expand All @@ -175,7 +178,7 @@ fn build_navmesh<T: ObstacleSource>(
.iter()
.map(|(transform, obstacle)| {
obstacle
.get_polygon(transform, &mesh_transform, up)
.get_polygon(transform, &mesh_transform, up, settings.agent_radius)
.into_iter()
.map(|v| v / scale)
.collect()
Expand Down

0 comments on commit 9eaca93

Please sign in to comment.