2014년 2월 25일 화요일

[일기]Box2D 도전, body의 개념.

Box2D에 body란 개념이 있었다.

난 이게 딱딱하고 충분히 변형되지 않는 물체라 생각하여 강체라고 부르기로 했다. 아니면 말고.


 그러나 이 강체 개념은 육안으로 관찰되는 것이 아니며 실제 충돌에 관혀하는 입자들도 아니다. 단지 물체의 물리적 속성을 의미한다.

 물체가 갖는 특징을 속성으로 가진다. 질량, 속도, 회전저항성, 각속도, 위치, 회전각과 같은 물리량들을 담는다고 보면 된다.

 실제 외형(실체 충돌에 관여하는 입자들의 집합;거시적)을 명시하려면 Fixture라는 고정물(붙박이)를 이용해야만 한다.

 강체는 이용 목적을 기준으로 세 가지로 분류된다.

 dynamic(동적 강체), static(정적 강체), kinematic(역학, 운동 강체)가 그 분류이다. 첫 두개는 단어만 보고 즉시 대략적으로 그 특성을 유추할 수 있다. 그러나 후자는 그렇지 않다.

 약술하면, 동적 강체는 실질적으로 움직이는, 물리적 특성을 따르는 모든 물체를 정의할 때 쓰인다. 예로 비행하는 야구공이나 탄환을 생각하면 된다.

 정적 강체는 그 수준이 매우 거시적이거나 물리적 영향의 효과가 미미하여 무시할 수 있는 수준의 물체를 정의할 때 쓰인다. 예로 인간 크기의 시점에서 지면이나 차량의 고정의자는 그 고정성이 매우 크므로 움직임이 거의 없는 것으로 간주될 수 있는데 이를 정의할 때 쓰인다. 단순히 절대 움직이지 않는 물체이다.

 역학 강체는 운동강체로 정적 강체와 같은 특성을 지니나 역학적으로 움직이고 있는 강체를 말한다. 정적 강체와 마찬가지로 그 움직임이나 특성에 있어 외부의 왠만한 힘을 가해졌을 때 물리적으로 받는 그 영향역이 매우 미비한 수준을 가지는 경우에 적용된다. 추가적인 점은 단지 이 물체는 움직인다는 것이다. 가령, 풍력 발전기의 날개나 에스컬레이터, 엘리베이터와 같은 것을 생각하면 된다. 그 위에 올라간 무게가 어떻든 간에(얼마나 밑으로 힘을 가하든 간에) 그것들은 느려지거나 하는 것 없이 움직인다.(물론 사람이 너무 많이 탄 경우는 예외이긴 하나 일반적 예를 들고자 하였다) 단순히 관성히 무한인 절대 운동을 방해받지 않는 물체이다.

 강체 생성

 강체를 생성하려면 정해진 순서를 따른다.

 첫째, 강체가 가질 물리적 특성들을 지정(강체 정의)한다. 이는 b2BodyDef 구조체를 통해 할 수 있다.

 둘째, 강체의 정의를 이용하여 World 클래스로 하여금 강체를 생성하도록 한다.

 셋째, World 클래스가 리턴한 포인터를 강체를 가리키는 포인터 객체로 받는다.

 다음은 그 예시이다.



 m_world는 상속받은 Test 클래스의 맴버 변수이다. 나중에 설명한다.

 설정을 세 가지만 하였다. 질량과 같은 정보는 하지 않았는데 이는 고정물(Fixture)을 정의할 때 자동으로 설정되는 부분이다.



 여기까지 진행 후 프로그램을 실행을 하여도 특별히 눈에 보여지는 부분은 없다. 만일 Testbed 프로그램의 우측에 있는 Center of Masses 체크박스에 체크를 하였다면, 질량중심이 지나간 흔적을 볼 수는 있을 것이다.

 간단히 고정물을 붙여 모양을 육안으로 확인해보자. 간단히 먼저 언급하자면 강체에는 여러개의 고정물이 연결될 수 있다. 그리고 이 고정물들은 그 부피와 밀도에 근거하여 정의한 강체의 실제 질량을 결정하게 된다. 질량은 고정물의 면적에 비례하며 후에 정의할 density(밀도)값에 정비례하는 특징을 갖는다.

 고정물을 정의하려면 외형(shape)를 선언하고 이를 고정물에 설정해야 한다. 고정물 또한 정의를 먼저 생성하는 과정을 거치며 다른 객체를 통해 만들어진다. 강체가 world클래스로부터 생성되어 리턴되었다면, 고정물은 연결될 강체 객체로부터 생성된다.


 생성자로 위 선언문을 옮겼다.


 적용한 결과 화면이다. 밑으로 떨어진다.

 이제 모양도 확인할 수 있으니 다음도 확인해본다.

 정적 강체 생성.
                defineOfBody.type = b2_staticBody;
