Collision & Physics

SimVX provides broadphase (AABB) + narrowphase (GJK) collision detection and raycasting.

Collision Shapes

Three built-in shape types:

from simvx.core import SphereShape, BoxShape, ConvexShape

sphere = SphereShape(radius=1.0)
box = BoxShape(half_extents=(0.5, 0.5, 0.5))
hull = ConvexShape(vertices=my_vertex_array)  # numpy Nx3

Each shape implements get_aabb() for broadphase and support() for GJK narrowphase.

Collision World

Register bodies and query overlaps:

from simvx.core import CollisionWorld, SphereShape
import numpy as np

world = CollisionWorld()

# Register bodies with shapes and positions
world.add_body(player, SphereShape(1.0), position=np.array([0, 0, 0]))
world.add_body(enemy, SphereShape(1.5), position=np.array([3, 0, 0]))

# Update positions each frame
world.update_position(player, new_pos)

# Query overlaps
hits = world.query_overlaps(player)  # returns list of overlapping bodies

# Test specific pair
if world.test_overlap(player, enemy):
    print("Collision!")

Collision Layers

Filter collisions with layer/mask bitmasks:

world.add_body(bullet, SphereShape(0.1), position=pos, layer=2, mask=4)
world.add_body(enemy, SphereShape(1.0), position=pos, layer=4, mask=2)

Raycasting

Cast rays through the collision world:

hits = world.raycast(
    origin=np.array([0, 1, 0]),
    direction=np.array([0, 0, -1]),
    max_dist=100.0,
    layer_mask=0xFFFFFFFF,
)

for hit in hits:
    print(f"Hit {hit.body} at distance {hit.distance}")
    print(f"Point: {hit.point}")

Node-Based Collision

For simpler cases, use CharacterBody3D with CollisionShape3D:

from simvx.core import CharacterBody3D

class Bullet(CharacterBody3D):
    def __init__(self):
        super().__init__(collision=0.5)  # sphere radius
        self.velocity = Vec3(0, 0, -20)

    def physics_process(self, dt):
        self.move_and_slide(dt)
        for enemy in self.get_overlapping(group="enemies"):
            enemy.destroy()

API Reference

See simvx.core.collision for the complete collision API.