블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2794)
Unity3D (852)
Programming (478)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (185)
협업 (11)
3DS Max (3)
Game (12)
Utility (68)
Etc (98)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (55)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday

Ogre로 프로젝트를 하면서 가장 시간을 많이 들였던 충돌 처리 부분 입니다. 
처음에는 물리 엔진을 써보고자 Physx , bullet, OgreODE 등 많은 물리엔진을 찾아서 사용 해보려 했지만...;;
결국 Ogre로 구현을 하게 되었습니다. ;; 
게임 개발에 필요한 수학적 지식이 부족한 상황에서 검색을 하던중 directx 로 구현한 OBB 충돌 소스를 찾게 되어서 
그 소스를 이용하여 Ogre에서 구현을 해봤습니다. 

dx 소스는 GpgStudy 에서 참고 하였습니다. 
Link에 추가 해놓으테니까 참고 하시면 좋을 것 같습니다~~
그리고 이만희님의 OBB 충돌 논문(Fast Overlap Test for OBB)
을 보시면 그래도 이해더 좀더 되 실 겁니다.
첨부 파일로 올려 놓겠습니다.(올려도 되려나??)


 
-소스 코드- 

BOOL PlayState::centerOBB(OBBoxRenderable* OBB1, OBBoxRenderable* OBB2)
{

 //box1이 이동하는 OBB / box2는 고정되어 있는 OBB

 Vector3 obb1_center, obb2_center, T, LL; //box1,box2 의 각각 센터 좌표, 
 Real box_len, a1, a2, a3, b1, b2, b3, TL;
 Matrix4 obb1_invers_mat, obb2_rotae_mat;
 Matrix4 R ;

 //OBB 박스의 월드 좌표??
 obb1_invers_mat = OBB1->getCharMat.inverse();
 obb2_rotae_mat = OBB2->getMonMat();

 //box1 의 좌표계를 box2의 좌표계로 회전변환 행렬 R = RA-1 * RB(-1은 iverse)
 R = obb1_invers_mat * obb2_rotae_mat;

 //box의 좌표축의 normal vector x, y, z 값 (제가 이해한 내용 - 틀린 내용 일 수도 있음 ㅋ)

 Vector3 obb1_size = OBB1->getWorldBoundingBox().getSize();
 Vector3 obb2_size = OBB2->getWorldBoundingBox().getSize();

 a1 = obb1_size.x; 
 a2 = obb1_size.y ;
 a3 = obb1_size.z ;

 b1 = obb2_size.x ;
 b2 = obb2_size.y ;
 b3 = obb2_size.z ;

 obb1_center = OBB1->getWorldBoundingBox().getCenter();
 obb2_center = OBB2->getWorldBoundingBox().getCenter();


 //box1 의좌표계에서 box1 중심에서 box2의 중심으로의 이동을 나타내는 vector3
 T = Vector3(obb1_center.x - obb2_center.x, obb1_center.y - obb2_center.y, obb1_center.z - obb2_center.z);

 //0. LL = A1
 box_len = a1 + b1 * R[0][0] + b2*R[0][1] + b3*R[0][2];
 LL =Vector3(1.0f, 0.0f, 0.0f); //분할 축의 벡터 
 TL = T.absDotProduct(LL); //T 와 L의 내적의 절대값
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }
 
 //1. LL = A2
 box_len = a2 + b1 * R[1][0] + b2*R[1][1] + b3*R[1][2];
 LL = Vector3(0.0f, 1.0f, 0.0f);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //2. LL = A3
 box_len = a3 + b1 * R[2][0] + b2*R[2][1] + b3*R[2][2];
 LL = Vector3(0.0f, 0.0f, 1.0f); 
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //3. LL = RB1[R11 R21 R31]
 box_len = a1*R[0][0] + a2 * R[1][0] + a3*R[2][0] + b1;
 LL = Vector3(R[0][0], R[1][0], R[2][0]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //4. LL = RB2[R12 R22 R32]
 box_len = a1*R[0][1] + a2 * R[1][1] + a3*R[2][1] + b2;
 LL = Vector3(R[0][1], R[1][1], R[2][1]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //5. LL = RB3[R13 R23 R33]
 box_len = a1*R[0][2] + a2 * R[1][2] + a3*R[2][2] + b3;
 LL = Vector3(R[0][2], R[1][2], R[2][2]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //6. LL = A1 X RB1 = [1 0 0] X [R13 R23 R33] = [ 0 -R31 R21 ]
 box_len = a2*R[2][0] + a3*R[1][0] + b2*R[0][2] + b3*R[0][1];
 LL = Vector3(0.0f,  R[2][0], R[1][0]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //7. LL = A1 X RB2 = [1 0 0] X [R12 R22 R32] = [ 0 -R32 R22 ]
 box_len = a2*R[2][1] + a3*R[1][1] + b1*R[0][2] + b3*R[0][0];
 LL = Vector3(0.0f,  -R[2][1], R[1][1]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //8. LL = A1 X RB3 = [1 0 0] X [R13 R23 R33] = [ 0 -R33 R23 ]
 box_len = a2*R[2][2] + a3*R[1][2] + b1*R[0][1] + b2*R[0][0];
 LL = Vector3(0.0f,  -R[2][2], R[1][2]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //9. LL = A2 X RB1 = [0 1 0] X [R11 R21 R31] = [R31 0 -R11]
 box_len = a1*R[2][0] + a3*R[0][0] + b2*R[1][2] + b3*R[1][1];
 LL = Vector3(R[2][0], 0.0f, R[0][0]);
 TL = LL.absDotProduct(T);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //10. LL = A2 X RB2 = [0 1 0] X [R12 R22 R32] = [R32 0 -R12]
 box_len = a1*R[2][1] + a3*R[0][1] + b1*R[1][2] + b3*R[1][0];
 LL = Vector3(R[2][1], 0.0f, -R[0][1]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //11. LL = A2 X RB3 = [0 1 0] X [R13 R23 R33] = [R33 0 -R13]
 box_len = a1*R[2][2] + a3*R[0][2] + b1*R[1][1] + b2*R[1][0];
 LL = Vector3(R[2][2], 0.0f, -R[0][2]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
 /* cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //12. LL = A3 X RB1 = [0 0 1] X [R11 R21 R31] = [-R21 R11 0]
 box_len = a1*R[1][0] + a2*R[0][0] + b2*R[2][2] + b3*R[2][1];
 LL = Vector3(-R[1][0], R[0][0], 0.0f);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //13. LL = A3 X RB2 = [0 0 1] X [R12 R22 R32] = [-R22 R12 0]
 box_len = a1*R[1][1] + a2*R[0][1] + b1*R[2][2] + b3*R[2][0];
 LL = Vector3(-R[1][1], R[0][1], 0.0f);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //14. LL = A3 X RB3 = [0 0 1] X [R13 R23 R33] = [-R23 R13 0]
 box_len = a1*R[1][2] + a2*R[0][2] + b1*R[2][1] + b2*R[2][0];
 LL = Vector3(-R[1][2], R[0][2], 0.0f);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
 /* cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //cout << "충돌!!" << endl;
 return 1;
}

구현을 해서 실행을 시켜본 결과 충돌 검출은 잘 하는데 살짝 떨어져 있어도 충돌 체크를 하는 경우가 있는데,
이유는 저도 잘...ㅠㅠ 그래도 이렇게해서 충돌 체크를 한다는거에 감사할 따름입니다. ㅋㅋ
혹시 소스 자체에 수정 할 부분이 있다고 생각되시는 분은 가르침 부탁 드리겠습니다^^ㅋ

인증샷!!!!



 Ps. box의 Matrix를 받아 오는 함수를 사용해서 Matrix값을 받아오게 했었는데, 값이 이상 했나 보네여 ;; 충돌 처리가  정확히 되지 않았습니다. 그래서 객체의 Entity 의_getBoneMatrices.transpose()를 사용해서 Matrix값을 받아 와서 충돌처리를 했더니 정확하게 OBB의 충돌 위치에서 멈추는 것을 확인 할 수 있었습니다. 

아직 정확한 Ogre의 분석이 되지 않은 상태에서 이것 저것 해보다가 얻어 걸린 것이라서 정확하게 어떻다라는 것을 제가 말씀 드릴 수는 없을 것 같습니다. 이해해 주시길..^^;; ㅋㅋ

(소스에서 이상한점을 발견 하시거나 잘못 된 곳을 발견하시면 저에게도 살포시 알려주세요~ㅋㅋㅋ)



출처 : http://eguru.co.kr/986

반응형
Posted by blueasa
, |