defineOfBody.position.Set(0, 10);
b2Body* staticBody = m_world->CreateBody(&defineOfBody);
staticBody->CreateFixture(&squreFixtureDefine);



 정적 강체는 충돌에서 어떠한 영향도 받지 않는다. 동적 강체와 충돌 가능하며 항상 고정 위치를 고수하는데 성공한다.

 다음은 역학 강체이다.

                defineOfBody.type = b2_kinematicBody;
defineOfBody.position.Set(-18, 11);
b2Body* kinematicBody = m_world->CreateBody(&defineOfBody);
kinematicBody->CreateFixture(&squreFixtureDefine);

kinematicBody->SetLinearVelocity( b2Vec2(1, 0));
kinematicBody->SetAngularVelocity( 360 * 3.141592/180.0);

 타입을 변경하고 위치를 좌측으로 이동하고 생성한다. 선속도를 지정했으며 각속도 또한 지정했다. 각속도 인자는 라디안을 기준 단위로 쓴다.

 참고로 Testbed에서 정적 강체는 녹색으로, 역학 강체는 청색으로 표시해 준다.


 역학 강체는 정적 강체와 충돌하지 않는다. 화면은 우측으로 이동한 역학 강체가 동적 강체를 튕겨낸 모습이다.


 강체의 속성들을 얻어오기

 경우의 수는 2가지가 대표적이다. 첫째는 강체의 포인터를 이용하여 정보를 얻는 방법이고, 둘째는 World 클래스로부터 강체 포인터의 링크드 리스트 자료구조를 받아와 각 강체별 포인터를 얻어내고 메서드를 이용하여 정보를 얻는 것이다.

  b2Vec2 pos = pBody->GetPosition();
  float angle = pBody->GetAngle();
  b2Vec2 v = pBody->GetLinearVelocity();
  float angularV = pBody->GetAngularVelocity();
  m_debugDraw.DrawString(5, m_textLine, 
    "Position:%.3f,%.3f Angle:%.3f", pos.x, pos.y, angle * 180.0/3.141592);
  m_textLine += 15;
  m_debugDraw.DrawString(5, m_textLine, 
    "Velocity:%.3f,%.3f Angular velocity:%.3f", v.x, v.y, angularV * 180.0/3.141592);
  m_textLine += 15;




  for ( b2Body* b = m_world->GetBodyList(); b; b = b->GetNext())
  {
      //작업 수행
  }

 강체 제거하기

 강체 제거는 World 클래스에서 이루어진다. 주의할 점은 강체를 제거하면 이곳에 연결된 고정물이나 접합점들이 다 제거된다. 제거한 뒤 포인터 변수를 사용하지 않도록 주의하면 된다.

  m_world->DestroyBody(pBody); //pBody : 제거할 강체의 포인터

 이상.

 자료의 대부분은 http://www.iforce2d.net/b2dtut/bodies에서 학습하였다.

