OBB¿Í OBBÀÇ Ãæµ¹¿¡ ´ëÇؼ ¾Ë¾Æ º¸ÀÚ. ÀÚ¼¼ÇÑ ¼³¸íÀº »ý·«ÇÏ°í ´ÙÀÌ·ºÆ®X·Î ÄÚµå ±¸Çö¿¡ ÁßÁ¡À» µÐ´Ù. »ç¿ë ¹æ¹ý : È»ìÇ¥ Up, Down Å° : ¾ÕÀ¸·Î , µÚ·Î È»ìÇ¥ Right Å° : ¿À¸¥ÂÊ ÁÖÀüÀÚ È¸Àü ¿À¸¥ÂÊ ´ëÈ»óÀÚ x axis, y axis, z axis : ¿ÞÂÊ ÁÖÀüÀÚ È¸ÀüÃà "+" Å° : ´ëÈ»óÀÚ¿¡¼ ÁöÁ¤ÇÑ È¸ÀüÃàÀ¸·Î ȸÀü ÄܼÖâ¿¡ Ãæµ¹ ·Î±×°¡ ½Ç½Ã°£À¸·Î ³ª¿Â´Ù. ÀÌ ÇÁ·Î±×·¥¿¡ »ç¿ëµÈ ±âº» Áö½ÄÀÌ´Ù. À©µµ¿ìÁî ÇÁ·Î±×·¥¿¡¼ ÄܼÖâÀ» ¶ç¿ì±â¼Ò½º¿¡ ´ÙÀ½ ¶óÀÎÀ» Ãß°¡ÇÑ´Ù.#pragma comment(linker , "/entry:WinMainCRTStartup
/subsystem:console")
directxÀÇ Çà·ÄÀÇ °áÇÕ ¼ø¼directxÀÇ Çà·ÄÀÇ °áÇÕ ¼ø¼´Â SRTÀÌ´Ù.S * R * T (Scaling * Rotation(Rz*Rx*Ry) * Translation) ȸÀü Çà·ÄÀº Z, X, Y ¼ø¼·Î °áÇյȴÙ. D3DXMatrixRotationYawPitchRoll( &matRotation, fRotY, fRotX, fRotZ ); or D3DXMatrixRotationX( &matRotationX, fRotX ); D3DXMatrixRotationY( &matRotationY, fRotY ); D3DXMatrixRotationZ( &matRotationZ, fRotZ ); matRotation = matRotationZ * matRotationX * matRotationY; D3DXCreateBox¿¡ Ä®¶ó Àû¿ëOBB ¹Ú½º¸¦ ±×¸®±â À§ÇØ ¾Æ·¡ ÇÔ¼ö¸¦ »ç¿ëÇÑ´Ù.D3DXCreateBox ¹Ú½º¸¦ ¸¸µçÈÄ ¸Þ½¬¸¦ Ŭ·ÐÇؼ Ä®¶ó¸¦ Ãß°¡ÇÑ´Ù. bool CreateBox(float w, float h, float d, int color,
ID3DXMesh **mesh)
{ assert(g_dxDevice != NULL); assert(mesh != NULL); ID3DXMesh *tempMesh; // Temp D3D mesh object // Create the sphere if(D3DXCreateBox(g_dxDevice, w, h, d, &tempMesh, NULL) != D3D_OK) return false; // Flag for how to create the D3D mesh. We want the vertex buffer and index // buffer memory to be managed by DirectX DWORD flag = D3DXMESH_VB_MANAGED | D3DXMESH_IB_MANAGED; // Copy the sphere, converting to our FVF if(tempMesh->CloneMeshFVF(flag, SVertexType, g_dxDevice, mesh) != D3D_OK) return false; SVertex *v; // Lock the vertex data of our box if((*mesh)->LockVertexBuffer(0, (void**)&v) != D3D_OK) { (*mesh)->Release(); return false; } // Set the box's color for(unsigned int i = 0; i < (*mesh)->GetNumVertices(); ++i) v[i].color = color; // Unlock the vertex data (*mesh)->UnlockVertexBuffer(); tempMesh->Release(); // Free up the temporary mesh return true; } ÁÖÀüÀÚ ÀÔ·Â Á¦¾î Update ÇÔ¼ö¿¡¼ Å°·Î Á¦¾î ÇÑ´Ù. void Update()
{ if (GetAsyncKeyState(VK_UP) & 0x8000) g_pos += (g_dir*g_move_unitys); if (GetAsyncKeyState(VK_DOWN) & 0x8000) g_pos += (-g_dir*g_move_unitys); if (GetAsyncKeyState(VK_RIGHT) & 0x8000) { float angle = GetAngle(g_dir.x, -g_dir.z); angle += 1.0f; float radian = D3DXToRadian(angle); D3DXMATRIX mat; D3DXMatrixRotationY(&mat, radian); g_dir = D3DXVECTOR3(1, 0, 0); D3DXVec3TransformCoord(&g_dir, &g_dir, &mat); } if (GetAsyncKeyState(VK_OEM_PLUS) & 0x8000) { g_angle2 += 1.0f; } } OBB ¿Í OBB Ãæµ¹ OBB ±¸Á¶Ã¼´Â Áß½ÉÁ¡ ÁÂÇ¥, ÁÂÇ¥ÃàÀÇ È¸ÀüÀ» ³ªÅ¸³½´Â ¹æÇâ º¤ÅÍ, ÁÂÇ¥ÃàÀÇ ¹ÝÁö¸§À» ³ªÅ¸³½´Ù. #define SVertexType D3DFVF_XYZ | D3DFVF_DIFFUSE
//vertex struct struct SVertex { float x, y, z; DWORD color; //diffuse color }; struct OBB { D3DXVECTOR3 c; // Áß½ÉÁ¡ ÁÂÇ¥ D3DXVECTOR3 u[3]; //XYZ ÁÂÇ¥ÃàÀÇ È¸ÀüÀ» ³ªÅ¸³»´Â ¹æÇâ º¤ÅÍ D3DXVECTOR3 r; // ÁÂÇ¥ÃàÀÇ ¹ÝÁö¸§ }; struct VERTEX { D3DXVECTOR3 position, normal; //float tu, tv; }; LPD3DXMESH ¸Þ½¬·Î ºÎÅÍ OBB ¹Ú½º¸¦ ¸¸µç´Ù. void ReadObb(LPD3DXMESH pMesh, D3DXMATRIX& mat,
LPD3DXMESH pMesh1, D3DXMATRIX& mat1)
{ ReleaseOBB(); CreateOBB(&g_obb1, pMesh, mat); CreateOBB(&g_obb2, pMesh1, mat1); OBB* obb = &g_obb1; CreateBox(obb->r.x*2.0f, obb->r.y*2.0f, obb->r.z*2.0f, 0xff0000, &g_boxMesh1); obb = &g_obb2; CreateBox(obb->r.x*2.0f, obb->r.y*2.0f, obb->r.z*2.0f, 0xffff, &g_boxMesh2); if(TestOBBOBB(&g_obb1, &g_obb2)) printf("TestOBBOBB is collision\r\n"); else printf("TestOBBOBB is none collision\r\n"); } void CreateOBB(OBB* obb, LPD3DXMESH pMesh, D3DXMATRIX& mat) { // ÃÖ´ë °ª, ÃÖ¼Ò°ªÀÇ Ãʱ⠰ª ¼³Á¤ D3DXVECTOR3 max = D3DXVECTOR3( -10000.0f, -10000.0f, -10000.0f); D3DXVECTOR3 min = D3DXVECTOR3( 10000.0f, 10000.0f, 10000.0f); //¸Þ½¬ÀÇ Á¤Á¡ µ¥ÀÌÅ͸¦ ¾ò¾î¿Â´Ù. VERTEX * vertexBuffer = NULL; pMesh->LockVertexBuffer( 0, (void **)&vertexBuffer); // ÃÖ´ë °ª, ÃÖ¼Ò°ª ±¸Çϱâ int num = (int)pMesh->GetNumVertices(); for (int i = 0; i < num; i ++) { D3DXVECTOR3& pos = vertexBuffer[i].position; if (pos.x <min.x) min.x = pos.x; if (pos.x> max.x) max.x = pos.x; if (pos.y <min.y) min.y = pos.y; if (pos.y> max.y) max.y = pos.y; if (pos.z <min.z) min.z = pos.z; if (pos.z> max.z) max.z = pos.z; } pMesh->UnlockVertexBuffer(); // Áß½ÉÁ¡ ±¸Çϱâ D3DXVECTOR3 worldPos = D3DXVECTOR3( mat._41, mat._42, mat._43); obb->c = (min + max) * 0.5f + worldPos; // ¹æÇâ º¤ÅÍ ±¸Çϱâ obb->u[0] = D3DXVECTOR3( mat._11, mat._12, mat._13); obb->u[1] = D3DXVECTOR3( mat._21, mat._22, mat._23); obb->u[2] = D3DXVECTOR3( mat._31, mat._32, mat._33); //¹ÝÁö¸§ ±¸Çϱâ obb->r.x = fabsf( max.x - min.x) * 0.5f; obb->r.y = fabsf( max.y - min.y) * 0.5f; obb->r.z = fabsf( max.z - min.z) * 0.5f; } OBB ¹Ú½º ·»´õ¸µ void SetObbToMatrix(OBB& obb, D3DXMATRIX& mat)
{ mat._41 = obb.c.x; mat._42 = obb.c.y; mat._43 = obb.c.z; mat._11 = obb.u[0].x; mat._12 = obb.u[0].y; mat._13 = obb.u[0].z; mat._21 = obb.u[1].x; mat._22 = obb.u[1].y; mat._23 = obb.u[1].z; mat._31 = obb.u[2].x; mat._32 = obb.u[2].y; mat._33 = obb.u[2].z; } void RenderOBB() { D3DXMATRIX matWorld; D3DXMatrixIdentity(&matWorld); SetObbToMatrix(g_obb1, matWorld); g_dxDevice->SetTransform(D3DTS_WORLD, &matWorld); g_boxMesh1->DrawSubset(0); SetObbToMatrix(g_obb2, matWorld); g_dxDevice->SetTransform(D3DTS_WORLD, &matWorld); g_boxMesh2->DrawSubset(0); } OBB¿Í OBB ¹Ú½ºÀÇ Ãæµ¹ üũÇϱâ int TestOBBOBB(OBB *a, OBB *b)
{ const float EPSILON = float(1.175494e-37); float R[3][3], AbsR[3][3]; for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { R[i][j] = D3DXVec3Dot(&a->u[i], &b->u[j]); AbsR[i][j] = fabsf(R[i][j]) + EPSILON; } } D3DXVECTOR3 t = b->c - a->c; t = D3DXVECTOR3(D3DXVec3Dot(&t, &a->u[0]), D3DXVec3Dot(&t, &a->u[1]), D3DXVec3Dot(&t, &a->u[2])); //ÃàL=A0, L=A1, L=A2ÆÇÁ¤ float ra, rb; for(int i = 0; i < 3; i++) { ra = a->r[i]; rb = b->r[0] * AbsR[i][0] + b->r[1] * AbsR[i][1] + b->r[2] * AbsR[i][2]; if(fabsf(t[i]) > ra + rb)return 0; } //ÃàL=B0, L=B1, L=B2ÆÇÁ¤ for(int i = 0; i < 3; i++) { ra = a->r[0] * AbsR[0][i] + a->r[1] * AbsR[1][i] + a->r[2] * AbsR[2][i]; rb = b->r[i]; if(fabsf(t[0] * R[0][i] + t[1] * R[1][i] + t[2] * R[2][i]) > ra + rb) return 0; } //ÃàL=A0 X B0ÆÇÁ¤ ra = a->r[1] * AbsR[2][0] + a->r[2] * AbsR[1][0]; rb = b->r[1] * AbsR[0][2] + b->r[2] * AbsR[0][1]; if(fabsf(t[2] * R[1][0] - t[1] * R[2][0]) > ra + rb) return 0; //ÃàL=A0 X B1ÆÇÁ¤ ra = a->r[1] * AbsR[2][1] + a->r[2] * AbsR[1][1]; rb = b->r[0] * AbsR[0][2] + b->r[2] * AbsR[0][0]; if(fabsf(t[2] * R[1][1] - t[1] * R[2][1]) > ra + rb) return 0; //ÃàL=A0 X B2ÆÇÁ¤ ra = a->r[1] * AbsR[2][2] + a->r[2] * AbsR[1][2]; rb = b->r[0] * AbsR[0][1] + b->r[1] * AbsR[0][0]; if(fabsf(t[2] * R[1][2] - t[1] * R[2][2]) > ra + rb) return 0; //ÃàL=A1 X B0ÆÇÁ¤ ra = a->r[0] * AbsR[2][0] + a->r[2] * AbsR[0][0]; rb = b->r[1] * AbsR[1][2] + b->r[2] * AbsR[1][1]; if(fabsf(t[0] * R[2][0] - t[2] * R[0][0]) > ra + rb) return 0; //ÃàL=A1 X B1ÆÇÁ¤ ra = a->r[0] * AbsR[2][1] + a->r[2] * AbsR[0][1]; rb = b->r[0] * AbsR[1][2] + b->r[2] * AbsR[1][0]; if(fabsf(t[0] * R[2][1] - t[2] * R[0][1]) > ra + rb) return 0; //ÃàL=A1 X B2ÆÇÁ¤ ra = a->r[0] * AbsR[2][2] + a->r[2] * AbsR[0][2]; rb = b->r[0] * AbsR[1][1] + b->r[1] * AbsR[1][0]; if(fabsf(t[0] * R[2][2] - t[2] * R[0][2]) > ra + rb) return 0; //ÃàL=A2 X B0ÆÇÁ¤ ra = a->r[0] * AbsR[1][0] + a->r[1] * AbsR[0][0]; rb = b->r[1] * AbsR[2][2] + b->r[2] * AbsR[2][1]; if(fabsf(t[1] * R[0][0] - t[0] * R[1][0]) > ra + rb) return 0; //ÃàL=A2 X B1ÆÇÁ¤ ra = a->r[0] * AbsR[1][1] + a->r[1] * AbsR[0][1]; rb = b->r[0] * AbsR[2][2] + b->r[2] * AbsR[2][0]; if(fabsf(t[1] * R[0][1] - t[0] * R[1][1]) > ra + rb) return 0; //ÃàL=A2 X B2ÆÇÁ¤ ra = a->r[0] * AbsR[1][2] + a->r[1] * AbsR[0][2]; rb = b->r[0] * AbsR[2][1] + b->r[1] * AbsR[2][0]; if(fabsf(t[1] * R[0][2] - t[0] * R[1][2]) > ra + rb) return 0; return 1; } dxfunc.cpp ObbTest.cpp obb_collision.zip github ¸µÅ©: https://github.com/hisimpson/obb_collision ÂüÁ¶) OBB ¼Ò½º °¡Á®¿È http://distancevector.web.fc2.com/collision.html D3DXCreateBox¿¡ Ä®¶ó Àû¿ë https://cpp.hotexamples.com/examples/-/-/D3DXCreateBox/cpp-d3dxcreatebox-function-examples.html |