2D axis aligned rect

Started by
1 comment, last by belfegor 11 years ago

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, &bboxPts, &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.x)

        {

            bb2D.minPt.x = outPts.x;

        }



        if(bb2D.minPt.y > outPts.y)

        {

            bb2D.minPt.y = outPts.y;

        }



        if(bb2D.maxPt.x < outPts.x)

        {

            bb2D.maxPt.x = outPts.x;

        }



        if(bb2D.maxPt.y < outPts.y)

        {

            bb2D.maxPt.y = outPts.y;

        }

    }


struct DEBUG_VERTEX

    {

        D3DXVECTOR4 p;

        DWORD color;

    };



    std::array<DEBUG_VERTEX, 8> linePts;

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

    {

        linePts.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.

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?

Solved. Pass identity matrix for D3DXVec3Project last parameter.

This topic is closed to new replies.

Advertisement