Commit bb121f46 authored by Nor-s's avatar Nor-s
Browse files

Update note

parent 6b6aa5dd
No related merge requests found
Showing with 762 additions and 41 deletions
+762 -41
# **box2d 2.4.1**
# Box2d <!-- omit in toc -->
- [1. **box2d 2.4.1**](#1-box2d-241)
- [1.1. **object**](#11-object)
- [1.2. **module**](#12-module)
- [1.3. Units](#13-units)
- [1.4. Factories and Definitions](#14-factories-and-definitions)
- [2. **Hello Box2D**](#2-hello-box2d)
- [2.1. **Creating a World**](#21-creating-a-world)
- [2.2. **Creating a GroundBox**](#22-creating-a-groundbox)
- [2.2.1. **step1**](#221-step1)
- [2.2.2. **step2**](#222-step2)
- [2.2.3. **step3**](#223-step3)
- [2.2.4. **step4**](#224-step4)
- [2.2.5. **about fixture**](#225-about-fixture)
- [2.3. **Creating a Dynamic Body**](#23-creating-a-dynamic-body)
- [2.4. **Simulating the world**](#24-simulating-the-world)
- [2.4.1. **time step**](#241-time-step)
- [2.4.2. **constraint solver**](#242-constraint-solver)
- [2.4.3. **simulation loop**](#243-simulation-loop)
- [2.5. **Cleanup**](#25-cleanup)
- [3. **Common Module**](#3-common-module)
- [3.1. **settings**](#31-settings)
- [3.2. **Memory Management**](#32-memory-management)
- [3.3. **Math**](#33-math)
- [4. **Collision Module**](#4-collision-module)
- [4.1. **shape**](#41-shape)
- [4.1.1. **Circle Shapes**](#411-circle-shapes)
- [4.1.2. **PolyGon Shapes**](#412-polygon-shapes)
- [4.1.3. **Edge Shapes**](#413-edge-shapes)
- [4.1.4. **Chain Shapes**](#414-chain-shapes)
- [4.2. **Geometric queries**](#42-geometric-queries)
- [4.2.1. **Shape Point Test**](#421-shape-point-test)
- [4.2.2. **Shape Ray Cast**](#422-shape-ray-cast)
- [4.3. **Pairwise Functions**](#43-pairwise-functions)
- [4.3.1. **Overlap**](#431-overlap)
- [4.3.2. **Contact manifolds**](#432-contact-manifolds)
- [4.3.3. **Distance**](#433-distance)
- [4.3.4. **Time of impact**](#434-time-of-impact)
- [4.4. **Dynamic Tree**](#44-dynamic-tree)
- [4.5. **Broad-phase**](#45-broad-phase)
- [5. **Dynamics Module**](#5-dynamics-module)
- [5.1. **Bodies**](#51-bodies)
- [5.1.1. **b2_staticBody**](#511-b2_staticbody)
- [5.1.2. **b2_kinematicBody**](#512-b2_kinematicbody)
- [5.1.3. **b2_dynamicBody**](#513-b2_dynamicbody)
- [5.1.4. **Body Definition**](#514-body-definition)
- [5.1.4.1. **Body Type**](#5141-body-type)
- [5.1.4.2. **Position and Angle**](#5142-position-and-angle)
- [5.1.4.3. **Damping**](#5143-damping)
- [5.1.4.4. **Gravity Scale**](#5144-gravity-scale)
- [5.1.4.5. **Sleep Parameters**](#5145-sleep-parameters)
- [5.1.4.6. **Fixed Rotation**](#5146-fixed-rotation)
- [5.1.4.7. **Bullets**](#5147-bullets)
- [5.1.4.8. **Activation**](#5148-activation)
- [5.1.4.9. **User Data**](#5149-user-data)
- [5.1.5. **Body Factory**](#515-body-factory)
- [5.1.6. **Using a Body**](#516-using-a-body)
- [5.1.7. **Mass Data**](#517-mass-data)
- [5.1.8. **State Information**](#518-state-information)
- [5.1.9. **Position and Velocity**](#519-position-and-velocity)
- [5.1.10. **Fiorces and Impulses**](#5110-fiorces-and-impulses)
- [5.1.11. **Coordinate Transformations**](#5111-coordinate-transformations)
- [5.1.12. **Acessing Fixtures, Joints, and Contacts**](#5112-acessing-fixtures-joints-and-contacts)
- [5.2. **Fixtures**](#52-fixtures)
- [5.2.1. **Fixture Creation**](#521-fixture-creation)
- [5.2.2. **Density**](#522-density)
- [5.2.3. **Friction**](#523-friction)
- [5.2.4. **Restitution**](#524-restitution)
- [5.2.5. **Filtering**](#525-filtering)
- [5.2.6. **Sensors**](#526-sensors)
- [5.3. **Joints**](#53-joints)
- [5.4. **Contacts**](#54-contacts)
- [5.5. **World**](#55-world)
- [6. **Loose Ends**](#6-loose-ends)
- [6.1. **User Data**](#61-user-data)
- [6.2. **Custom User Data**](#62-custom-user-data)
- [6.3. **Implicit Destruction**](#63-implicit-destruction)
- [6.4. **Pixels and Coordinate Systems**](#64-pixels-and-coordinate-systems)
- [6.5. **Debug Drawing**](#65-debug-drawing)
- [6.6. **Limitations**](#66-limitations)
- [7. links](#7-links)
# 1. **box2d 2.4.1**
- C++로 작성된 강체 시뮬레이션 라이브러리
- b2라는 접두어의 타입을 가지고 있음.
## **object**
## 1.1. **object**
---
......@@ -28,7 +111,7 @@
- Box2D에서는 이를 처리하기위해 특별한 알고리즘을 포함하고 있음.
- collision 알고리즘: 두 body의 움직임을 보간(iterpolate) 하여 첫번째 충돌시간(TOI)를 찾는다. body를 첫 충돌시점으로 이동시킨다음 충돌을 해결하는 하위 단계 solver를 사용하여 해결
## **module**
## 1.2. **module**
---
......@@ -41,7 +124,7 @@ common -> dynamics
- Collision: shapes, broad-phase, collision function/queries를 정의한다.
- Dynamic: simulation world, bodies, fixture, joints를 제공.
## Units
## 1.3. Units
---
......@@ -60,7 +143,7 @@ common -> dynamics
- length units을 변경하기위해서는 b2_lengthUnitsPerMeter를 수정해야한다. b2_user_settings.h에 있는 `B2_USER_SETTING`를 통해 병합충돌을 피할 수 있다. ([b2_settings.h](https://box2d.org/documentation/b2__settings_8h.html))
## Factories and Definitions
## 1.4. Factories and Definitions
---
......@@ -97,13 +180,13 @@ void b2Body::DestroyFixture(b2Fixture* fixture)
- Factories 는 정의에 대한 참조를 유지하지 않는다.
- 따라서 스택에 정의를 생성하고 임시 리소스에 보관할 수 있다.
# **Hello Box2D**
# 2. **Hello Box2D**
- 커다란 large ground box와 small dynamic box에 대한 예제
- 이 코드에는 그래픽이 포함되어있지 않다.
- 시간에 따른 상자 위치의 콘솔에 텍스트 출력만 표시된다.
## **Creating a World**
## 2.1. **Creating a World**
---
......@@ -119,7 +202,7 @@ b2World world(gravity);
> 주의! scope를 조심해야한다. (할당과 해제)
## **Creating a GroundBox**
## 2.2. **Creating a GroundBox**
---
......@@ -129,7 +212,7 @@ b2World world(gravity);
3. fixtures 정의 (shape, friction, density, etc.)
4. fixtures을 body에 생성(붙임)
### **step1**
### 2.2.1. **step1**
- ground body 생성해야한다.
- 이를 위해 body정의가 필요하다.
......@@ -140,7 +223,7 @@ b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0.0f, -10.0f);
```
### **step2**
### 2.2.2. **step2**
- body 정의를 world object로 넘겨 ground body를 생성한다.
- world object는 body정의에 대한 참조를 유지하지 않는다.
......@@ -151,7 +234,7 @@ groundBodyDef.position.Set(0.0f, -10.0f);
b2Body* groundBody = world.CreateBody(&groundBodyDef);
```
### **step3**
### 2.2.3. **step3**
- ground polygon을 생성해야한다.
- `SetAsBox` shortcut을 사용하여 ground polygon을 box shape로 형성하고, box가 부모 몸체의 원점에 중심이 되도록해야한다.
......@@ -168,7 +251,7 @@ groundBox.SetAsBox(50.0f, 10.0f);
- box2D는 mks 단위로 조정됬으므로, extents를 meters로 고려할 수 있다.
- Box2D는 일반적으로 객체가 일반적인 실제 객체 크기일 때 가장 잘 작동한다. (ex. box2d를 사용하여 glaciers, dust 파티클의 움직임을 모델링하는것은 좋은 생각이 아님)
### **step4**
### 2.2.4. **step4**
- shape fixture를 생성하는것이 마지막 단계이다.
- 간단한 방법으로 fixture 기본값을 사용하는것이다.
......@@ -181,7 +264,7 @@ groundBody->CreateFixture(&groundBox, 0.0f);
> _box2D는 shape에 대한 참조를 유지하지 않는다. data를 새로운 b2Shape 객체로 복사(clone)한다._
### **about fixture**
### 2.2.5. **about fixture**
- 모든 fixture는 부모 body가 있어야한다. (static 이더라도) 하지만, 모든 static fixtures를 single static body에 붙일 수 있다.
......@@ -193,7 +276,7 @@ groundBody->CreateFixture(&groundBox, 0.0f);
- 이유: 모양이 변형되는 body는 강체(rigid body) 가 아니지만, box2D는 rigidbody engine이다. Bodx2D에서 만들어진 많은 가정은 강체 모델을 기반이므로, 이를 위반하면 많은것들이 제대로 작동하지 않게된다.
## **Creating a Dynamic Body**
## 2.3. **Creating a Dynamic Body**
---
......@@ -236,13 +319,13 @@ fixtureDef.friction = 0.3f;
body->CreateFixture(&fixtureDef);
```
## **Simulating the world**
## 2.4. **Simulating the world**
---
- ground box 그리고 dynamic box를 초기화했으므로, 이제 시뮬레이션 할 준비만 몇가지 하면 된다.
### **time step**
### 2.4.1. **time step**
- Box2D는 적분기(integrator) 라는 컴퓨팅 알고리즘을 이용한다.
- 적분기: 물리 방정식을 이산시간에 대해서 시뮬레이션하는 알고리즘
......@@ -257,7 +340,7 @@ body->CreateFixture(&fixtureDef);
float timeStep = 1.0f / 60.0f;
```
### **constraint solver**
### 2.4.2. **constraint solver**
- 추가적으로 적분기에 constraint solver를 이용할 수 있다.
......@@ -282,7 +365,7 @@ int32 positionIterations = 2;
- time step 과 iteration count는 완전히 상관이 없으며, 한 iteration은 sub-step이 아니다.
- 하나의 solver iteration은 time step내의 모든 constraint를 한번씩은 통과해야한다. (최소한 한번)
### **simulation loop**
### 2.4.3. **simulation loop**
- 시뮬레이션 루프는 게임루프에 통합된다.
- 게임 루프 전체의 각각의 단계에서 [b2World::step](https://box2d.org/documentation/classb2_world.html#a82c081319af9a47e282dde807e4cd7b8)을 호출할 수 있다.
......@@ -312,7 +395,7 @@ for (int32 i = 0; i < 60; ++i)
0.00 1.01 0.00
```
## **Cleanup**
## 2.5. **Cleanup**
---
......@@ -320,18 +403,18 @@ for (int32 i = 0; i < 60; ++i)
- 이처럼 무효화되기 때문에. world의 객체들을 가리키는 모든 포인터들을 잘 관리해야한다.
- 이를 통해 성능을 얻었고, 코드도 간결해졌다.
# **Common Module**
# 3. **Common Module**
- settings, memory management, vector math
## **settings**
## 3.1. **settings**
- box2D에 정의 된 타입들을 통해 구조의 크기를 쉽게 결정가능하다.
- b2Settings.h 에 정의된 상수들, 일반적으로 조정할 필요가 없다.
- 부동소수점 연산을 하기 때문에 round-off 오류를 위한 수치 허용오차가 정의되어있음 (일부는 상대적, 절대적 허용오차는 MKS단위 사용)
- b2Version 구조체로 box2d의 현재 버전을 알아낼 수 있다.
## **Memory Management**
## 3.2. **Memory Management**
- 많은 수의 작은 객체(50-300바이트)를 할당하는 경향이 있는 box2d.
- 작은 객체에 대해 malloc, new 를 통해 시스템 힙을 사용하는 것은 비효율적이며 단편화를 일으킬 수 있다.
......@@ -344,16 +427,16 @@ for (int32 i = 0; i < 60; ++i)
- [참고] time step 실행도중 Box2D는 임시 작업 공간 메모리가 필요하다. 그러므로 b2StackAllocator 라는 스택할당자를 사용하여 단계별 힙 할당을 방지한다. (스택할당자와 상호작용할 필요 없다.)
## **Math**
## 3.3. **Math**
- 간단한 벡터, 행렬 연산 모듈을 포함한다.
- Box2D 내부 요구 사항에 맞게 설계되어있다.
# **Collision Module**
# 4. **Collision Module**
- shapes, dynamic tree, broad-phase(큰 시스템에서 충돌처리 가속을 위한)
## **shape**
## 4.1. **shape**
- 충돌 기하학을 설명, 물리 시뮬레이션과 독립적으로 사용됨.
- 최소한 rigid bodies과 어떻게 연결되는지 방법을 이해애야한다.
......@@ -372,7 +455,7 @@ for (int32 i = 0; i < 60; ++i)
> shape가 body에 연결되면, 해당 꼭짓점이 local-coordinates 표현된다.
### **Circle Shapes**
### 4.1.1. **Circle Shapes**
- circle 은 position 과 radius 를 가지고 있다.
- circle 로 속이 빈 원을 만들 수 없다.
......@@ -383,7 +466,7 @@ circle.m_p.Set(2.0f, 3.0f);
circle.m_radius = 0.5f;
```
### **PolyGon Shapes**
### 4.1.2. **PolyGon Shapes**
- Polygon 은 convex polygons이다. (볼록 다각형)
- Polygon은 속이 비어있지 않는다.
......@@ -427,7 +510,7 @@ void SetAsBox(float hx, float hy, const b2Vec2& center, float angle);
> Not that polygon skin is only provided to help with continuous collision. The purpose is not to simulate rounded polygons.
### **Edge Shapes**
### 4.1.3. **Edge Shapes**
- edge shape는 선분(line segments)이다.
- 이는 게임을 위한 자유형식의 static 환경을 만드는데 도움이 되도록 제공된다.
......@@ -467,7 +550,7 @@ edge.SetOneSided(v0, v1, v2, v3);
- 일반적으로 이 방법은 사용안한다. (wasteful and tedious)
- chain shapes를 사용한다.
### **Chain Shapes**
### 4.1.4. **Chain Shapes**
- 사슬 모양은 많은 edge를 함께 연결하여 static game worlds를 구성하는 효율적인 방법을 제공한다.
- 사슬 모양은 자동적으로 ghost collisions를 제거하고 일방적인 충돌을 제공한다. (provide one-sided collision)
......@@ -511,11 +594,11 @@ for (int32 i = 0; i \< chain.GetChildCount(); ++i)
}
```
## **Geometric queries**
## 4.2. **Geometric queries**
- 단일 shape에 대해 여러 기하학적 쿼리(geometric queries)를 수행할 수 있다.
### **Shape Point Test**
### 4.2.1. **Shape Point Test**
- shape transform과 world point을 인자로 받아 shape가 겹치는지 테스트할 수 있다.
......@@ -529,7 +612,7 @@ bool hit = shape->TestPoint(transform, point);
- edge와 chain은 항상 false (chain이 loop여도)
### **Shape Ray Cast**
### 4.2.2. **Shape Ray Cast**
- shape에 ray를 투사하여 첫 번째 교차점과 법선벡터를 얻을 수 있다. (first intersection and normal vector)
- raycast가 한번에 하나의 edge만을 검사하기 때문에 chain shape에 child index가 포함된다.
......@@ -555,11 +638,11 @@ if (hit)
}
```
## **Pairwise Functions**
## 4.3. **Pairwise Functions**
- Collision 모듈에는 한 쌍의 shape를 취하고 일부 결과를 계산하는 함수가 포함되어있다.
### **Overlap**
### 4.3.1. **Overlap**
- [b2TestOberlap](https://box2d.org/documentation/b2__collision_8h.html#a769992d82855399cf20721cd6b411fe7): 두 shape가 겹치는지?
......@@ -570,7 +653,7 @@ bool overlap = b2TestOverlap(shapeA, indexA, shapeB, indexB, xfA, xfB);
- 체인 shape인 경우, child indices를 제공해야한다.
### **Contact manifolds**
### 4.3.2. **Contact manifolds**
- Box2D에는 overlapping shapes를 계산하는 기능이 있다.
- 원-원 or 원-다각형 : 하나의 접점과 법선만 얻을 수 있다.
......@@ -614,13 +697,13 @@ if (state1[0] == b2_removeState)
}
```
### **Distance**
### 4.3.3. **Distance**
- b2Distance 함수는 두 shape 사이의 거리를 계산하는데 사용할 수 있다.
- distance function은 [b2DistanceProxy](https://box2d.org/documentation/structb2_distance_proxy.html)로 변환하려면 두 shape 모두 필요하다.
- 반복호출에 대해 distance function을 warm start하는데 사용되는 일부 캐싱도 있다.
### **Time of impact**
### 4.3.4. **Time of impact**
- 만일 두 shape가 빠르게 움직이는 경우 단일 time step에서 서로를 터널링할 수 있다.
- b2TimeOfImpact 함수는 두 개의 움직이는 shape가 충돌하는 시간을 결정하는 데 사용된다.
......@@ -641,13 +724,651 @@ if (state1[0] == b2_removeState)
- 만일 고정 회전(fixed rotations)을 사용하면, shape cast를 수행할 수 있다.
- 이 경우, the time of impact function은 모든 충돌을 놓치지 않는다.
## **Dynamic Tree**
## 4.4. **Dynamic Tree**
-
- [b2DynamicTree](https://box2d.org/documentation/classb2_dynamic_tree.html)는 많은 shape를 효율적으로 구성하는데 사용된다.
## **Broad-phase**
- 이 클래서는 어떤 shape인지 모르지만, 사용자 데이터 포인터가 있는 AABBs(axis-aligned bounding boxes)에서 작동한다.
# links
- dynamic tree는 계층적 AABB 트리이다.
- 트리의 각 내부 노드에는 두개의 자식을 가진다.
- 리프노드는 단일 사용자 AABB(single user AABB)이다.
- 트리는 퇴화 입력(degenerate input)의 경우에도 균형을 유지하기 위해 회전을 사용한다.
- 트리 구조는 효율적인 ray casts 그리고 영역 쿼리를 허용한다.
- 예를 들어, scene에 여러 shape가 있을 수 있다. 여기서 ray casst를 수행하려면, brute force 방법으로 각 shape에 대해 ray cast 하는 방법을 사용할 수 있다.
- 이런 방법은 비효율적이다. (shape가 서로 떨어져 있을 경우)
- 그러므로 dynamic tree를 유지하고, 이 tree에 대해 raycast를 수행하여 많은 개수의 shape를 스킵할 수 있다.
- region query: tree를 사용하여 쿼리 AABB와 겹치는 모든 리프 AABB를 찾음.
- 많은 shape를 스킵할 수 있기 때문에 빠르다.
- 일반적으로 이 트리를 직접 사용하지 않는다.
- b2World 클래스를 사용하여 레이 캐스트 및 지역 쿼리를 수행한다.
## 4.5. **Broad-phase**
- 물리 단계에서 충돌처리는 narrow-phase와 broad-phase로 나눌 수 있다.
- narrow-phase: shape 쌍에서 접점을 계산
- N개의 shape: N\*N/2 개의 쌍에 대해 narrow-phase를 수행해야한다.
- b2BroadPhase 클래스는 이러한 쌍을 관리하기 위해 dynamic tree를 사용하여 부하를 줄인다.
- 이것은 narrow-phase 호출의 수를 크게 줄여준다.
- broad-phase: 일반적으로 직접 상호작용하지 않는다.(내부적으로 box2D가 생성하고 관리)
- b2BroadPhase는 Box2D의 시뮬레이션 루프에 맞게 설계되었다.
# 5. **Dynamics Module**
- 다이나믹 모듈은 Box2D의 가장 복잡한 부분이다.
- 대부분 사용자가 상호작용하는 모듈.
- Common과 Collision 모듈 위에 있는 모듈
- 아래와 같은 클래스를 가지고 있다.
- fixture
- rigid body
- contact
- joint
- world
- listener
- 클래스 사이에 많은 종속성이 있다. (다른 클래스를 참조)
## 5.1. **Bodies**
- position 과 velocity를 가지고 있다.
- forces, torques, impulses (힘, 토크, 충격)을 bodies에 적용할 수 있다.
- Body의 종류: static, kinematic, dynamic
- body는 fixtures(shapes)의 척추
- bodies는 fixture를 운반하면서 world에서 움직인다.
- Body는 항상 강체이다.
- 즉, 동일한 강체에 부착된 fixtures는 서로에 대해 상대적으로 움직이지 않고, 서로 충돌하지 않는다.
- fixtures에는 collision geometry 와 밀도(density)가 있다.
- 일반적으로 body는 fixtures에서 mass 속성을 얻는다.
- 그러나 body를 만든 후 mass 속성을 override할 수 있다.
- 일반적으로 생성한 모든 bodies에 대해 pointers을 유지한다.
- 그러므로 body position을 쿼리하여 그래픽 개체의 위치를 업데이트할 수 있다.
- 또한 포인터에 대한 작업이 완료되면 파괴할 수 있다.
### 5.1.1. **b2_staticBody**
- 시뮬레이션에서 움직이지 않음
- 무한한 mass를 가진것 처럼 동작
- mass와 inverse mass값 == 0
- 사용자가 수동적으로 이동 가능
- 속도 == 0
- 다른 static, kinematic body와 충돌하지 않는다.
### 5.1.2. **b2_kinematicBody**
- 속도에 따라 시뮬레이션 중에 움직임
- forces에 반응하지 않음
- 수동적으로 움직일 수 있지만 일반적으로 속도를 설정하여 이동시킴
- 무한한 mass를 가진것처럼 동작하지만
- mass와 inverse mass 값 == 0
- 다른 static, kinematic과 충돌하지 않는다.
### 5.1.3. **b2_dynamicBody**
- 완전히 시뮬레이션되는 body
- 사용자가 수동으로 이동할 수 있지만, 일반적으로 forces에 따라 움직임
- 어떠한 body와도 충돌 가능하다.
- 0이 아닌 질량을갖는다
- 만약 0으로 설정하면 자동적으로 1kg의 질량을 갖고 회전하지 않는다.
### 5.1.4. **Body Definition**
- body를 생성하기 전에 body definition을 생성해야한다. ([b2BodyDef](https://box2d.org/documentation/structb2_body_def.html))
- 초기화 하는데 필요한 데이터를 가진다.
- 이 정의에서 body로 데이터를 복사한다.
- 정의에 대한 포인터는 유지하지 않는다.
- 정의를 재활용하여 여러 body를 생성할 수 있다.
#### 5.1.4.1. **Body Type**
- static, kinematic, and dynamic.
- 나중에 이를 변경하는것인 비용이 비싸므로 생성시에 설정
- 필수적이다.
```cpp
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
```
#### 5.1.4.2. **Position and Angle**
- 생성시 body위치를 초기화
- world 원점에서 생성하고, body를 움직이는것보다 성능이 좋다.
- 원점에서 여러 body를 생성하면 성능이 저하된다.
- body's origin: Fixtures 그리고 joints은 body 원점을 기준으로 부착된다.
- 질량 중심 위치(cenger of mass): 부착된 shape의 질량분포(mass distribution)에서 결정되거나 [b2MassData](https://box2d.org/documentation/structb2_mass_data.html)로 명시적으로 설정할 수 있다.
- Box2D의 내부 계산의 대부분은 질량 중심 위치를 사용한다.
- 예를들어, b2Body는 질량중심에 대한 선형속도를 저장한다.
- body의 각도를 라디안 단위로 지정할 수 있으며, 이는 질량중심위치의 영향을 받지 않는다.
- 나중에 mass 속성들을 변경하면, body의 질량중심이 이동할 수 있지만, 원점 위치는 변경되지 않고, 부착된 shapes 과 joints 또한 이동하지 않는다.
```cpp
b2BodyDef bodyDef;
bodyDef.position.Set(0.0f, 2.0f); // the body's origin position.
bodyDef.angle = 0.25f * b2_pi; // the body's angle in radians.
```
- rigid body는 참조 프레임이다.
- 해당 프레임에서 fixtures 및 joints를 정의할 수 있다.
- 이것들은 local 프레임에서 절대 움직이지 않는다.
#### 5.1.4.3. **Damping**
- bodies의 world 속도를 줄이기 위해 사용된다.
- friction은 접촉할 때 발생함(damping과 다름)
- 마찰을 대체 할 수 없음, 두가지 모두 사용해야함.
- Damping 매개변수는 0~ INF 사이
- 0: 감쇠가 없음
- INF: 전체 감쇠
- 일반적으로 0 과 0.1 사이의 값을 사용한다.
```cpp
b2BodyDef bodyDef;
bodyDef.linearDamping = 0.0f;
bodyDef.angularDamping = 0.01f;
```
- Damping은 안정성과 성능에 대한 근사치
- 작은 감쇠값: timestep 과 무관
- 더 큰 감쇠값: timestep 에 따라 효과가 달라짐
#### 5.1.4.4. **Gravity Scale**
- 단일 body의 중력을 조절 (증가하면 안정성이 떨어짐)
```cpp
// Set the gravity scale to zero so this body will float
b2BodyDef bodyDef;
bodyDef.gravityScale = 0.0f;
```
#### 5.1.4.5. **Sleep Parameters**
- 시뮬레이션 횟수가 적을 수록 좋기 때문에 body를 중단하게 함.
- Box2D가 body(or group)이 정지했다고 판단하면 body는 CPU 오버헤드가 거의 없는 절전상태에 들어간다.
- awake 상태의 body와 충돌하면 깨어나게된다.
- Bodies에 연결된 joint 나 접점이 파괴된 경우에도 body가 깨어난다.
- 수동으로 깨울 수 있다.
- Body 정의에서 잠을 잘 수 있는지 와 생성할 때의 상태를 지정할 수 있다.
```cpp
b2BodyDef bodyDef;
bodyDef.allowSleep = true;
bodyDef.awake = true;
```
#### 5.1.4.6. **Fixed Rotation**
- 캐릭터와 같은 강체가 회전하지 않게 하기 위한 설정
- 하중이 가해져도 회전하지 않는다.
```cpp
b2BodyDef bodyDef;
bodyDef.fixedRotation = true;
```
- 이 플래그는 회전 관성(rotational inertia) 그리고 그 역(inverse)이 0으로 설정되도록 한다.
#### 5.1.4.7. **Bullets**
- 이산 시뮬레이션에서 강체는 한 timestap에서 더 많이 이동할 수 있다.
- 터널링에 관한 것
- 기본적으로 Box2D는 연속 충돌 감지(CCD)를 사용하여 dynamic이 static을 터널링하는 것을 방지한다.
- 이전 위치에서 새 위치로 shape는 sweeping하여 수행한다.
- 엔진은 sweeping동안 새로운 충돌을 찾고, 충돌시간(TOI)을 계산한다.
- body가 첫번째 TOI로 이동된 다음, solver가 하위 단계를 수행하여 전체 timestep을 완료한다.(하위 단계 내에서 추가 TOI이벤트가 있을 수 있다.)
- 일반적으로 ccd는 dynamic에서 사용되지 않는다.
- 이는 성능을 합리적으로 유지하기 위해 수행된다.
- 일부 게임에서 dynamic body에 ccd가 필요할 경우가 있다. (ex. 고속 총알을 dynamic body에, 이 경우 ccd가 없으면 뚫릴 수 있음)
- 빠르게 움직이는 객체는 bullets이라는 라벨을 붙일 수 있다.
- bullet은 static, dynamic body 모두에 ccd를 수행한다.
```cpp
b2BodyDef bodyDef;
bodyDef.bullet = true;
```
- 이 플래그는 dynamic body일 경우에만 유효하다.
#### 5.1.4.8. **Activation**
- 충돌이나 역학(collision or dynamics)에 참여하지 않을 수 있다.
- 이 상태는 body가 다른 body에 의해 깨어나지 않고, body의 fixture가 broad-phase에 배치되지 않는다는 점을 제외하고는 sleep과 유사하다.
- 즉, 충돌, 레이 캐스트에 참여하지 않는다.
- 이 설정은 나중에 변경할 수 있다.
```cpp
b2BodyDef bodyDef;
bodyDef.active = true;
```
- joint는 비활성 body에 연결될 수 있지만, 시뮬레이션되지 않는다.
- body를 활성화 할 때 joint가 왜곡되지 않도록 주의해야한다.
- body를 활성화하는 것은 body를 처음부터 생성하는 것 만큼 비용이 많이 든다.
- 따라서 streaming worlds에서 이를 활용하면 안된다.
- 이 경우 생성/ 파괴를 사용하여 메모리를 절약해야한다.
#### 5.1.4.9. **User Data**
- 사용자 데이터는 void pointer이다.
- 응용 프로그램 객체를 연결할 수 있는 연결고리이다,
- 일관성있게 객체 타입을 연결해야한다.
```cpp
b2BodyDef bodyDef;
bodyDef.userData.pointer = reinterpret_cast<uintptr_t>(&myActor);
```
### 5.1.5. **Body Factory**
- body는 world class에서 제공하는 body factory를 사용하여 생성 및 파괴된다.
- 이를 통해 world는 효율적으로 메모리 관리를 할 수 있다.
```cpp
b2World* myWorld;
b2Body* dynamicBody = myWorld->CreateBody(&bodyDef);
// ... do stuff ...
myWorld->DestroyBody(dynamicBody);
dynamicBody = nullptr;
```
> 주의: body를 생성할 때 new, malloc을 사용해서는 안된다.
- box2D는 body definition 또는 그 데이터에 대한 참조를 유지하지 않는다. (사용자 데이터 포인터는 유지)
- 따라서 임시 body 정의를 생성하고, 동일한 body 정의를 재사용할 수 있다.
- body를 삭제하면 부착된 fixtures, joints는 자동적으로 삭제된다.
### 5.1.6. **Using a Body**
- 생성한 후에, 많은 작업을 수행할 수 있다.
- 질량 속성 설정, 위치 및 속도 접근, forces 적용, 점 및 벡터 변환 등
### 5.1.7. **Mass Data**
- 물체에는 질량(스칼라), 질량 중심(2-vector), 회전 관성(스칼라) 가 있다.
- static body의 경우 질량 및 회전 관성 == 0
- 물체의 회전이 고정되어 있으면 회전 관성 == 0
- 일반적으로 body에 fixture를 추가할 때 body의 mass 속성이 자동으로 설정된다.
- 런타임에 body의 질량을 조정할 수 있다.
```cpp
void b2Body::SetMassData(const b2MassData* data);
```
- body의 mass를 직접 설정한 후 fixture에 의해 지시된 natural mass로 되돌릴 경우 아래와 같은 함수를 사용한다.
```cpp
void b2Body::ResetMassData();
```
- body의 mass data와 관련된 함수는 다음과 같다.
```cpp
float b2Body::GetMass() const;
float b2Body::GetInertia() const;
const b2Vec2& b2Body::GetLocalCenter() const;
void b2Body::GetMassData(b2MassData* data) const;
```
### 5.1.8. **State Information**
- body state 접근하는 함수들
```cpp
void b2Body::SetType(b2BodyType type);
b2BodyType b2Body::GetType();
void b2Body::SetBullet(bool flag);
bool b2Body::IsBullet() const;
void b2Body::SetSleepingAllowed(bool flag);
bool b2Body::IsSleepingAllowed() const;
void b2Body::SetAwake(bool flag);
bool b2Body::IsAwake() const;
void b2Body::SetEnabled(bool flag);
bool b2Body::IsEnabled() const;
void b2Body::SetFixedRotation(bool flag);
bool b2Body::IsFixedRotation() const;
```
### 5.1.9. **Position and Velocity**
- 속도와 위치에 접근하는 함수들
- 이것은 렌더링할 때 일반적이다.
- 위치를 설정할 수 있지만, 시뮬레이션 결과를 얻는것이 일반적
```cpp
bool b2Body::SetTransform(const b2Vec2& position, float angle);
const b2Transform& b2Body::GetTransform() const;
const b2Vec2& b2Body::GetPosition() const;
float b2Body::GetAngle() const;
```
- Local 그리고 world 좌표에서 질량 중심 위치에 접근할 수 있다.
- 내부 시뮬레이션은 대부분 질량 중심을 사용한다. (보통 사용자가 접근하지 않는다.)
- 일반적으로 body transform 을 사용할 수 있다.
- ex. body가 정사각형일 경우 질량중심은 정사각형 중심에 있다. (body의 원점은 모서리일 수 있다.)
```cpp
const b2Vec2& b2Body::GetWorldCenter() const;
const b2Vec2& b2Body::GetLocalCenter() const;
```
- 선형 및 각속도에 접근할 수 있다.
- 선형 속도(linear velocity): 질량 중심에 대한것, 질량 특성이 변경되면 변경될 수 있다.
### 5.1.10. **Fiorces and Impulses**
- 힘, 토크, 충격을 body에 적용
- 이 경우 하중이 가해지는 world point 를 넘겨줘야한다.
- 이로 인해 질량 중심에 대한 토크가 발생한다.
```cpp
void b2Body::ApplyForce(const b2Vec2& force, const b2Vec2& point);
void b2Body::ApplyTorque(float torque);
void b2Body::ApplyLinearImpulse(const b2Vec2& impulse, const b2Vec2& point);
void b2Body::ApplyAngularImpulse(float impulse);
```
- 힘, 토크, 충격을 가하면 body가 깨어나게 된다. (For example, you may be applying a steady force and want to allow the body to sleep to improve performance.)
- 이를 막기 위해 아래와 같은 코드를 추가할 수 있다.
```cpp
if (myBody->IsAwake() == true)
{
myBody->ApplyForce(myForce, myPoint);
}
```
### 5.1.11. **Coordinate Transformations**
- body class에는 local 과 world space사이에서 점과 벡터를 변환하는 데 도움이 되는 몇가지 유틸리티 함수가 있다.
- 책추천: "Essential Mathematics for Games and Interactive Applications" by Jim Van Vert
- 이러한 함수들은 inline일 경우 효율적이다.
```cpp
b2Vec2 b2Body::GetWorldPoint(const b2Vec2& localPoint);
b2Vec2 b2Body::GetWorldVector(const b2Vec2& localVector);
b2Vec2 b2Body::GetLocalPoint(const b2Vec2& worldPoint);
b2Vec2 b2Body::GetLocalVector(const b2Vec2& worldVector);
```
### 5.1.12. **Acessing Fixtures, Joints, and Contacts**
- body의 fixtures에 접근할 수 있다. (반복문을 통해)
```cpp
for (b2Fixture* f = body->GetFixtureList(); f; f = f->GetNext())
{
MyFixtureData* data = (MyFixtureData*)f->GetUserData();
// do something with data ...
}
```
- body의 joint 리스트 또한 유사하다.
- 연관된 contacts 리스트도 제공한다.
- 이를 사용해 현재 접촉에 대한 정보를 얻을 수 있다.
- 이 리스트에는 이전 timestep 동안 존재했던것들이 없을 수 있다.
## 5.2. **Fixtures**
- shape는 body에 대해 알지 못한다.
- 물리 시뮬레이션과 독립적으로 사용될 수 있다.
- 따라서 body에 shape를 붙이기 위해 b2Fixture 클래스를 사용한다.
- 여러 fixture가 있는것을 compound body라고 한다.
- fixture는 아래와 같은 데이터를 가지고 있다.
- a single shape
- broad-phase proxies
- density, friction, and restitution
- collision filtering flags
- back pointer to the parent body
- user data
- sensor flag
### 5.2.1. **Fixture Creation**
- fixture 정의를 생성하고, body에서 생성한다.
- 부모 body가 제거되면, 자동으로 fixture도 제거된다. (따로 포인터로 저장할 필요 없다.)
```cpp
b2Body* myBody;
b2FixtureDef fixtureDef;
fixtureDef.shape = &myShape;
fixtureDef.density = 1.0f;
b2Fixture* myFixture = myBody->CreateFixture(&fixtureDef);
```
- 깨지기 쉬운 물체를 모델링하기 위해 fixture를 body에서 제거할 수 있다.
```cpp
myBody->DestroyFixture(myFixture);
```
### 5.2.2. **Density**
- fixture 밀도는 mass의 속성을 계산하는데 사용된다.
- 밀도는 0 또는 양수이다.
- 일반적으로 모든 fixture에 대해 유사한 밀도를 사용해야한다. (stacking 안정성 향상)
- 밀도를 설정할 때 body의 질량은 조정되지 않는다. (ResetMassData 호출해야한다.)
```cpp
b2Fixture* fixture;
fixture->SetDensity(5.0f);
b2Body* body;
body->ResetMassData();
```
### 5.2.3. **Friction**
- friction은 물체가 사실적으로 서로를 따라 미끄러지도록 하는 데 사용된다.
- Box2D는 static, dynamic friction을 지원하지만 둘다 동일한 매개변수를 사용한다.
- 마찰은 Box2D에서 정확하게 시뮬레이션된다.
- 마찰 강도는 수직력(normal force)에 비례한다.(쿨롱 마찰)
- 마찰 매개변수는 일반적으로 0과 1 사이에서 설정되지만, 음수가 아닌 값일 수 있다.
- 마찰 값이 0이면 마찰이 꺼짐
- 1이면 강해짐
- 두 shape 사이에서 마찰이 계산될 때 Box2D는 두 상위 fixture의 마찰 매개변수를 결합한다.(기하평균)
- 따라서 하나가 마찰이 0일 경우 접점은 마찰이 없다.
```cpp
b2Fixture* fixtureA;
b2Fixture* fixtureB;
float friction;
friction = sqrtf(fixtureA->friction * fixtureB->friction);
```
- [b2Contact::SetFriction](https://box2d.org/documentation/classb2_contact.html#a6cac6c0db18a161a359d73672596b413) 을 사용하여 혼합된 마찰을 override할 수 있다.
- b2ContactListener callback 에서 수행된다.
### 5.2.4. **Restitution**
- 복원은 물체를 튕기기 위해 사용된다.
- 복원 값은 0~1 사이로 설정된다.
- 테이블에 공을 떨어뜨릴 때 만약 0의 값을 가지고 있으면 공은 튀지 않는다.
- 이를 비탄성 충돌이라고 부른다.
- 값이 1 이면 공의 속도가 정확히 반영된다.
- 이를 완전 탄성 충돌이라고 부른다.
- 아래의 코드로 결합될 수 있다.
```cpp
b2Fixture* fixtureA;
b2Fixture* fixtureB;
float restitution;
restitution = b2Max(fixtureA->restitution, fixtureB->restitution);
```
- 이와 같은 결합으로 bouncy floor가 아니더라도 bouncy ball을 만들 수 있다.
- [b2Contact::SetRestitution](https://box2d.org/documentation/classb2_contact.html#a685a1c4cfca30c379c402e20e04723b6)을 사용하여 기본 혼합을 override할 수 있다.
- b2ContactListener callback 에서 수행된다.
- 다중 접촉에 대해서 복원은 대략적인 시뮬레이션을 수행한다.
- Box2D가 반복 솔버를 사용하기 때문.
- Box2D는 충돌 속도가 작은 경우에도 비탄성충돌을 사용한다. (jitter를 방지하는데 사용 b2_velocityRhreshold)
### 5.2.5. **Filtering**
- collision filtering을 사용하면 fixtures 사이의 충돌을 방지할 수 있다.
- 예를들어, 자전거를 타는 캐릭터, 자전거가 지형과 충돌, 캐릭터가 지형과 충돌하기를 원하지만 캐릭터와 자전거가 충돌하지 않게(겹쳐져야하므로)
- 범주 및 그룹을 사용하여 이러한 충돌 필터링을 지원한다.
- Box2D는 16개의 충돌 범주를 지원한다.
- 각 fixture에 대해 카테고리를 지정할 수 있다.
- 또한 이 fixture가 충돌할 수 있는 다른 카테고리를 지정할 수 있다.
- 예를 들어, 멀티플레이어 게임에서 모든 플레이어는 서로 충돌하지 않고 몬스터는 서로 충돌하지 않지만, 플레이어와 몬스터는 충돌하게 지정 가능하다.
- 이것은 비트 마스킹으로 수행된다.
```cpp
b2FixtureDef playerFixtureDef, monsterFixtureDef;
playerFixtureDef.filter.categoryBits = 0x0002;
monsterFixtureDef.filter.categoryBits = 0x0004;
playerFixtureDef.filter.maskBits = 0x0004;
monsterFixtureDef.filter.maskBits = 0x0002;
```
- 충돌이 발생하는 규칙은 다음과 같다.
```cpp
uint16 catA = fixtureA.filter.categoryBits;
uint16 maskA = fixtureA.filter.maskBits;
uint16 catB = fixtureB.filter.categoryBits;
uint16 maskB = fixtureB.filter.maskBits;
if ((catA & maskB) != 0 && (catB & maskA) != 0)
{
// fixtures can collide
}
```
- 충돌 그룹을 사용하면 통합 그룹 인덱스를 지정할 수 있다.
- 동일한 그룹 인덱스를 가진 모든 fixture가 항상 충돌(양수 인덱스)하거나 충돌하지 않도록(음수 인덱스) 할 수 있다.
- 이것은 일반적으로 자전거 부품과 같이 관련성이 있는 항목에 사용된다.
- 아래의 예에서 fixture1 과 fixture2는 항상 충돌하지만 fixture3과 4는 절대 충돌하지 않는다.
```cpp
fixture1Def.filter.groupIndex = 2;
fixture2Def.filter.groupIndex = 2;
fixture3Def.filter.groupIndex = -8;
fixture4Def.filter.groupIndex = -8;
```
- 다른 그룹 인덱스의 fixture간의 충돌은 카테고리 및 마스크 비트에 따라 필터링된다.
- 즉, 그룹 필터링은 카테고리 필터링보다 우선순위가 높다.
- 추가적으로 알아야하는 필터링은 다음과 같다.
- static body에 붙은 fixture는 오직 dynamic 과 충돌
- kinematic body에 붙은 fixture는 오직 dynamic 과 충돌
- 같은 body에 붙은 fixtures는 결코 서로 충돌하지 않는다.
- 추가적으로 joint로 연결된 body의 fixture간의 충돌을 선택적으로 활성화/비활성화 할 수 있다.
- 때때로 fixture가 이미 생성된 후에 filtering을 변경해야할 수 있다.
- [GetFilterData](https://box2d.org/documentation/classb2_fixture.html#ad956250d9f684a407992ec178320127e), [SetFilterData](https://box2d.org/documentation/classb2_fixture.html#a2c5e0d12c174927a4ad550459be334ad)를 사용하여 b2Filter 구조를 가져오고 설정할 수 있다.
- 필터 데이터를 변경해도 다음 time step까지 접촉점(contacts)이 추가되거나 제거되지 않는다. (world class)
### 5.2.6. **Sensors**
- 두개의 fixture가 겹치지만 충돌 응답이 없어야 할 때.
- 센서는 충돌을 감지하지만 응답을 생성하지 않는 fixture이다.
- 모든 fixture를 센서로 표시할 수 있다.
- static, kinematic, dynamic
- 센서와 solid fixture를 혼합하여 사용할 수 있다.
- 센서는 최소한 하나의 body가 동적일 때만 접점을 형성(감지)한다.
- 센서는 접점을 생성하지 않는다.
- 두가지 방법으로 센서 상태를 가져올 수 있다.
1. [b2Contact::IsTouching](https://box2d.org/documentation/classb2_contact.html#a681346f93e2a27403383775a752c06a0)
2. [b2ContactListener::BeginContact](https://box2d.org/documentation/classb2_contact_listener.html#a35148fc56fb9eac12077200fbd928f65) and [b2ContactListener::EndContact](https://box2d.org/documentation/classb2_contact_listener.html#afb3059058e5c47903a3947c2eef5826b)
## 5.3. **Joints**
Joint Definition
Joint Factory
Using Joints
Distance Joint
Revolute Joint
Prismatic Joint
Pulley Joint
Gear Joint
Mouse Joint
Wheel Joint
Weld Joint
Rope Joint
Friction Joint
Motor Joint
Wheel Joint
## 5.4. **Contacts**
Contact Class
Accessing Contacts
---
Contact Listener
shape
rigid body
fixture
constraint
contact constraint
joint
joint limit
joint motor
world
solver
continuous collision
b2_staticBody
b2_kinematicBody
---
b2_dynamicBody
contact point
contact normal
contact separation
contact manifold
normal impulse
tangent impulse
contact ids
---
Begin Contact Event
End Contact Event
Pre-Solve Event
Post-Solve Event
---
Contact Filtering
## 5.5. **World**
Creating and Destroying a World
Using a World
Simulation
Exploring the World
AABB Queries
Ray Casts
# 6. **Loose Ends**
## 6.1. **User Data**
## 6.2. **Custom User Data**
## 6.3. **Implicit Destruction**
## 6.4. **Pixels and Coordinate Systems**
## 6.5. **Debug Drawing**
## 6.6. **Limitations**
# 7. links
https://box2d.org/documentation/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment