개요
Box3D는 이식 가능한 C17 물리 엔진으로, 연속 충돌 감지, 소프트 스텝 강체 솔버 및 데이터 지향 설계를 갖추고 있습니다. 멀티스레딩, SIMD 및 크로스 플랫폼 결정성을 지원하며 대규모 강체 스태킹 시나리오에 적합합니다.
README 미리보기
# Box3D\n\n[](https://github.com/erincatto/box3d/actions)\n[](https://cla-assistant.io/erincatto/box3d)\n\n\n\nBox3D is a 3D physics engine for games.\n\n[](https://www.youtube.com/watch?v=jr_Fzl2XwKU)\n\n## Features\n\n### Collision\n\n- Continuous collision detection\n- Contact events\n- Convex hulls, capsules, spheres, triangle meshes, and height fields\n- Multiple shapes per body\n- Collision filtering\n- Ray casts, shape casts, and overlap queries\n- Sensor system\n- Character mover\n\n### Physics\n\n- Robust _Soft Step_ rigid body solver\n- Continuous physics for fast translations and rotations\n- Island based sleep\n- Revolute, prismatic, distance, motor, weld, and wheel joints\n- Joint limits, motors, springs, and friction\n- Joint and contact forces\n- Body movement events and sleep notification\n\n### System\n\n- Data-oriented design\n- Written in portable C17\n- Extensive multithreading and SIMD\n- Optimized for large piles of bodies\n- Cross platform determinism\n- Recording and replay\n\n### Samples\n\n- Uses sokol to run with D3D11 on Windows, Metal on macOS, and OpenGL 4.5 on Linux.\n- Graphical user interface with imgui.\n- Many samples to demonstrate features and performance.\n\n## Building all platforms\n\n- Install [CMake](https://cmake.org/)\n- Install [git](https://git-scm.com/)\n- Ensure these run from the command line\n\n## Building with CMake presets (recommended)\n\nThis uses the presets in `CMakePresets.json`.\n\n- Windows: `cmake --preset windows` then `cmake --build --preset windows-release`\n- Linux: `cmake --preset linux-release` then `cmake --build --preset linux-release`\n- macOS: `cmake --preset macos` then `cmake --build --preset macos-release`\n- Windows MinGW: `cmake --preset mingw-release` then `cmake --build --preset mingw-release`\n\nRun the samples app (must be in the Box3D directory).\n\n- Windows: `.\build\bin\Release\samples.exe`\n- Linux: `./build/bin/samples`\n- macOS: `./build/bin/Release/samples`\n\n## Building for Visu
FAQ (5)
문제 해결Box3D에서 voxel 모양의 box hull을 많이 생성할 때 b3AddHullToDatabase가 매우 느린 이유는 무엇인가요?
성능 저하는 심각한 해시 테이블 충돌로 인해 발생합니다. 기존의 djb2 스타일 헐 해시는 0.25f의 배수처럼 규칙적인 간격으로 배치된 float 좌표를 충분히 혼합하지 못했고, 버킷 선택에는 해시의 하위 비트(hash & buckets_mask)만 사용되었습니다. 이로 인해 수천 개의 복셀 헐이 동일한 버킷 체인에 매핑될 수 있었으며, 반복적인 헐 비교와 과도한 테이블 증가가 발생했습니다. 이 문제는 PR #126에서 개선된 64비트 헐 해시를 사용하여 수정되었습니다. Box3D를 해당 PR이 포함된 버전으로 업데이트하십시오. 보고된 3,000개 헐 재현 사례에서 이 수정은 소요 시간을 약 159.9 ms에서 3.9 ms로, 버킷 수를 2,097,152에서 4,096으로 줄였습니다. 임시 해결 방법으로 1.0e-4f와 같은 작은 고유 지터를 헐 오프셋에 추가할 수 있지만, 이는 콜라이더 지오메트리를 변경하므로 정확한 복셀 정렬이 필요한 경우에는 피해야 합니다.
문제 해결Box3D 월드를 스텝할 때 b3FreeElement에서 발생하는 UBSan misaligned address 패닉을 어떻게 해결하나요?
크래시는 b3Manifold가 268바이트이기 때문에 발생합니다. 홀수 개의 매니폴드가 함께 패킹되면 다음 요소가 8바이트 경계에서 4바이트 벗어난 위치에서 시작할 수 있는데, b3FreeElement는 8바이트 정렬이 필요한 void*를 그 위치에 저장합니다.
b3CreateBlockAllocator(block_allocator.c)에서 각 할당자 요소 크기를 포인터 정렬에 맞게 올림하여 이 문제를 수정합니다:
elementSize = (elementSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
이는 요소 크기가 블록/프리 리스트 초기화에 사용되기 전에 적용해야 합니다. 영향을 받는 64비트 플랫폼에서는 sizeof(void *)를 사용하는 것으로 충분합니다. 64바이트 캐시 라인 크기로 올림해도 동작하지만 공간을 더 많이 낭비합니다.
Box3D v0.1.0에서는 이 정렬 패치를 적용하거나, 임시 해결 방법으로 Box3D 타겟에 대한 정렬 검사만 비활성화하세요:
-fno-sanitize=alignment
모든 새니타이제이션을 비활성화해도 패닉을 피할 수 있지만, 패치가 적용될 때까지 ASan/UBSan을 활성화한 상태로 유지하면서 정렬 검사만 억제하는 것이 더 바람직합니다.
문제 해결collideConnected가 false로 설정된 조인트를 생성한 후에도 두 Box3D 바디가 여전히 충돌하는 문제를 어떻게 해결하나요?
이 문제는 조인트를 생성하면 이후의 충돌 필터링은 변경되지만, 두 바디 사이에 이미 존재하는 b3Contact 객체는 파괴되지 않기 때문에 발생합니다. 이 문제는 Box3D PR #157에서 공식적으로 수정되었으므로, 해당 PR이 포함된 Box3D 버전으로 업데이트하세요. 이전 버전에서의 해결 방법으로는, 조인트를 생성한 직후 다음 시뮬레이션 스텝이 실행되기 전에 연결된 바디들 사이의 콘택트를 명시적으로 파괴하세요. 예를 들어 jointDef.collideConnected == false인 경우 b3DestroyContactsBetweenBodies(world, bodyA, bodyB)를 호출합니다.
문제 해결Box3D b3World_Step가 깊이 겹친 동적 바디를 얇은 정적 벽을 통과하게 밀어내는 문제를 해결하는 방법은?
이는 예상된 솔버 동작이며, Box3D의 버그가 아닙니다. "속도를 0으로 설정하고, b3World_Step을 호출하고, 반복하는" 패턴은 지원되는 준정적(quasi-static) 침투 해제 방법이 아닙니다. 큰 동적 바디의 중심이 얇은 벽의 반대편을 넘어가면, 접촉 솔버는 어느 쪽을 "방 안쪽"으로 의도했는지 추론할 수 없습니다. 솔버는 현재 접촉 법선을 따라 해결하는데, 이 법선이 반대쪽을 가리킬 수 있으므로 반복적인 보정이 누적되어 오브젝트를 더 멀리 밀어냅니다.
다음 접근 방법 중 하나를 사용하세요:
1. **스텝 전에 깊은 겹침을 방지하세요.** 스폰하거나 드래그된 포즈를 수락하기 전에 벽 콜라이더에 대해 오버랩/셰이프 캐스트 쿼리를 실행하세요. b3World_Step을 호출하기 전에 후보 포즈를 거부하거나 올바른 벽면으로 클램프하세요.
2. **진입 측면을 명시적으로 추적하세요.** 오브젝트가 내부 쪽에 있었다면 interiorWallFace - objectHalfExtent로 다시 투영하세요. 중심이 벽을 넘은 후에 솔버가 그 쪽을 선택해 줄 것이라고 기대하지 마세요.
3. **모터 조인트로 드래깅을 구동하세요.** 동적 아이템에 대해 모터 조인트를 생성하고 포인터 타겟을 향해 타겟 변환/선형 오프셋을 업데이트하세요. 충분한 maxForce와 maxTorque를 설정한 다음, 접촉 제약이 벽에서 멈추도록 하세요. b3Body_SetLinearVelocity를 사용한 후 속도를 0으로 하는 스텝을 위치 완화 수단으로 사용하지 마세요.
4. **이미 유효하지 않은 상태를 수동으로 복구하세요.** 바디가 이미 깊게 침투했거나 벽 중심선을 넘어간 상태라면, 스텝하기 전에 알려진 비침투 변환으로 되돌리세요.
연속 충돌을 활성화하면 고속 터널링을 방지하는 데 도움이 되지만, 처음부터 유효하지 않은 깊게 겹친 배치는 해결해 주지 않습니다. 이 동작은 커밋 3fc20f5b45 및 30c67b5e6d에서 확인되었으며, 유지 관리자는 오버랩 검증과 모터 조인트 사용을 권장합니다.
문제 해결왜 제 mover가 거의 수직에 가깝거나 얕은 각도로 이동할 때 메시 삼각형 가장자리에 걸리나요?
이 문제는 mover shape cast 중 backside 삼각형 충돌로 인해 발생합니다. 이는 PR #130에서 수정되었습니다. 해당 PR이 포함된 물리 엔진 빌드로 업데이트한 후 다시 빌드하세요. 이제 shape cast는 mesh와 height-field 삼각형에 대한 backside 충돌을 무시하여 ray-cast 동작과 일치하며, mover 충돌에는 더 부드러운 접촉에 필요한 삼각형 정보가 포함됩니다. 사용자 정의 mesh를 정의하는 경우 삼각형 winding을 확인하고 새로운 b3MeshDef clockwise 옵션(및 stride)을 올바르게 설정하세요.