simvx.core.navigation3d.mesh¶
NavigationMesh3D — triangle-based navmesh with A* pathfinding.
Module Contents¶
Classes¶
3D navigation mesh with triangle-based A* pathfinding. |
Data¶
API¶
- class simvx.core.navigation3d.mesh.NavigationMesh3D[source]¶
3D navigation mesh with triangle-based A* pathfinding.
Stores walkable geometry as triangles and builds an adjacency graph for pathfinding. Supports manual polygon insertion and automated bake from level geometry.
Initialization
- property vertices: numpy.ndarray¶
(N, 3) float32 array of mesh vertices.
- property triangles: numpy.ndarray¶
(M, 3) int32 array of triangle vertex indices.
- property triangle_count: int¶
- add_polygon(vertices: list[simvx.core.math.types.Vec3], cell_size: float = 0.0) → None[source]¶
Add a walkable polygon.
Without
cell_sizethe polygon is fan-triangulated from the first vertex (fast, 2 triangles for a quad). Whencell_sizeis positive the polygon’s axis-aligned bounding box is subdivided into a regular grid of right-triangles, keeping only cells whose centres fall inside the polygon. The finer mesh is required for obstacle carving to work at useful resolution.Args: vertices: 3+ coplanar points defining the polygon boundary. cell_size: When > 0, grid cell size for subdivision. Typical values: 0.5 – 2.0 depending on obstacle density.
- add_triangle(v0: simvx.core.math.types.Vec3, v1: simvx.core.math.types.Vec3, v2: simvx.core.math.types.Vec3) → None[source]¶
Add a single walkable triangle.
- add_obstacle(vertices: list[simvx.core.math.types.Vec3]) → None[source]¶
Subtract an obstacle region from the walkable area.
The polygon is projected onto the XZ plane. Any navmesh triangle whose centroid falls inside the obstacle polygon (or whose area overlaps it significantly) is marked as blocked and excluded from pathfinding.
Args: vertices: 3+ points defining the obstacle boundary (Y is ignored).
- bake_from_geometry(mesh_vertices: numpy.ndarray, mesh_indices: numpy.ndarray, agent_radius: float = 0.5, agent_height: float = 2.0, max_slope: float = 45.0, cell_size: float = 0.3, cell_height: float = 0.2) → None[source]¶
Generate navmesh from level geometry using simplified Recast-style algorithm.
Steps: 1. Voxelize geometry into a height field 2. Mark walkable voxels (slope < max_slope, clearance > agent_height) 3. Build regions from connected walkable areas 4. Extract contours and triangulate
Args: mesh_vertices: (N, 3) float32 array of source mesh vertices. mesh_indices: (M, 3) int32 array of triangle indices. agent_radius: Agent capsule radius for erosion. agent_height: Minimum clearance height. max_slope: Maximum walkable slope in degrees. cell_size: Horizontal voxel size. cell_height: Vertical voxel size.
- find_path(start: simvx.core.math.types.Vec3, end: simvx.core.math.types.Vec3) → list[simvx.core.math.types.Vec3][source]¶
A* pathfinding on the navmesh triangle graph.
Finds the shortest path from start to end by searching through connected triangles. Returns a list of waypoints (triangle centroids + start/end) forming the path, or an empty list if no path exists.
Args: start: Start position in world space. end: End position in world space.
Returns: List of Vec3 waypoints, or empty list if unreachable.
- get_closest_point(point: simvx.core.math.types.Vec3) → simvx.core.math.types.Vec3[source]¶
Snap a point to the nearest navmesh surface.
Args: point: Query point in world space.
Returns: Closest point on the navmesh surface.
- is_point_on_mesh(point: simvx.core.math.types.Vec3, tolerance: float = 0.5) → bool[source]¶
Test if a point is on the walkable area.
Args: point: Query point in world space. tolerance: Maximum distance from navmesh surface to still count.
Returns: True if point is within tolerance of the navmesh.
- sample_position(center: simvx.core.math.types.Vec3, radius: float, max_attempts: int = 30) → simvx.core.math.types.Vec3 | None[source]¶
Sample a random point near center that lies on the navmesh.
Args: center: Center of the sampling sphere. radius: Maximum distance from center. max_attempts: Number of random samples to try.
Returns: A random point on the navmesh within radius, or None if not found.