OBB and OBB collision

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