Перейти к содержанию

Python API

Python-биндинги реализованы через nanobind и разделены на два модуля.

Модуль termin.colliders (_colliders_native)

Геометрические примитивы и запросы.

Типы

from termin.colliders import (
    ColliderType,      # enum: Box, Sphere, Capsule
    Collider,          # базовый интерфейс
    ColliderPrimitive, # примитив с transform
    BoxCollider,
    SphereCollider,
    CapsuleCollider,
    AttachedCollider,
    UnionCollider,
    Ray3,
    RayHit,
    ColliderHit,
)

Создание коллайдеров

from termin.geombase import Vec3, GeneralPose3

# Box
box = BoxCollider(half_size=Vec3(1, 0.5, 0.3))
box = BoxCollider.from_size(Vec3(2, 1, 0.6))

# Sphere
sphere = SphereCollider(radius=0.5)

# Capsule
capsule = CapsuleCollider(half_height=0.5, radius=0.25)
capsule = CapsuleCollider.from_total_height(1.5, radius=0.25)

# С трансформом
box = BoxCollider(Vec3(1, 1, 1), transform=GeneralPose3(...))

Запросы

# Raycast
ray = Ray3(origin=Vec3(0, 0, 5), direction=Vec3(0, 0, -1))
hit = box.closest_to_ray(ray)
if hit.hit():
    print(hit.point_on_collider, hit.distance)

# Коллизия между коллайдерами
result = box.closest_to_collider(sphere)
if result.colliding():
    print(result.normal, result.distance, result.point_on_a, result.point_on_b)

AttachedCollider

attached = AttachedCollider(collider=box, transform=entity_transform)
print(attached.world_transform())
print(attached.colliding(other_collider))
print(attached.distance(other_collider))

UnionCollider

union = UnionCollider()
union.add(box)
union.add(sphere)
# или
union = UnionCollider([box, sphere])

Velocity hints

collider.linear_velocity = Vec3(1, 0, 0)
collider.angular_velocity = Vec3(0, 0, 3.14)
vel = collider.point_velocity(world_point)

Модуль termin.collision (_collision_native)

CollisionWorld, BVH, контактные данные.

Типы

from termin.collision import (
    CollisionWorld,
    BVH,
    ContactManifold,
    ContactPoint,
    ContactID,
    RayHit,        # расширенная версия с collider pointer
    ColliderPair,
)

CollisionWorld

world = CollisionWorld()

# Управление
world.add(collider)
world.remove(collider)
world.update_pose(collider)
world.update_all()

# Детекция
manifolds = world.detect_contacts()
for m in manifolds:
    print(m.collider_a, m.collider_b, m.normal)
    for pt in m.get_points():
        print(pt.position, pt.penetration)

# Raycast
hits = world.raycast(ray)
closest = world.raycast_closest(ray)

# AABB-запрос
colliders = world.query_aabb(aabb)

# Из сцены
world = CollisionWorld.from_scene(scene)

ContactManifold

m.collider_a        # Collider*
m.collider_b        # Collider*
m.normal             # Vec3
m.point_count        # int
m.get_points()       # list[ContactPoint]
m.same_pair(other)   # bool
m.pair_key()         # uint64

BVH

bvh = world.bvh  # read-only доступ

bvh.insert(collider, aabb)
bvh.remove(collider)
bvh.update(collider, new_aabb)

# Запросы
colliders = bvh.query_aabb(aabb)
hits = bvh.query_ray(ray)        # list[(collider, t_min, t_max)]
pairs = bvh.query_all_pairs()    # list[(collider_a, collider_b)]

bvh.node_count()
bvh.compute_height()
bvh.validate()

Зависимости модулей

_collision_native
├── _colliders_native
├── _geom_native (termin.geombase)
└── _entity_native (termin.entity)

_colliders_native
└── _geom_native (termin.geombase)