• Advertisement
Sign in to follow this  

2D axis aligned rect

This topic is 1756 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Edited by belfegor

Share this post


Link to post
Share on other sites
Advertisement

I found my mistake

 

bBox.maxPt += pos;
  bBox.minPt += pos;

 

accumulating every frame instead just when teapot position changes.

 

Now i have strange offset, as you can see on picture

 

offseterror.jpg

 

Any clue how to resolve this?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement