Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


#Actualbelfegor

Posted 30 March 2013 - 02:38 AM

I am trying to draw 2D axis aligned rect around my 3D teapot object.

I cant get correct results and do not know what i am doing wrong.

 

1. Load teapot and calculate bbox

 

struct BBox

{

    D3DXVECTOR3 minPt;

    D3DXVECTOR3 maxPt;

};



BBox bBox;
...
hr = D3DXLoadMeshFromX("Teapot.x", D3DXMESH_MANAGED, d3d9device, 0, 0, 0, 0, &teapotMesh);

    if(FAILED(hr))

    {

        MessageBox(0, TEXT("Failed to load teapot mesh!"), 0, 0);

        return false;

    }

    

    BYTE* pData = 0;

    teapotMesh->LockVertexBuffer(0, (LPVOID*)&pData);

    hr = D3DXComputeBoundingBox((D3DXVECTOR3*)pData, teapotMesh->GetNumVertices(), teapotMesh->GetNumBytesPerVertex(), &bBox.minPt, &bBox.maxPt);

    if(FAILED(hr))

    {

        MessageBox(0, TEXT("Failed to compute bbox!"), 0, 0);

        return false;

    }

    teapotMesh->UnlockVertexBuffer();

 

2. get 8 points of a bbox function

 

std::array<D3DXVECTOR3, 8> GetBBoxCorners(const BBox& bb)

{

    std::array<D3DXVECTOR3, 8> out;

    D3DXVECTOR3 c    = (bb.minPt + bb.maxPt) * 0.5f;

    D3DXVECTOR3 e    = (bb.maxPt - bb.minPt) * 0.5f;



    out[0] = D3DXVECTOR3((c.x - e.x), (c.y - e.y), (c.z - e.z));

    out[1] = D3DXVECTOR3((c.x + e.x), (c.y - e.y), (c.z - e.z));

    out[2] = D3DXVECTOR3((c.x - e.x), (c.y + e.y), (c.z - e.z));

    out[3] = D3DXVECTOR3((c.x + e.x), (c.y + e.y), (c.z - e.z));

    out[4] = D3DXVECTOR3((c.x - e.x), (c.y - e.y), (c.z + e.z));

    out[5] = D3DXVECTOR3((c.x + e.x), (c.y - e.y), (c.z + e.z));

    out[6] = D3DXVECTOR3((c.x - e.x), (c.y + e.y), (c.z + e.z));

    out[7] = D3DXVECTOR3((c.x + e.x), (c.y + e.y), (c.z + e.z));



    return out;

}

 

3. Draw teapot

 

effect->SetTechnique("tTech");

    effect->Begin(0, 0);

    effect->BeginPass(0);
 
D3DXVECTOR3 pos(0.0f, 1.0f, 4.0f);
D3DXMATRIX teapotMat;

    D3DXMatrixTranslation(&teapotMat, pos.x, pos.y, pos.z);



    D3DXMATRIX worldViewProj = teapotMat * cam->getView() * cam->getProjection();



    effect->SetMatrix("WorldViewProjection", &worldViewProj);

    effect->SetTexture("DiffuseTex", teapotTexture);

    effect->CommitChanges();

   teapotMesh->DrawSubset(0);
 
effect->EndPass();

    effect->End();

 

4. Transform 8 bbox points and find 2d min/max rect

 

bBox.maxPt += pos;

    bBox.minPt += pos;

    auto bboxPts = GetBBoxCorners(bBox);

    auto ptCnt   = bboxPts.size();

    decltype(bboxPts) outPts;

    D3DVIEWPORT9 vp;

    d3d9device->GetViewport(&vp);

    for(std::size_t i = 0; i < ptCnt; ++i)

    {

        D3DXVec3Project(&outPts[i], &bboxPts[i], &vp, &cam->getProjection(), &cam->getView(), &teapotMat);

    }



    struct BBox2D

    {

        D3DXVECTOR2 minPt;

        D3DXVECTOR2 maxPt;

    };



    BBox2D bb2D;

    bb2D.minPt = D3DXVECTOR2(std::numeric_limits<float>::max(), std::numeric_limits<float>::max());

    bb2D.maxPt = D3DXVECTOR2(std::numeric_limits<float>::min(), std::numeric_limits<float>::min());

    for(std::size_t i = 0; i < ptCnt; ++i)

    {

        if(bb2D.minPt.x > outPts[i].x)

        {

            bb2D.minPt.x = outPts[i].x;

        }



        if(bb2D.minPt.y > outPts[i].y)

        {

            bb2D.minPt.y = outPts[i].y;

        }



        if(bb2D.maxPt.x < outPts[i].x)

        {

            bb2D.maxPt.x = outPts[i].x;

        }



        if(bb2D.maxPt.y < outPts[i].y)

        {

            bb2D.maxPt.y = outPts[i].y;

        }

    }

 

 

