#mesh #path-finding #navigation #recast #generate #region

recast-rs

来自 recastnavigation 的 Recast 的绑定

1 个不稳定版本

0.1.0 2023年5月10日

#1977 in 游戏开发

自定义许可

120KB
3K SLoC

recast-rs

Rust 对 recastnavigation 的绑定。

入门

Recast 实际上是一个从几何体生成导航网格的工具箱。生成导航网格的一个好起点是

  1. 创建一个 Heightfield
  2. 将三角形光栅化到 Heightfield 中。请考虑将三角形标记为可通行的。
  3. Heightfield 中创建一个 CompactHeightfield
  4. (可选) 消蚀可通行区域。
  5. (可选) 使用盒子、圆柱或凸多边形标记区域。
  6. CompactHeightfield 构建区域。
  7. CompactHeightfield (带区域) 创建一个 ContourSet
  8. ContourSet 创建一个 PolyMesh
  9. 使用 PolyMesh 数据作为导航网格。

作为这个过程的简单示例

use recast_rs::*;

fn generate_nav_mesh(
  vertices: &[Vec3<f32>],
  triangles: &[Vec3<i32>],
) -> Result<Vec<Vec<Vec3<f32>>>, ()> {
  let mut context = Context::new();

  let (min_bounds, max_bounds) = util::calculate_bounds(vertices);

  let mut heightfield = Heightfield::new(
    &mut context,
    min_bounds,
    max_bounds,
    /* cell_horizontal_size */ 1.0,
    /* cell_height= */ 1.0,
  )?;

  let mut area_ids = vec![0; triangles.len()];
  util::mark_walkable_triangles(
    &mut context,
    /* walkable_slope_angle= */ 45.0,
    vertices,
    triangles,
    &mut area_ids,
  );

  heightfield.rasterize_indexed_triangles_i32(
    &mut context,
    vertices,
    triangles,
    &area_ids,
    /* flag_merge_threshold= */ 1,
  )?;

  let mut compact_heightfield = CompactHeightfield::<NoRegions>::new(
    &heightfield,
    &mut context,
    /* walkable_height= */ 3,
    /* walkable_climb= */ 1,
  )?;

  compact_heightfield
    .erode_walkable_area(&mut context, /* radius= */ 1)?;

  let compact_heightfield = compact_heightfield.build_regions(
    &mut context,
    /* border_size= */ 0,
    /* min_region_area= */ 0,
    /* merge_region_area= */ 0,
  )?;

  let contour_set = ContourSet::new(
    &compact_heightfield,
    &mut context,
    /* max_error= */ 1.0,
    /* max_edge_len= */ 10,
    ContourBuildFlags {
      tessellate_wall_edges: true,
      tessellate_area_edges: false,
    },
  )?;

  let poly_mesh = PolyMesh::new(
    &contour_set,
    &mut context,
    /* max_vertices_per_polygon= */ 8,
  )?;

  Ok(
    poly_mesh
      .polygons_iter()
      .map(|polygon| {
        polygon
          .valid_vertices()
          .iter()
          .map(|&vertex_index| poly_mesh.vertex(vertex_index as usize).as_f32())
          .collect()
      })
      .collect(),
  )
}

注意在这个例子中,我们只为每个多边形创建一个 Vec,用组成该多边形的顶点填充。实际上,你可能想要提取每个多边形的邻接信息,以便将其用作导航网格。

许可

MIT 许可 下许可。

依赖

~1.6–3.5MB
~81K SLoC