Jump to content

  • Log In with Google      Sign In   
  • Create Account


2D axis aligned rect


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
2 replies to this topic

#1 belfegor   Crossbones+   -  Reputation: 2384

Like
0Likes
Like

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.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, 30 March 2013 - 02:38 AM.


Sponsor:

#2 belfegor   Crossbones+   -  Reputation: 2384

Like
0Likes
Like

Posted 30 March 2013 - 06:29 AM

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?



#3 belfegor   Crossbones+   -  Reputation: 2384

Like
0Likes
Like

Posted 30 March 2013 - 08:59 AM

Solved. Pass identity matrix for D3DXVec3Project last parameter.






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS