libm만 필요). 데이터 지향 설계·SIMD·멀티스레딩·크로스플랫폼 결정론을 정면에 내세운다.
(저장소: erincatto/box3d · MIT 라이선스 · 최초 릴리스 v0.1.0 (2026-06-30, 알파) · TrendShift Daily 9위)
이 저장소가 대체 무엇인가.
게임에서 상자가 바닥에 떨어져 구르고, 캐릭터가 벽에 부딪혀 멈추고, 자동차 바퀴가 서스펜션에 눌리는 장면을 떠올려 보자. 이 모든 움직임 뒤에는 매 순간 "이 물체가 다음 1/60초 동안 어디로, 얼마나 회전하며 움직여야 하는가"를 계산하는 수학 엔진이 있다. 그 계산을 전담하는 라이브러리가 물리 엔진이고, Box3D는 그 3차원 버전이다.
비유하면: 게임 개발자 = 무대 연출가, 물리 엔진 = 무대 위 모든 소품이 중력·마찰·충돌의 법칙을 따르게 만드는 보이지 않는 스태프. 연출가는 "상자를 여기 둬"라고 배치만 하면, 그다음 상자가 굴러 떨어지는 사실적인 움직임은 Box3D가 뉴턴 역학을 수치적으로 풀어서 만들어 낸다.
README의 자기소개는 딱 한 문장이다: "Box3D is a 3D physics engine for games." 하지만 이 담백한 한 줄 뒤에는 중요한 맥락이 있다. 저자 Erin Catto는 2007년부터 Box2D를 만들어 온 사람으로, Box2D는 앵그리버드류 물리 퍼즐부터 수많은 인디·상용 게임 엔진의 2D 물리 기반이 된 업계 표준급 오픈소스다. 그가 오랜 GDC(게임 개발자 컨퍼런스) 강연과 연구로 다듬은 물리 솔버 기법을 이제 3차원으로 확장한 것이 Box3D다.
실제로 저장소를 뜯어보면, 이것은 "장난감 예제"가 아니라 87개의 C 소스 파일로 이루어진 본격 엔진이다. 충돌 감지(broad/narrow phase), 강체 솔버, 8종의 관절(joint), 볼록 껍질(convex hull)·캡슐·구·삼각형 메시·높이 필드 충돌, 광선/도형 캐스트, 센서, 캐릭터 무버, 그리고 녹화·재생(recording/replay)과 크로스플랫폼 결정론까지 들어 있다. 핵심 라이브러리(box3d::box3d)는 C 런타임 외에 어떤 외부 라이브러리에도 의존하지 않는다 — 게임 엔진에 그대로 끼워 넣기 좋다는 뜻이다.
Box2D 창시자의 3D 후속작 · 갓 나온 v0.1.0 · "Soft Step" 솔버 · 결정론 · 무의존성 C17.
Box3D가 공개 직후 TrendShift 상위권에 오른 이유는 단순한 "새 물리 엔진"이어서가 아니다. Erin Catto라는 이름값과, 그가 십수 년간 발표해 온 솔버 연구가 마침내 3D로 결실을 맺었다는 서사 때문이다. 최초 릴리스 v0.1.0이 2026-06-30에 올라왔다 — 즉 이 문서를 쓰는 시점 기준 갓 며칠 된 따끈한 알파 소프트웨어다.
| 비교 축 | 기존 대표 엔진들 | Box3D의 접근 |
|---|---|---|
| 계보 | Bullet(범용), PhysX(NVIDIA), Jolt(Horizon 게임 출신) | 업계 표준 Box2D의 정통 3D 후속 — API 철학·솔버 계보가 이어짐 |
| 언어 | 대개 C++ (클래스·상속·템플릿) | 순수 C17 + 불투명 핸들 API — ABI 안정성·바인딩 용이 |
| 의존성 | 서드파티 수학/컨테이너 라이브러리 동반이 흔함 | 코어는 C 런타임 + libm뿐. 자체 컨테이너·할당자·해시테이블 내장 |
| 솔버 | 전통적 순차 임펄스(Sequential Impulse) 계열 | Catto의 "Soft Step" 소프트 제약 솔버 — 서브스텝 기반 안정성 |
| 결정론 | 플랫폼마다 부동소수점 결과가 미묘하게 달라지기 쉬움 | 크로스플랫폼 결정론을 명시적 설계 목표로 (-ffp-contract=off 등) |
| 재현성 | 별도 도구 필요 | 녹화·재생(recording/replay) 기능이 엔진에 내장 (recording_replay.c 116KB) |
README의 System 항목은 이 엔진의 성격을 압축한다. 객체 하나하나를 클래스 인스턴스로 다루는 전통적 OOP 대신, 같은 종류 데이터를 배열로 촘촘히 모아 CPU 캐시 적중률과 SIMD 벡터화를 극대화하는 데이터 지향 설계(DOD)를 택했다. "많은 물체 더미(large piles of bodies)에 최적화"라는 문구가 이를 뒷받침한다. 물리 엔진은 성능이 곧 생명인 분야라, 이 설계 선택 자체가 훌륭한 학습 교재가 된다.
릴리스 노트에서 저자 스스로 알파임을 명시한다. API는 앞으로 바뀔 수 있고, 문서(docs/)도 채워지는 중이며, Pull Request는 현재 막혀 있다(버그·기능 요청은 이슈로만 접수). 프로덕션 게임에 바로 넣기보다는, "최신 물리 엔진 아키텍처를 최고 수준 저자의 코드로 배우는 교재"이자 "장기적으로 지켜볼 프로젝트"로 접근하는 것이 현실적이다.
README 하단에는 흔치 않은 항목이 있다. 저자는 유닛 테스트·샘플 앱·Box2D↔Box3D 코드 이식·빌드 설정·코드 리뷰·벤치마킹에 LLM을 사용했고, 그 외 모든 코드는 자신이 직접 작성했으며 "모든 코드 한 줄 한 줄에 책임진다"고 밝힌다. AI 도구 사용이 일상이 된 시대에 오픈소스 저자가 사용 범위를 투명하게 밝힌 좋은 선례다.
C17 코어 라이브러리 + C++20 샘플 앱 + CMake 빌드 + SIMD + 크로스플랫폼 그래픽/디버깅 도구.
Box3D는 "엔진 코어"와 "그것을 눈으로 보여 주는 샘플 앱"을 명확히 분리한다. 코어는 그래픽이 전혀 없는 순수 계산 라이브러리이고, 샘플 앱은 그 결과를 3D로 그려 주는 별도 프로그램이다. 이 분리 덕분에 코어는 어떤 렌더러(Unity·Unreal·자작 엔진)에도 붙일 수 있다.
| 레이어 | 기술 / 버전 | 역할 |
|---|---|---|
| 코어 언어 | C17 (ISO C 2018) | 물리 엔진 본체. 클래스 대신 함수 + 불투명 핸들. ABI가 안정적이라 어떤 언어에서든 바인딩하기 쉬움 |
| 샘플 언어 | C++20 | 데모/테스트용 앱. 코어를 링크해 실제로 굴려 보는 놀이터 |
| 빌드 시스템 | CMake ≥ 3.22 + CMakePresets | Windows/Linux/macOS/Xcode/Emscripten 한 벌의 설정으로 관리 |
| SIMD 수학 | SSE2(x86) / Neon(ARM) | 벡터·행렬 연산을 한 번에 4개씩 처리. BOX3D_DISABLE_SIMD로 끌 수 있음 |
| 멀티스레딩 | 사용자 제공 태스크 시스템 (콜백 기반) | 엔진이 스레드를 직접 만들지 않고, 게임의 잡 시스템에 일을 넘길 수 있게 훅만 제공 |
| 샘플 그래픽 | sokol (D3D11 / Metal / OpenGL 4.5) | OS별 그래픽 API를 하나로 감싼 헤더 전용 라이브러리. Win=D3D11, mac=Metal, Linux=GL |
| 샘플 UI | Dear ImGui | 즉시 모드 GUI. 파라미터 슬라이더·디버그 패널을 즉석에서 그림 |
| WebAssembly | Emscripten (pthread + 메모리 성장) | 브라우저에서 돌아가는 WASM 빌드도 CMake에 준비되어 있음 |
| 프로파일링 | Tracy (BOX3D_PROFILE) | 프레임별 성능을 실시간 타임라인으로 뜯어보는 프로파일러(옵션) |
| 문서 | Doxygen (BOX3D_DOCS) | 헤더 주석에서 API 레퍼런스를 자동 생성 |
| 디버깅 보조 | .natvis + Sanitizer | Visual Studio에서 엔진 자료구조를 예쁘게 표시. ASan/TSan/UBSan/MSan 옵션 내장 |
| 테스트/벤치 | 자체 유닛 테스트 + benchmark/ | 내부 함수까지 검증하려 테스트는 정적 링크로 빌드 |
World world;처럼 구조체 내부를 노출하지만, Box3D는 b3WorldId·b3BodyId·b3ShapeId처럼 내부가 숨겨진 작은 정수 표(ID)만 건네준다. 사용자는 그 ID로 함수를 호출할 뿐, 물체의 실제 메모리 배치는 모른다. 장점: (1) 엔진이 내부 자료구조(예: 배열 재배치)를 자유롭게 바꿔도 사용자 코드가 안 깨진다, (2) 다른 언어(Python·Rust·C#)에서 바인딩하기 쉽다, (3) 잘못된 포인터 접근 위험이 준다. 데이터 지향 설계와 궁합이 좋은 선택이다.simd.c/simd.h에서 이 둘을 추상화하고, 필요하면 BOX3D_DISABLE_SIMD로 꺼서 순수 스칼라 코드로 되돌릴 수 있다(디버깅·이식용).한 번의 b3World_Step 안에서 벌어지는 일 — 브로드페이즈 → 내로우페이즈 → 제약 그래프 → Soft Step 솔버 → 적분.
물리 엔진의 심장은 b3World_Step(worldId, timeStep, subStepCount) 함수 하나다. 게임이 매 프레임 이 함수를 부르면, 엔진은 "지난 1/60초 동안 세계가 어떻게 변했는가"를 통째로 계산한다. 그 내부는 대략 이런 파이프라인으로 흐른다.
물체가 n개면 충돌 검사 조합은 순진하게 하면 n²이다. 1,000개면 50만 번. 이걸 피하려고 dynamic_tree.c(무려 54KB)가 AABB 트리(각 물체를 감싸는 축 정렬 상자를 계층 트리로 관리)를 유지한다. 두 물체의 감싸는 상자조차 안 겹치면 정밀 검사를 아예 건너뛴다. 이 단계에서 살아남은 소수의 "충돌 후보 쌍"만 다음 단계로 넘어간다.
후보 쌍이 정해지면 실제로 얼마나, 어디서 겹치는지 계산한다. 볼록 도형 사이 거리는 distance.c(47KB)의 GJK 알고리즘이 담당하고, 겹침이 확인되면 convex_manifold.c(50KB)·triangle_manifold.c·mesh_contact.c 등이 접촉 매니폴드(접촉점 좌표 + 파고든 깊이 + 밀어낼 법선 방향)를 만든다. 도형 종류별(구·캡슐·볼록껍질·삼각형 메시·높이 필드) 전용 코드가 나뉘어 있다.
여러 스레드가 동시에 물리를 풀 때 위험한 건, 두 스레드가 같은 물체를 동시에 수정하는 경우다(데이터 레이스). constraint_graph.c는 이를 그래프 색칠(graph coloring)로 막는다. 접촉·관절을 노드로 보고, "같은 물체를 공유하는 제약끼리는 다른 색"이 되도록 칠한다. 그러면 같은 색 그룹 안의 제약들은 절대 같은 물체를 건드리지 않으므로, 스레드들이 락 없이 병렬로 처리해도 안전하다. 색깔을 하나씩 순서대로 처리하되, 각 색 안에서는 마음껏 병렬화하는 것이다.
식당 주방에서 요리사 여러 명이 동시에 일한다. 두 사람이 같은 도마를 동시에 쓰면 사고가 난다. 그래서 "같은 도마를 쓰는 주문은 서로 다른 시간대(색)에 배정"하고, 같은 시간대에는 서로 다른 도마를 쓰는 주문만 몰아서 동시에 처리한다. 제약 그래프 색칠이 바로 이 스케줄링이다 — 충돌(도마 공유) 없는 작업만 묶어 병렬로 돌린다.
이 엔진의 이름값 있는 부분이다. 전통적 솔버는 "물체가 절대 겹치면 안 된다"는 딱딱한(hard) 제약을 강제하다가 펄쩍 튀거나 부들부들 떠는(jitter) 불안정을 겪곤 한다. Erin Catto가 GDC 강연들에서 다듬어 온 Soft Step(소프트 제약) 접근은, 제약을 "아주 뻣뻣하지만 감쇠가 있는 스프링"으로 모델링해 수치적으로 훨씬 안정적으로 만든다. 그리고 한 스텝(1/60초)을 subStepCount(기본 4)개의 서브스텝으로 잘게 나눠 반복한다 — 60Hz 겉보기로 돌리되 내부적으로는 240Hz로 제약을 여러 번 다잡는 셈이다.
// docs/hello.md 원문 — 서브스텝의 의미를 저자가 직접 설명
float timeStep = 1.0f / 60.0f; // 프레임레이트에 묶지 말 것 (고정 스텝 권장)
int subStepCount = 4; // 4로 나누면 제약이 240Hz로 풀림
b3World_Step(worldId, timeStep, subStepCount); // 매 틱 1회 호출
// "More sub-steps improve accuracy at the cost of performance."
서로 접촉·관절로 연결된 물체 무리를 아일랜드(island)라 부른다(island.c). 한 아일랜드의 모든 물체가 충분히 오래 거의 안 움직이면, 엔진은 그 무리를 "잠재워(sleep)" 다음 스텝부터 계산에서 빼 버린다. 바닥에 쌓여 정지한 상자 100개를 매 프레임 다시 푸는 건 낭비이기 때문이다. 새 충돌이 들어오면 그 아일랜드만 다시 깨운다. 이것이 "많은 물체 더미에 최적화"의 핵심 비결 중 하나다.
Box3D는 크로스플랫폼 결정론을 설계 목표로 못 박았다. 같은 입력을 주면 Windows·Linux·macOS에서 비트 단위로 동일한 시뮬레이션 결과가 나오도록 하는 것이다. 이를 위해 CMake에서 -ffp-contract=off(부동소수점 곱셈-덧셈 융합 최적화 차단)를 켜 컴파일러가 결과를 미묘하게 바꾸는 걸 막는다. 그 위에 recording_replay.c(116KB)·world_snapshot.c가 얹혀, 시뮬레이션을 녹화했다가 나중에 똑같이 재생할 수 있다.
결정론이 보장되면 온라인 게임에서 각 클라이언트가 물리를 따로 돌려도 결과가 일치해(락스텝) 네트워크로 위치 전체를 안 보내도 된다. 또 e스포츠 리플레이를 "입력만 저장 → 재생"으로 가볍게 만들 수 있고, 물리 버그가 정확히 재현되어 디버깅이 쉬워진다. 결정론은 물리 엔진에서 "있으면 좋은" 게 아니라 특정 장르에선 필수 인프라다.
최상위 레이아웃 + src/ 87개 소스 파일을 역할별로 묶어서.
진짜 알맹이인 src/의 87개 파일을 역할별로 묶으면 물리 엔진의 해부도가 보인다.
파일 크기가 곧 "복잡도 지도"다. physics_world.c(130KB)가 오케스트라 지휘자, contact_solver.c(78KB)·solver.c(79KB)가 안정성을 책임지는 심장, hull.c·mesh.c·distance.c가 "어디서 부딪혔나"를 재는 측량 팀, recording_replay.c(116KB)가 결정론을 지키는 블랙박스다. 처음 읽는다면 docs/hello.md → include/box3d/box3d.h(공개 API) → samples/ 순서로, 내부 구현(src)은 필요할 때만 파고드는 게 좋다.
이 저장소에서 실제로 무엇을 배울 수 있는가 + 각 주제 실습 아이디어.
Box3D는 물체를 Body 객체 하나하나로 흩어 두지 않고, 같은 속성끼리 배열로 모아 캐시 친화적으로 배치한다. solver_set.c·arena_allocator.c를 읽으며 "왜 OOP 대신 이렇게 짰는가"를 따라가면 성능 지향 아키텍처의 사고방식을 얻는다.
실습: 같은 물체 1만 개를 (a) 객체 배열, (b) 속성별 배열(SoA)로 각각 순회하며 시간을 재 캐시 효과를 체감해 보기.
include/box3d/만 봐도 "사용자에게 무엇을 숨기고 무엇을 보여줄지"에 대한 모범 답안이 보인다. Def 구조체 + b3Default***Def() 패턴은 "C에는 생성자가 없다"는 제약을 우아하게 푸는 방법이다.
실습: 내 작은 C 라이브러리(예: 간단한 파일 파서)를 불투명 핸들 + Default-Def 패턴으로 리팩터링해 보기.
solver.c·contact_solver.c와 Erin Catto의 공개 GDC 슬라이드를 함께 보면, "왜 딱딱한 제약이 튀는가"와 "서브스텝·소프트 제약이 왜 안정적인가"를 이론+코드로 배울 수 있다. 게임 물리를 넘어 로보틱스·시뮬레이션에도 통하는 지식이다.
실습: 스프링-질량 하나를 오일러 적분 vs 세미-임플리싯 적분으로 각각 구현해, 큰 스텝에서 어느 쪽이 폭발하는지 관찰.
dynamic_tree.c는 게임·GIS·레이트레이싱에 두루 쓰이는 동적 AABB 트리(BVH)의 실전 구현이다. 삽입·삭제·재균형·질의를 어떻게 빠르게 유지하는지가 다 들어 있다.
실습: 2D 점 1만 개에 대한 간단한 AABB 트리를 만들어, "반경 안의 이웃 찾기"를 브루트포스와 속도 비교.
constraint_graph.c + parallel_for.c는 "데이터 레이스를 자료구조 수준에서 원천 차단"하는 고급 패턴을 보여준다. 뮤텍스로 막는 대신, 애초에 충돌하지 않는 작업만 묶어 병렬로 돌린다.
실습: 그래프 색칠로 스레드에 작업을 배분하는 미니 스케줄러를 만들어, 뮤텍스 버전과 성능 비교.
-ffp-contract=off 한 줄의 의미를 파고들면 FMA(융합 곱셈-덧셈), 컴파일러 재배치, x87 vs SSE 정밀도 같은 부동소수점의 함정을 배운다. 네트워크 게임·리플레이를 만들려면 반드시 아는 지식이다.
실습: 같은 부동소수점 누적 연산을 최적화 플래그를 바꿔 컴파일해, 결과가 달라지는지 확인.
samples/는 헤더 전용 라이브러리 sokol로 세 OS의 그래픽 API를 하나로 감싸고, Dear ImGui로 디버그 UI를 즉석에서 그린다. "렌더러와 물리 코어를 어떻게 깔끔히 분리하는가"의 좋은 예다.
실습: 샘플 하나를 골라 파라미터(중력·마찰·서브스텝)를 ImGui 슬라이더로 바꿔 가며 거동 변화를 관찰.
코어를 빌드하려면 무엇이 필요한가.
| 항목 | 요구사항 |
|---|---|
| 코어 컴파일러 | C17 지원 컴파일러 (MSVC, GCC, Clang) |
| 샘플 컴파일러 | C++20 지원 컴파일러 (샘플 앱을 빌드할 때만) |
| 빌드 도구 | CMake ≥ 3.22 + git (명령줄에서 실행 가능해야) |
| 운영체제 | Windows · Linux · macOS 모두 빌드/실행 (샘플 포함) |
| CPU 명령어 | SSE2(x86) 또는 Neon(ARM) — BOX3D_DISABLE_SIMD로 끌 수 있음 |
| 그래픽(샘플) | Windows=D3D11 · macOS=Metal · Linux=OpenGL 4.5 |
| 정밀도 옵션 | 기본 float(단정밀도). 큰 세계엔 BOX3D_DOUBLE_PRECISION(double) |
| 추가 도구(옵션) | Doxygen(문서), Tracy(프로파일), Emscripten(WASM), sokol-shdc(셰이더) |
| 라이선스 | MIT — 상용 게임에도 자유롭게 사용 가능 |
float로 계산한다 — 빠르고 대부분 게임에 충분하다. 다만 아주 넓은 오픈월드(좌표가 커질수록 float 오차가 커짐)에서는 BOX3D_DOUBLE_PRECISION으로 64비트 double을 켤 수 있다. 또 엔진은 미터·킬로그램·초(MKS) 단위에 맞춰 튜닝되어 있어, "1m 크기 물체"처럼 현실 규모로 다뤄야 안정적이다(빙하나 먼지 크기는 float 한계를 벗어난다고 문서가 경고한다).난이도별 5단계 — 빌드하고, 굴려 보고, 붙여 쓰고, 뜯어보기.
공식 docs/hello.md의 최소 예제를 그대로 따라 해 본다. 그래픽 없이 콘솔에 상자가 y=4에서 떨어져 y≈1에 멈추는 좌표가 찍힌다. 물리 엔진 사용의 전체 뼈대(세계 생성 → 물체·도형 붙이기 → 스텝 루프 → 정리)를 30줄로 체득하는 것이 목표.
// 핵심 골격 (docs/hello.md 요약, C)
#include <box3d/box3d.h>
#include <stdio.h>
int main(void) {
b3WorldDef worldDef = b3DefaultWorldDef(); // 기본값 채우기
worldDef.gravity = (b3Vec3){ 0.0f, -10.0f, 0.0f };
b3WorldId world = b3CreateWorld(&worldDef);
// 바닥(정적 물체)
b3BodyDef groundDef = b3DefaultBodyDef();
groundDef.position = (b3Vec3){ 0.0f, -10.0f, 0.0f };
b3BodyId ground = b3CreateBody(world, &groundDef);
b3BoxHull groundBox = b3MakeBoxHull(50.0f, 10.0f, 50.0f); // 절반 크기(half-extent)
b3ShapeDef gsd = b3DefaultShapeDef();
b3CreateHullShape(ground, &gsd, &groundBox.base);
// 떨어지는 상자(동적 물체)
b3BodyDef boxDef = b3DefaultBodyDef();
boxDef.type = b3_dynamicBody; // 안 켜면 안 떨어진다!
boxDef.position = (b3Vec3){ 0.0f, 4.0f, 0.0f };
b3BodyId body = b3CreateBody(world, &boxDef);
b3BoxHull cube = b3MakeCubeHull(1.0f);
b3ShapeDef sd = b3DefaultShapeDef();
sd.density = 1.0f; sd.baseMaterial.friction = 0.3f; // 밀도 0이면 안 됨
b3CreateHullShape(body, &sd, &cube.base);
for (int i = 0; i < 90; ++i) {
b3World_Step(world, 1.0f/60.0f, 4); // dt, 서브스텝 4
b3Vec3 p = b3Body_GetPosition(body);
printf("%4.2f %4.2f %4.2f\n", p.x, p.y, p.z);
}
b3DestroyWorld(world); // 전부 한 번에 해제
return 0;
}
CMake 프리셋으로 실제 3D 샘플을 띄워 본다. imgui 패널로 데모를 바꿔 가며 물리 거동을 눈으로 관찰하는 것이 목표.
# 리눅스 예시 (README 기준)
cmake --preset linux-release
cmake --build --preset linux-release
./build/bin/samples
# Windows: cmake --preset windows → build_vs2026.bat 도 가능
# macOS: cmake --preset macos
과제 1 코드에 revolute joint(경첩)로 진자를, wheel joint로 간단한 서스펜션 자동차를 붙여 본다. include/box3d/box3d.h의 관절 API와 samples/의 관절 데모를 참고하면 된다. 관절 8종의 차이를 직접 손으로 익히는 것이 목표.
README가 권장하는 방식으로, 빈 CMake 프로젝트를 만들고 Box3D를 FetchContent로 끌어와 링크해 본다. "무의존 코어를 남의 프로젝트에 끼우는" 실전 경험이다.
include(FetchContent)
FetchContent_Declare(box3d
GIT_REPOSITORY https://github.com/erincatto/box3d.git
GIT_TAG v0.1.0)
FetchContent_MakeAvailable(box3d)
target_link_libraries(my_app PRIVATE box3d::box3d)
상자 수백 개를 쌓아 놓고, 정지 후 어느 시점에 아일랜드가 "잠드는지"를 island.c에 로그를 심어 관찰한다. 나아가 BOX3D_PROFILE(Tracy)을 켜 잠든 물체가 스텝 시간에서 빠지는 걸 프로파일러로 확인한다. 엔진 최적화의 핵심을 코드 레벨에서 이해하는 것이 목표.
물리 엔진을 "쓰는 사람"에서 "이해하는 사람"으로 — 6주 계획.
| 주차 | 주제 | 할 일 |
|---|---|---|
| 1주차 | C 기초 다지기 & 빌드 환경 | C17 문법, 포인터/구조체, CMake 기본. 과제 1·2 완주. 불투명 핸들 API 감 잡기 |
| 2주차 | 벡터·쿼터니언 수학 | 3D 회전을 쿼터니언으로 다루는 법. math_functions.h 읽기. 오일러각과의 차이 이해 |
| 3주차 | 강체 역학 & 적분 | 속도·힘·토크·관성 텐서. 세미-임플리싯 오일러 적분. 스프링-질량 실습(과제 6-학습3) |
| 4주차 | 충돌 감지 | AABB 트리(dynamic_tree.c)와 GJK(distance.c) 읽기. 브로드/내로우페이즈 구분 |
| 5주차 | 제약 솔버 & Soft Step | Erin Catto의 GDC 슬라이드 + contact_solver.c. 순차 임펄스·소프트 제약·서브스텝 이론 |
| 6주차 | 성능 & 결정론 | 데이터 지향 설계, 그래프 색칠 병렬화, -ffp-contract와 부동소수점 결정론. 과제 5 완주 |
물리 엔진은 "수학 → 역학 → 충돌 → 솔버 → 최적화" 순으로 층이 쌓인다. 처음부터 solver.c(79KB)를 열면 좌절하기 쉽다. API 사용자(과제 1~4) → 이론(2~5주차) → 내부 구현(과제 5) 순서로, "쓸 줄 아는 상태에서 원리를 파고드는" 흐름이 훨씬 덜 지친다. Box2D 시절 자료(Catto의 강연·문서)가 방대하니 3D로 넘어오기 전 2D 개념을 먼저 잡아도 좋다.
이 문서와 저장소에 나온 주요 용어 정리.
distance.c가 구현.b3BodyId처럼 내부를 숨긴 ID로 API를 노출하고, b3Default***Def()로 설정 구조체 기본값을 채우는 C 스타일 API 설계.공식 저장소 · 문서 · 저자 자료.
| 구분 | 링크 |
|---|---|
| GitHub 저장소 | github.com/erincatto/box3d |
| 공식 3D 문서 | box2d.org/documentation3d |
| Box2D 본가(이론·강연 보고) | box2d.org |
| 결정론 관련 글 | box2d.org/posts/2024/08/determinism |
| 소개 영상(저자) | YouTube — Introducing Box3D |
| 고정 타임스텝 가이드 | Fix Your Timestep! |
| 커뮤니티 | Discord · GitHub Discussions |
| 라이선스 | MIT (상용 이용 가능) |