본문 바로가기

프로그래밍 -----------------------/C,C++ 팁

평면의방정식을 이용한 면<->점 충돌채크



// 노멀값을 구하기 위한 벡터 빼기 순서
 // 루프를 돌려서 처리하고 싶기에 이렇게 인덱스를 만듬
 //      면 0  1  2          3  4  5
 WORD wIndex[] = { 2, 3, 4, /* | */ 5, 7, 6,
                             3, 4, 2, /* | */ 7, 6, 5};
 
 // 폴리곤의 법선을 구한다.
 D3DXVECTOR3 vV1,vV2;
 float d1,d2,dir;
 
 int nCnt=0;
 int nCollCount=0; // 충돌한 면의 카운트
 for(j=0; j<6; j++)
 {
  if(j>=3) nCnt=1;
  
  // 세점에서 법선 구하기
  vV1 = vPoint[ wIndex[j] ] - vPoint[ nCnt ];
  vV2 = vPoint[ wIndex[j+6] ] - vPoint[ nCnt ];
  D3DXVec3Cross(&vNormal[j],&vV1, &vV2);   // 법선을 구한다.   
  D3DXVec3Normalize(&vNormal[j],&vNormal[j]);  // 법선을 노멀화
  
  // 평면 방정식에 D 값 구하기 ( AX+BY+CZ+D = 0 )
  // D = -(AX+BY+CZ)
  // = -( (a,b,c) * (x,y,z) )
  //
  
  // Step.1
  // 먼저 평면에 포함되어 있는 점을 가지고 d 값을 구한다.
  // 원점을 중심으로 노멀값으로부터 떨어진 점(vPoint)의 d 값을 구하면,
  // 원점의 평면에서, 평면 방정식을 성립함 (당연 점(vPoint)는 캐릭터의 바운딩박스임)
  d1 = -D3DXVec3Dot(&vNormal[j],&vPoint[nCnt]);
  
  // Step.2
  // 마찬가지로 vDest를 원점의 평면에서 d값을 구한다.
  d2 = -D3DXVec3Dot(&vNormal[j],&vDest);
  
  // Step.3
  // 마지막으로 d1과 d2값을 뺀다.
  // 먼저 빼는 넘(지금은 d1)을 기준으로 d2가 있는 방향과 거리가 나온다.
  // 두개의 값을 뺀 결과 값이, [+] 값이라면 d2는 d1의 오른쪽(+방향)에 있는 것이며,
  // [-] 값이라면 d2는 d1에 왼쪽(-방향)에 위치하고 있다.
  // 만약 0이면 d2는 d1에 완전히 포함했다. 라는게 성립된다.
  dir = d1 - d2;
  
  if( dir < 0 ) // 0 보다 작으면 더 계산할 필요없이, 충돌이 아님
   break;  // 현재 for문을 끊어버림~ 
  
  // 여기까지 오면 일단 현재 면은 충돌로 판정해야 한다.
  ++nCollCount; // 충돌면의 숫자를 늘린다.
 }
 
 if( nCollCount >= 6) // 충돌한 면이 6면보다 많다면, 물론 많을순 없지만 -_-
 {
  return true; // 충돌 되었다고 알리고, 여기서 충돌채크는 끝을 낸다.
 }