simvx.core.collision

Collision system — shapes, broadphase AABB grid, narrowphase GJK/SAT, raycasting.

Module Contents

Classes

CollisionShape

Abstract base for collision shapes.

SphereShape

Sphere collision shape defined by a radius.

BoxShape

Axis-aligned box collision shape defined by half-extents.

ConvexShape

Convex hull collision shape built from a set of vertices.

CapsuleShape

Capsule collision shape — cylinder with hemispherical caps along the Y axis.

SpatialHashGrid

Uniform-grid spatial hash for broadphase collision culling.

RayHit

Result of a raycast query.

ShapeCastResult

Result of a shape cast (swept shape) query.

CollisionWorld

Broadphase (AABB) + narrowphase (GJK) collision world.

Data

API

simvx.core.collision.__all__

[‘CollisionShape’, ‘SphereShape’, ‘BoxShape’, ‘ConvexShape’, ‘CapsuleShape’, ‘SpatialHashGrid’, ‘Ray…

class simvx.core.collision.CollisionShape

Abstract base for collision shapes.

Subclasses must implement get_aabb() for broadphase and support() for GJK narrowphase intersection testing.

abstractmethod get_aabb(position: numpy.ndarray) tuple[numpy.ndarray, numpy.ndarray]

Return (min_corner, max_corner) in world space.

abstractmethod support(position: numpy.ndarray, direction: numpy.ndarray) numpy.ndarray

GJK support function: furthest point in given direction.

class simvx.core.collision.SphereShape(radius: float = 1.0)

Bases: simvx.core.collision.CollisionShape

Sphere collision shape defined by a radius.

Initialization

__slots__

(‘radius’,)

get_aabb(position: numpy.ndarray) tuple[numpy.ndarray, numpy.ndarray]

Returns AABB for a sphere at the given position.

support(position: numpy.ndarray, direction: numpy.ndarray) numpy.ndarray

Returns the furthest point on the sphere in the given direction.

class simvx.core.collision.BoxShape(half_extents: tuple[float, float, float] = (0.5, 0.5, 0.5))

Bases: simvx.core.collision.CollisionShape

Axis-aligned box collision shape defined by half-extents.

Initialization

__slots__

(‘half_extents’,)

get_aabb(position: numpy.ndarray) tuple[numpy.ndarray, numpy.ndarray]

Returns AABB for a box at the given position.

support(position: numpy.ndarray, direction: numpy.ndarray) numpy.ndarray

Returns the furthest vertex of the box in the given direction.

class simvx.core.collision.ConvexShape(vertices: numpy.ndarray)

Bases: simvx.core.collision.CollisionShape

Convex hull collision shape built from a set of vertices.

Vertices are stored in local space and translated to world space during AABB and support queries.

Initialization

__slots__

(‘vertices’,)

get_aabb(position: numpy.ndarray) tuple[numpy.ndarray, numpy.ndarray]

Returns AABB bounding the convex hull at the given position.

support(position: numpy.ndarray, direction: numpy.ndarray) numpy.ndarray

Returns the vertex with maximum projection onto the direction.

class simvx.core.collision.CapsuleShape(radius: float = 0.5, height: float = 2.0)

Bases: simvx.core.collision.CollisionShape

Capsule collision shape — cylinder with hemispherical caps along the Y axis.

Initialization

__slots__

(‘radius’, ‘height’)

get_aabb(position: numpy.ndarray) tuple[numpy.ndarray, numpy.ndarray]

Returns AABB for a capsule at the given position.

The capsule is oriented along the Y axis. The half-height of the cylindrical segment is (height / 2 - radius) (clamped to 0), plus the radius of the hemispherical caps gives a total Y extent of height / 2.

support(position: numpy.ndarray, direction: numpy.ndarray) numpy.ndarray

Returns the furthest point on the capsule in the given direction.

The capsule is the Minkowski sum of a line segment (along Y) and a sphere of the given radius. The support point is the center of whichever hemisphere is more aligned with direction, offset by radius in the normalised direction.

class simvx.core.collision.SpatialHashGrid(cell_size: float = 2.0)

Uniform-grid spatial hash for broadphase collision culling.

Maps axis-aligned bounding boxes to grid cells so that overlap queries only need to check bodies in neighbouring cells rather than every body in the world.

Initialization

__slots__

(‘cell_size’, ‘_inv_cell’, ‘_grid’)

insert(body_id: int, aabb_min: numpy.ndarray, aabb_max: numpy.ndarray) None

Insert a body into all grid cells its AABB overlaps.

query(aabb_min: numpy.ndarray, aabb_max: numpy.ndarray) set[int]

Return body IDs in cells that overlap the given AABB.

clear() None

Reset the grid for the next frame.

class simvx.core.collision.RayHit

Result of a raycast query.

Attributes: body: The collider reference that was hit. point: World-space hit position. distance: Distance from ray origin to the hit point.

body: Any

None

point: numpy.ndarray

None

distance: float

None

class simvx.core.collision.ShapeCastResult

Result of a shape cast (swept shape) query.

body: Any

None

point: numpy.ndarray

None

normal: numpy.ndarray

None

distance: float

None

fraction: float

None

class simvx.core.collision.CollisionWorld(use_spatial_hash: bool = False, cell_size: float = 2.0)

Broadphase (AABB) + narrowphase (GJK) collision world.

Bodies are registered with a shape, position, and collision layer/mask. Supports overlap queries between bodies and raycasting against all bodies.

Args: use_spatial_hash: When True, uses a :class:SpatialHashGrid for broadphase culling instead of brute-force AABB checks. cell_size: Grid cell size for the spatial hash (ignored when use_spatial_hash is False).

Initialization

add_body(body: Any, shape: simvx.core.collision.CollisionShape, position: numpy.ndarray | None = None, layer: int = 1, mask: int = 1) None

Register a body with a collision shape.

remove_body(body: Any) None

Unregister a body.

update_position(body: Any, position: numpy.ndarray) None

Update a body’s position and recompute its AABB.

When the spatial hash is enabled the grid is rebuilt lazily before the next :meth:query_overlaps call via :meth:rebuild_spatial_hash.

rebuild_spatial_hash() None

Rebuild the spatial hash grid from all current bodies.

query_overlaps(body: Any) list[Any]

Find all bodies overlapping with the given body.

When the spatial hash is enabled, only candidate bodies from neighbouring grid cells are checked instead of the entire world.

test_overlap(body_a: Any, body_b: Any) bool

Test if two specific bodies overlap.

raycast(origin: numpy.ndarray, direction: numpy.ndarray, max_dist: float = 1000.0, layer_mask: int = 4294967295) list[simvx.core.collision.RayHit]

Cast a ray and return all hits sorted by ascending distance.

Uses AABB broadphase to cull, then shape-specific narrowphase for spheres and boxes. ConvexShape falls back to AABB hit distance.

shape_cast(shape: simvx.core.collision.CollisionShape, from_pos: numpy.ndarray, to_pos: numpy.ndarray, layer_mask: int = 4294967295, exclude: set | None = None, max_results: int = 32) list[simvx.core.collision.ShapeCastResult]

Sweep a shape from from_pos to to_pos and return all intersecting bodies.

Uses binary search along the sweep path to find the first contact fraction for each candidate body. Results sorted by distance.

property body_count: int