diff --git a/Cargo.toml b/Cargo.toml
index 4d7fb08..c949e5c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -18,7 +18,6 @@ default = []
rapier = ["bevy_rapier3d"]
xpbd = ["bevy_xpbd_3d"]
debug_draw = ["bevy/bevy_gizmos"]
-trace = []
[[example]]
name = "rapier3d"
@@ -68,3 +67,8 @@ bevy = { version = "0.11", default-features = false, features = [
"zstd",
] }
futures-lite = "1.13"
+criterion = { version = "0.5" }
+
+[[bench]]
+name = "simple_geometry"
+harness = false
\ No newline at end of file
diff --git a/benches/simple_geometry.rs b/benches/simple_geometry.rs
new file mode 100644
index 0000000..91d1441
--- /dev/null
+++ b/benches/simple_geometry.rs
@@ -0,0 +1,97 @@
+use bevy::prelude::{UVec2, Transform, Vec3};
+use criterion::{Criterion, criterion_group, criterion_main, black_box};
+use oxidized_navigation::{build_tile_sync, NavMeshSettings, conversion::{GeometryToConvert, GeometryCollection, ColliderType}};
+use parry3d::shape::Cuboid;
+
+
+fn generate_single_primitive_geometry() {
+ let tile_coord = UVec2::new(0, 0);
+ let heightfields = vec![];
+
+
+ let geometry_collections = vec![
+ GeometryCollection {
+ transform: Transform::from_xyz(0.0, 0.0, 0.0),
+ geometry_to_convert: GeometryToConvert::Collider(ColliderType::Cuboid(Cuboid::new(Vec3::new(10.0, 0.2, 10.0).into()))),
+ area: None
+ }
+ ];
+ let nav_mesh_settings = NavMeshSettings {
+ cell_width: 0.25,
+ cell_height: 0.1,
+ tile_width: 100,
+ world_half_extents: 12.5,
+ world_bottom_bound: -100.0,
+ max_traversable_slope_radians: (40.0_f32 - 0.1).to_radians(),
+ walkable_height: 20,
+ walkable_radius: 1,
+ step_height: 3,
+ min_region_area: 100,
+ merge_region_area: 500,
+ max_contour_simplification_error: 1.1,
+ max_edge_length: 80,
+ max_tile_generation_tasks: Some(1),
+ };
+
+ black_box(build_tile_sync(geometry_collections, tile_coord, heightfields, &nav_mesh_settings));
+}
+
+fn generate_many_primitive_geometry() {
+ let tile_coord = UVec2::new(0, 0);
+ let heightfields = vec![];
+
+
+ let geometry_collections = vec![
+ GeometryCollection {
+ transform: Transform::from_xyz(0.0, 0.0, 0.0),
+ geometry_to_convert: GeometryToConvert::Collider(ColliderType::Cuboid(Cuboid::new(Vec3::new(10.0, 0.2, 10.0).into()))),
+ area: None
+ },
+ GeometryCollection {
+ transform: Transform::from_xyz(5.0, 1.0, 0.0),
+ geometry_to_convert: GeometryToConvert::Collider(ColliderType::Cuboid(Cuboid::new(Vec3::new(1.0, 1.0, 1.0).into()))),
+ area: None
+ },
+ GeometryCollection {
+ transform: Transform::from_xyz(-5.0, 1.0, 2.0),
+ geometry_to_convert: GeometryToConvert::Collider(ColliderType::Cuboid(Cuboid::new(Vec3::new(4.0, 1.0, 1.0).into()))),
+ area: None
+ },
+ GeometryCollection {
+ transform: Transform::from_xyz(-2.5, 2.0, 2.0),
+ geometry_to_convert: GeometryToConvert::Collider(ColliderType::Cuboid(Cuboid::new(Vec3::new(1.0, 2.0, 1.0).into()))),
+ area: None
+ },
+ GeometryCollection {
+ transform: Transform::from_xyz(-2.5, 2.0, -2.0),
+ geometry_to_convert: GeometryToConvert::Collider(ColliderType::Cuboid(Cuboid::new(Vec3::new(1.0, 2.0, 1.0).into()))),
+ area: None
+ }
+ ];
+ let nav_mesh_settings = NavMeshSettings {
+ cell_width: 0.25,
+ cell_height: 0.1,
+ tile_width: 100,
+ world_half_extents: 12.5,
+ world_bottom_bound: -100.0,
+ max_traversable_slope_radians: (40.0_f32 - 0.1).to_radians(),
+ walkable_height: 20,
+ walkable_radius: 1,
+ step_height: 3,
+ min_region_area: 100,
+ merge_region_area: 500,
+ max_contour_simplification_error: 1.1,
+ max_edge_length: 80,
+ max_tile_generation_tasks: Some(1),
+ };
+
+ black_box(build_tile_sync(geometry_collections, tile_coord, heightfields, &nav_mesh_settings));
+}
+
+fn criterion_benchmark(c: &mut Criterion) {
+ c.bench_function("Generate Single Primitive Geometry", |b| b.iter(generate_single_primitive_geometry));
+ c.bench_function("Generate Many Primitive Geometry", |b| b.iter(generate_many_primitive_geometry));
+}
+
+criterion_group!(benches, criterion_benchmark);
+criterion_main!(benches);
\ No newline at end of file
diff --git a/src/conversion.rs b/src/conversion.rs
index a9d3009..cc0ebcb 100644
--- a/src/conversion.rs
+++ b/src/conversion.rs
@@ -7,13 +7,13 @@ use parry3d::{
use crate::{heightfields::TriangleCollection, Area};
-pub(super) struct GeometryCollection {
- pub(super) transform: Transform,
- pub(super) geometry_to_convert: GeometryToConvert,
- pub(super) area: Option,
+pub struct GeometryCollection {
+ pub transform: Transform,
+ pub geometry_to_convert: GeometryToConvert,
+ pub area: Option,
}
-pub(super) enum ColliderType {
+pub enum ColliderType {
Cuboid(Cuboid),
Ball(Ball),
Capsule(Capsule),
@@ -22,7 +22,7 @@ pub(super) enum ColliderType {
Triangle(Triangle),
}
-pub(super) enum GeometryToConvert {
+pub enum GeometryToConvert {
Collider(ColliderType),
ParryTriMesh(Vec>, Vec<[u32; 3]>),
}
diff --git a/src/heightfields.rs b/src/heightfields.rs
index 50773a7..c9c5d43 100644
--- a/src/heightfields.rs
+++ b/src/heightfields.rs
@@ -58,10 +58,10 @@ pub(super) struct TriangleCollection {
pub(super) area: Option,
}
-pub(super) struct HeightFieldCollection {
- pub(super) transform: Transform,
- pub(super) heightfield: Arc,
- pub(super) area: Option,
+pub struct HeightFieldCollection {
+ pub transform: Transform,
+ pub heightfield: Arc,
+ pub area: Option,
}
pub(super) fn build_heightfield_tile(
diff --git a/src/lib.rs b/src/lib.rs
index 6f49c06..8bb3dbc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -49,11 +49,11 @@ use parry3d::na::Vector3;
use parry3d::shape::{HeightField, TypedShape};
use regions::build_regions;
use smallvec::SmallVec;
-use tiles::{create_nav_mesh_tile_from_poly_mesh, NavMeshTiles};
+use tiles::{create_nav_mesh_tile_from_poly_mesh, NavMeshTiles, NavMeshTile};
pub mod colliders;
mod contour;
-mod conversion;
+pub mod conversion;
#[cfg(feature = "debug_draw")]
pub mod debug_draw;
mod heightfields;
@@ -614,8 +614,23 @@ async fn build_tile(
nav_mesh: Arc>,
) {
#[cfg(feature = "trace")]
- let _span = info_span!("Build Tile").entered();
+ let _span = info_span!("Async build Tile").entered();
+ let nav_mesh_tile = build_tile_sync(geometry_collections, tile_coord, heightfields, &nav_mesh_settings);
+
+ let Ok(mut nav_mesh) = nav_mesh.write() else {
+ error!("Nav-Mesh lock has been poisoned. Generation can no longer be continued.");
+ return;
+ };
+
+ if nav_mesh.tile_generations.get(&tile_coord).unwrap_or(&0) < &generation {
+ nav_mesh.tile_generations.insert(tile_coord, generation);
+
+ nav_mesh.add_tile(tile_coord, nav_mesh_tile, &nav_mesh_settings);
+ }
+}
+
+pub fn build_tile_sync(geometry_collections: Vec, tile_coord: UVec2, heightfields: Vec, nav_mesh_settings: &NavMeshSettings) -> NavMeshTile {
let triangle_collection = {
#[cfg(feature = "trace")]
let _span = info_span!("Convert Geometry Collections").entered();
@@ -629,61 +644,51 @@ async fn build_tile(
tile_coord,
triangle_collection,
heightfields,
- &nav_mesh_settings,
+ nav_mesh_settings,
)
};
let mut open_tile = {
#[cfg(feature = "trace")]
let _span = info_span!("Build Open Heightfield Tile").entered();
- build_open_heightfield_tile(voxelized_tile, &nav_mesh_settings)
+ build_open_heightfield_tile(voxelized_tile, nav_mesh_settings)
};
// Remove areas that are too close to a wall.
{
#[cfg(feature = "trace")]
let _span = info_span!("Erode walkable area").entered();
- erode_walkable_area(&mut open_tile, &nav_mesh_settings);
+ erode_walkable_area(&mut open_tile, nav_mesh_settings);
}
{
#[cfg(feature = "trace")]
let _span = info_span!("Calculate distance field").entered();
- calculate_distance_field(&mut open_tile, &nav_mesh_settings);
+ calculate_distance_field(&mut open_tile, nav_mesh_settings);
}
{
#[cfg(feature = "trace")]
let _span = info_span!("Build regions").entered();
- build_regions(&mut open_tile, &nav_mesh_settings);
+ build_regions(&mut open_tile, nav_mesh_settings);
}
let contour_set = {
#[cfg(feature = "trace")]
let _span = info_span!("Build contours").entered();
- build_contours(open_tile, &nav_mesh_settings)
+ build_contours(open_tile, nav_mesh_settings)
};
let poly_mesh = {
#[cfg(feature = "trace")]
let _span = info_span!("Build poly mesh").entered();
- build_poly_mesh(contour_set, &nav_mesh_settings)
+ build_poly_mesh(contour_set, nav_mesh_settings)
};
- let nav_mesh_tile = {
+
+ {
#[cfg(feature = "trace")]
let _span = info_span!("Create nav-mesh tile from poly mesh").entered();
- create_nav_mesh_tile_from_poly_mesh(poly_mesh, tile_coord, &nav_mesh_settings)
- };
-
- let Ok(mut nav_mesh) = nav_mesh.write() else {
- error!("Nav-Mesh lock has been poisoned. Generation can no longer be continued.");
- return;
- };
-
- if nav_mesh.tile_generations.get(&tile_coord).unwrap_or(&0) < &generation {
- nav_mesh.tile_generations.insert(tile_coord, generation);
-
- nav_mesh.add_tile(tile_coord, nav_mesh_tile, &nav_mesh_settings);
+ create_nav_mesh_tile_from_poly_mesh(poly_mesh, tile_coord, nav_mesh_settings)
}
}