struct DEBUG_VERTEX

    {

        D3DXVECTOR4 p;

        DWORD color;

    };



    std::array<DEBUG_VERTEX, 8> linePts;

    for(std::size_t i = 0; i < ptCnt; ++i)

    {

        linePts[i].color = D3DCOLOR_XRGB(255, 0, 0);

    }

    float z = 0.5f;

    float w = 1.0f;

    linePts[0].p = D3DXVECTOR4(bb2D.minPt.x, bb2D.minPt.y, z, w);

    linePts[1].p = D3DXVECTOR4(bb2D.maxPt.x, bb2D.minPt.y, z, w);

    linePts[2].p = D3DXVECTOR4(bb2D.maxPt.x, bb2D.minPt.y, z, w);

    linePts[3].p = D3DXVECTOR4(bb2D.maxPt.x, bb2D.maxPt.y, z, w);

    linePts[4].p = D3DXVECTOR4(bb2D.maxPt.x, bb2D.maxPt.y, z, w);

    linePts[5].p = D3DXVECTOR4(bb2D.minPt.x, bb2D.maxPt.y, z, w);

    linePts[6].p = D3DXVECTOR4(bb2D.minPt.x, bb2D.maxPt.y, z, w);

    linePts[7].p = D3DXVECTOR4(bb2D.minPt.x, bb2D.minPt.y, z, w);



    d3d9device->SetTransform(D3DTS_PROJECTION, &cam->getProjection());

    d3d9device->SetTransform(D3DTS_VIEW, &cam->getView());

    d3d9device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);

    d3d9device->DrawPrimitiveUP(D3DPT_LINELIST, linePts.size() / 2, &linePts[0], sizeof(DEBUG_VERTEX));

 

Can you spot what i am doing wrong?

If you need more info please tell.

 

Thank you for your time.


#1belfegor

Posted 30 March 2013 - 02:33 AM

I am trying to draw 2D axis aligned rect around my 3D teapot object.

I cant get correct results and do not know what i am doing wrong.

 

1. Load teapot and calculate bbox

struct BBox

{

    D3DXVECTOR3 minPt;

    D3DXVECTOR3 maxPt;

};



BBox bBox;
...
hr = D3DXLoadMeshFromX("Teapot.x", D3DXMESH_MANAGED, d3d9device, 0, 0, 0, 0, &teapotMesh);

    if(FAILED(hr))

    {

        MessageBox(0, TEXT("Failed to load teapot mesh!"), 0, 0);

        return false;

    }

    

    BYTE* pData = 0;

    teapotMesh->LockVertexBuffer(0, (LPVOID*)&pData);

    hr = D3DXComputeBoundingBox((D3DXVECTOR3*)pData, teapotMesh->GetNumVertices(), teapotMesh->GetNumBytesPerVertex(), &bBox.minPt, &bBox.maxPt);

    if(FAILED(hr))

    {

        MessageBox(0, TEXT("Failed to compute bbox!"), 0, 0);

        return false;

    }

    teapotMesh->UnlockVertexBuffer();

 

2. get 8 points of a bbox function

std::array<D3DXVECTOR3, 8> GetBBoxCorners(const BBox& bb)

{

    std::array<D3DXVECTOR3, 8> out;

    D3DXVECTOR3 c    = (bb.minPt + bb.maxPt) * 0.5f;

    D3DXVECTOR3 e    = (bb.maxPt - bb.minPt) * 0.5f;



    out[0] = D3DXVECTOR3((c.x - e.x), (c.y - e.y), (c.z - e.z));

    out[1] = D3DXVECTOR3((c.x + e.x), (c.y - e.y), (c.z - e.z));

    out[2] = D3DXVECTOR3((c.x - e.x), (c.y + e.y), (c.z - e.z));

    out[3] = D3DXVECTOR3((c.x + e.x), (c.y + e.y), (c.z - e.z));

    out[4] = D3DXVECTOR3((c.x - e.x), (c.y - e.y), (c.z + e.z));

    out[5] = D3DXVECTOR3((c.x + e.x), (c.y - e.y), (c.z + e.z));

    out[6] = D3DXVECTOR3((c.x - e.x), (c.y + e.y), (c.z + e.z));

    out[7] = D3DXVECTOR3((c.x + e.x), (c.y + e.y), (c.z + e.z));



    return out;

}

 

