2014년 3월 4일 화요일

[일기] box2D, Ghost_vertieces, 유령 정점들.

http://www.iforce2d.net/b2dtut/ghost-vertices 에서 다음을 설명했다.

가장 흔한 질문은 고정체들을 평평하게 배치했음에도 불구하고 그 위를 수평으로 이동하는 고정체가 갑자기 돌부리에 걸린 듯 행동한다는 것.

 이 원인은 Box2D의 충돌 판정이 다물체간이 아닌 단 2개 고정체 사이에서만 이루어지기 때문이라는 것이다.

 눈에는 보이지 않으나 두 고정체가 상호간 위아래로 위치해 있고 중력이 작용한다면, 그리고 아래 고정체의 강체는 정적이라면, 위에 있는 고정체는 위로부터 중력을 받고, 아래로부터 수직항력을 받게 된다. 이 때, 위에 있는 고정체는 상하로 진동한다.



 이렇게 진동하고 있는 고정체가 우측으로 이동할 경우, 지면을 구성하는 고정체들과 연이어 충돌하게 된다. 만일 지면을 구성하는 고정체들이 사각형이고 이 사각형들이 서로 꽉 붙어서 긴 직사각형을 형성하고 있다면, 위의 고정체는 이동시마다 각 지면을 구성하는 고정체들의 좌측 모서리와 충돌하게 된다.

 중요한 사실은 고정체간의 충돌이 일어나면,  Box2D에서는 그 겹친 영역을 가장 빨리 벗어나도록 힘을 적용하게 된다는 사실이다.

[그림 1]

[그림 2]


 이 때, 진동하던 고정체는 위아래로 아래 고정체들과 계속 겹쳐진다. 단일 고정체 위에 있는 경우에서 충돌하는 경우 [그림2]와 같이 위아래로 힘이 가해져 계속 상하로 진동하하게 된다. 그런데 충돌은 2개 사이에서만 처리된다. 다음과 같은 상황이 일어난다.
위 고정체가 경계를 이동한다.
충돌은 각 2개씩의 고정체들 사이에서만 처리된다. 좌측은 [그림 2]와 같이 수평하게 겹쳐 위아래로 벗어나는 것이 빠르기 때문에 힘이 상하로 작용한다.

우측의 경우 상황은 달라진다. 아직 우측으로 많이 이동하지 못하여 [그림 1]처럼 충돌할 수도 있고 충분히 많이 이동하여 [그림 2]처럼 충돌할 수도 있다.


 이 때 문제가 발생한다고 한다. 그러나 사실 그렇게 빈번하게 일어나지는 않는다고 하는데 경험해 봐야 할 것 같다.

첫째 해결 방법은 고정체들의 경계를 깎는 것이다.

Box2D ghost vertex

[그림 출저 :  http://www.iforce2d.net/b2dtut/ghost-vertices]

 이 경우 힘은 위쪽으로 충분히 작용한다. 저렇게 되면 위쪽 고정체는 반시계 방향으로 회전할 것 같지만 사실 좌측에는 이미 지면이 있고 그 지면은 위쪽 고정체를 위쪽으로 밀어내므로 문제가 되지 않는다.

 경계를 위 그림에서는 위쪽 고정체만 깎았으나, 지면을 깍아도 되고 둘 다 깎아도 된다.
물론 위쪽 고정체가 원이라면 문제는 거의 발생하지 않는다.

둘째 해결 방법은 경계선을 이용하는 것이다. EdgeShape로 일컬어지는 클래스를 이용하여 똑같이 지형을 연이어 연결하면, 고정체를 이용하는 것보다 상당히 튕겨지는 빈도가 적어진다.

 그러나 직선이라면 그냥 하나로 다 긋는게 여러 선분을 잇는 것보다 편하지 않나..?

 셋째 방법이 유령 정점이다.


 v1, 과 v2는 실제 화면에 나타나 충돌 대상이 되는 경계를 그릴 정점이며, v0와 v3은 외각 정점으로 화면에 보이지 않는다. 또한 직접적인 충돌 대상도 아니다.

 단, 실제 영역인 v1과 v2 사이에서 충돌이 일어날 때는 엄연한 충돌 판정 영역의 확장으로서 작용하게 된다.

b2EdgeShape edgeShape;
  edgeShape.Set( v1, v2 );
  edgeShape.m_vertex0.Set( v0 );
  edgeShape.m_vertex3.Set( v3 );
  edgeShape.m_hasVertex0 = true;
  edgeShape.m_hasVertex3 = true;

로 설정하며, Vertex0 과 Vertex3은 각각 위 그림의 v0과 v3을 의미한다.






기가 막히다.

댓글 없음:

댓글 쓰기