5.2 KiB
5.2 KiB
Phase 5-1: Collision Detection — Design Spec
Overview
voltex_physics crate에 충돌 감지 시스템을 구현한다.
Broad phase (BVH) + Narrow phase (전용 함수) 구조로, Sphere와 Box 콜라이더를 지원한다.
Dependencies
voltex_math— Vec3, Mat4, AABB(신규)voltex_ecs— World, Entity, Transform, SparseSet
Module Structure
crates/voltex_physics/
├── Cargo.toml
└── src/
├── lib.rs — public exports
├── aabb.rs — AABB type (voltex_math에 추가)
├── collider.rs — Collider enum
├── contact.rs — ContactPoint
├── bvh.rs — BvhTree (broad phase)
├── narrow.rs — sphere_vs_sphere, sphere_vs_box, box_vs_box
└── collision.rs — detect_collisions (ECS 통합)
참고: AABB는 voltex_math에 추가한다 (스펙에 명시된 기본 수학 타입).
Types
AABB (voltex_math에 추가)
#[derive(Debug, Clone, Copy)]
pub struct AABB {
pub min: Vec3,
pub max: Vec3,
}
Methods:
new(min, max) -> Selffrom_center_half_extents(center, half_extents) -> Selfcenter() -> Vec3half_extents() -> Vec3contains_point(point: Vec3) -> boolintersects(other: &AABB) -> boolmerged(other: &AABB) -> AABB— 두 AABB를 감싸는 최소 AABBsurface_area() -> f32— BVH SAH 비용 계산용
Collider (voltex_physics)
#[derive(Debug, Clone, Copy)]
pub enum Collider {
Sphere { radius: f32 },
Box { half_extents: Vec3 },
}
- ECS 컴포넌트로 사용. 형상(shape)만 저장.
- 위치는 같은 entity의
Transform.position에서 가져온다. aabb(&self, position: Vec3) -> AABB— broad phase용 바운딩 박스 생성
ContactPoint (voltex_physics)
#[derive(Debug, Clone, Copy)]
pub struct ContactPoint {
pub entity_a: Entity,
pub entity_b: Entity,
pub normal: Vec3, // A에서 B 방향 단위 법선
pub depth: f32, // 침투 깊이 (양수 = 겹침)
pub point_on_a: Vec3, // A 표면의 접촉점
pub point_on_b: Vec3, // B 표면의 접촉점
}
BvhTree (voltex_physics)
바이너리 트리. 각 리프는 하나의 Entity + AABB.
pub struct BvhTree {
nodes: Vec<BvhNode>,
}
enum BvhNode {
Leaf { entity: Entity, aabb: AABB },
Internal { aabb: AABB, left: usize, right: usize },
}
Methods:
build(entries: &[(Entity, AABB)]) -> Self— 중앙값 분할(median split)로 구축. 가장 긴 축 기준 정렬 후 이분.query_pairs(&self) -> Vec<(Entity, Entity)>— 트리 순회로 AABB가 겹치는 리프 쌍 반환.
매 프레임 rebuild한다 (동적 씬 대응). 최적화(incremental update)는 성능 문제 발생 시 추후 적용.
Narrow Phase Functions (voltex_physics::narrow)
모든 함수는 위치(Vec3)와 형상 파라미터를 받아 Option<ContactPoint>를 반환한다.
Entity 정보는 호출부에서 채운다.
pub fn sphere_vs_sphere(
pos_a: Vec3, radius_a: f32,
pos_b: Vec3, radius_b: f32,
) -> Option<(Vec3, f32, Vec3, Vec3)> // (normal, depth, point_a, point_b)
pub fn sphere_vs_box(
sphere_pos: Vec3, radius: f32,
box_pos: Vec3, half_extents: Vec3,
) -> Option<(Vec3, f32, Vec3, Vec3)>
pub fn box_vs_box(
pos_a: Vec3, half_a: Vec3,
pos_b: Vec3, half_b: Vec3,
) -> Option<(Vec3, f32, Vec3, Vec3)>
box_vs_box: SAT (Separating Axis Theorem) 기반. 축 정렬(AABB vs AABB)만 지원한다. 회전된 OBB는 Convex Hull 추가 시 GJK/EPA로 대체.
ECS Integration (voltex_physics::collision)
pub fn detect_collisions(world: &World) -> Vec<ContactPoint>
Transform+Collider를 가진 entity를query2로 수집- 각 entity의 AABB 계산 (
collider.aabb(transform.position)) BvhTree::build()→query_pairs()로 broad phase 후보 추출- 각 후보 쌍에 대해 collider 타입 조합에 맞는 narrow phase 함수 호출
- 접촉이 있으면
ContactPoint에 entity 정보를 채워 결과에 추가
Conventions
- 법선(normal): entity_a에서 entity_b 방향
- 침투 깊이(depth): 양수 = 겹침, 0 이하 = 접촉 없음
- 좌표계: 기존 voltex_math 규약 (오른손 좌표계)
- WGSL vec3 alignment 규칙은 AABB에 해당 없음 (GPU에 올리지 않음)
Test Plan
voltex_math (AABB)
new,from_center_half_extents생성center,half_extents계산contains_point: 내부/외부/경계intersects: 겹침/분리/접선merged: 두 AABB 합집합surface_area: 정확도
voltex_physics
- narrow::sphere_vs_sphere: 겹침, 분리, 접선, 완전 포함
- narrow::sphere_vs_box: 면/모서리/꼭짓점 접촉, 분리, 내부 포함
- narrow::box_vs_box: 각 축 겹침, 분리, 접선
- collider::aabb: Sphere/Box의 AABB 생성
- bvh::build: 빈 입력, 단일, 다수 엔트리
- bvh::query_pairs: 겹치는 쌍 정확성, 분리된 쌍 미포함
- collision::detect_collisions: ECS 통합 E2E
Out of Scope (Phase 5-1)
- Capsule, Convex Hull 콜라이더
- GJK/EPA 알고리즘
- 회전된 박스(OBB) 충돌
- 리지드바디 시뮬레이션 (Phase 5-2)
- 레이캐스팅 (Phase 5-3)
- 연속 충돌 감지 (CCD)