-----------------------------------------------------
Box2D는 물리적 현상을 모사하는데 있어서 몇 가지의 전제를 두고 있다.

 그 중 한 가지는 모든 물체는 완벽한 강체라는 사실이다. 즉, 물체로 대표되는 강체는 절대로 형체가 변형되지 않는다는 뜻이다. 찌그러지거나 깨지거나 하는 현상은 없다.

 그런데 Body는 누구든 이름만 봐도 이 클래스가 강체를 대표하는 구나하는 판단 정도는 내릴 수 있을 정도로 그 이름 자체가 직관적이다.

 그러나, box2D에서 Body라는 이름으로 표현되는 강체는 우리가 일반적으로 사고하는 것과는 약간 다른 특징을 지닌다.

 보통 사람들은 강체를 그냥 물체들 즉, 형태가 있고, 시각적으로 관찰될 수 있는 물체들로 인식한다. 그러나 Box2D에서도 이와 같이 생각하면 오해가 빚어진다.

 Box2D에서의 Body는 무형이다. 다만 물체의 특성만을 가진 추상적인 개념이다. 물체를 세계에 나타내기 위한 정보들만이 있다고 보면 된다.

 간단하게 말해서, 가질 수 있는 정보는 대표적으로 다음과 같다.

 1. 강체의 타입
 2. 강체의 위치

 Box2D에서는 강체를 세 가지 범주로 나누어 처리한다. 첫째는 동적 강체이며, 둘째는 정적 강체, 마지막 한 가지는 운동 강체이다.

 동적 강체는, 다시 표현하여 힘의 영향을 받아 운동하는 물체로 일반적인 상식선의 물체들과 같다고 보면 된다. 가령, 의자, 상자, 공 등이 해당된다. 공은 차면 날아가고, 의자는 사람을 받칠 수 있으며, 상자는 운반될 수 있다.

 정적 강체는, 고정되어 절대 움직이지 않는 물체를 말한다. 길바닥이나, 지층의 암석, 건축물 등은 사람의 시각에서는 고정되어 있는 것들로 움직임이 없다. 이러한 개념을 나타내는 타입이다.

 운동 강체는, 정해진 운동을 하는 물체로 운동의 흐름을 절대 방해받지 않는 물체이다. 지구는 사람들이 점프를 뛰고 폭탄을 지면에 떨구어도 자전을 멈추지 않는다. 좀더 작은 개념에서 엘리베이터에 만원을 초과하는 사람이 탑승하지 않는 한, 1명이 탑승하든 12명이 탑승하든 1층에서 100층까지 도달하는 시간은 같다.

 강체의 위치는 물체들이 화면에서 위치할 장소를 지정하는 것으로 2차원의 좌표벡터로 나타난다. X와 Y값의 쌍으로 값을 지정할 수 있으며, 이후 물체가 움직일 때마다 갱신되는 값이므로 이 값을 얻어오면 현재 물체가 어디에 있는지를 확인할 수 있다.

 몇가지 Box2D의 설정이 있는데, 다음과 같다.

 동적 강체는 다른 모든 타입과 충돌한다. 동적 강체끼리는 당연히 충돌 가능하다. 정적 강체나, 운동 강체와 충돌하면 튕겨 나간다. 정적 강체는 절대 움직이지 않는다. 

 정적 강체와 운동 강체끼리는 그러나, 충돌하지 않는다. 모순이라는 단어가 나온 배경을 생각해 볼때, 이치에 맞는 듯하다. 정적 강체는 절대로 움직이지 않는다. 반면, 운동 강체는 절대 운동을 방해받지 않는다. 이는 앞으로 나가는 물체가 절대 벽에 막혔다고 해서 멈춘다거나 하지 않는다는 뜻이다. 그러나 이 가정은 서로 엇갈린다. 이에 Box2D에서는 아예 충돌처리를 하지 않는 것으로 마무리 지었다.

댓글 없음:

댓글 쓰기