Sign in to follow this  
belfegor

2D axis aligned rect

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

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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this