3. Draw teapot

effect->SetTechnique("tTech");

    effect->Begin(0, 0);

    effect->BeginPass(0);
 
D3DXVECTOR3 pos(0.0f, 1.0f, 4.0f);
D3DXMATRIX teapotMat;

    D3DXMatrixTranslation(&teapotMat, pos.x, pos.y, pos.z);



    D3DXMATRIX worldViewProj = teapotMat * cam->getView() * cam->getProjection();



    effect->SetMatrix("WorldViewProjection", &worldViewProj);

    effect->SetTexture("DiffuseTex", teapotTexture);

    effect->CommitChanges();

   teapotMesh->DrawSubset(0);
 
effect->EndPass();

    effect->End();

 

4. Transform 8 bbox points and find 2d min/max rect

bBox.maxEdge += pos;

    bBox.minEdge += pos;

    auto bboxPts = GetBBoxCorners(bBox);

    auto ptCnt   = bboxPts.size();

    decltype(bboxPts) outPts;

    D3DVIEWPORT9 vp;

    d3d9device->GetViewport(&vp);

    for(std::size_t i = 0; i < ptCnt; ++i)

    {

        D3DXVec3Project(&outPts[i], &bboxPts[i], &vp, &cam->getProjection(), &cam->getView(), &teapotMat);

    }



    struct BBox2D

    {

        D3DXVECTOR2 minEdge;

        D3DXVECTOR2 maxEdge;

    };



    BBox2D bb2D;

    bb2D.minEdge = D3DXVECTOR2(std::numeric_limits<float>::max(), std::numeric_limits<float>::max());

    bb2D.maxEdge = D3DXVECTOR2(std::numeric_limits<float>::min(), std::numeric_limits<float>::min());

    for(std::size_t i = 0; i < ptCnt; ++i)

    {

        if(bb2D.minEdge.x > outPts[i].x)

        {

            bb2D.minEdge.x = outPts[i].x;

        }



        if(bb2D.minEdge.y > outPts[i].y)

        {

            bb2D.minEdge.y = outPts[i].y;

        }



        if(bb2D.maxEdge.x < outPts[i].x)

        {

            bb2D.maxEdge.x = outPts[i].x;

        }



        if(bb2D.maxEdge.y < outPts[i].y)

        {

            bb2D.maxEdge.y = outPts[i].y;

        }

    }

 

struct DEBUG_VERTEX

    {

        D3DXVECTOR4 p;

        DWORD color;

    };



    std::array<DEBUG_VERTEX, 8> linePts;

    for(std::size_t i = 0; i < ptCnt; ++i)

    {

        linePts[i].color = D3DCOLOR_XRGB(255, 0, 0);

    }

    float z = 0.5f;

    float w = 1.0f;

    linePts[0].p = D3DXVECTOR4(bb2D.minEdge.x, bb2D.minEdge.y, z, w);

    linePts[1].p = D3DXVECTOR4(bb2D.maxEdge.x, bb2D.minEdge.y, z, w);

    linePts[2].p = D3DXVECTOR4(bb2D.maxEdge.x, bb2D.minEdge.y, z, w);

    linePts[3].p = D3DXVECTOR4(bb2D.maxEdge.x, bb2D.maxEdge.y, z, w);

    linePts[4].p = D3DXVECTOR4(bb2D.maxEdge.x, bb2D.maxEdge.y, z, w);

    linePts[5].p = D3DXVECTOR4(bb2D.minEdge.x, bb2D.maxEdge.y, z, w);

    linePts[6].p = D3DXVECTOR4(bb2D.minEdge.x, bb2D.maxEdge.y, z, w);

    linePts[7].p = D3DXVECTOR4(bb2D.minEdge.x, bb2D.minEdge.y, z, w);



    d3d9device->SetTransform(D3DTS_PROJECTION, &cam->getProjection());

    d3d9device->SetTransform(D3DTS_VIEW, &cam->getView());

    d3d9device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);

    d3d9device->DrawPrimitiveUP(D3DPT_LINELIST, linePts.size() / 2, &linePts[0], sizeof(DEBUG_VERTEX));

 

Can you spot what i am doing wrong?

If you need more info please tell.

 

Thank you for your time.


PARTNERS