Hi,
I have a strange problem with calculating my AABB extents, min and max.
For testing I places 2 small cubes in my scene, which constantly take over the AABB's min and max vertices as a world position.
This perfectly illustrates the sympton.
Only with 90, 180, 270 or 360 degrees rotation the extents match the real min and max points of the rotating object.
Here's the video:
Below are the related code parts.
This is what I do:
- calculate the AABB initally with untransformed, not rotated verticies
- the 8 corners are stored in a 'base' vertex array
- every frame where the object is moved or rotated, I transform the 8 base vertices with the new matrix
- then I find the min/ max extents to use for AABB culling
Can someone help me out?
// initial creation of the AABB
void CreateAABB(TVERTEX *pVtxArray, DWORD pStart, DWORD pNr, BOUNDINGBOX *pBox)
{
// MIN and MAX vertices
pBox->min.x = pVtxArray[pStart].position.x;
pBox->min.y = pVtxArray[pStart].position.y;
pBox->min.z = pVtxArray[pStart].position.z;
pBox->max.x = pVtxArray[pStart].position.x;
pBox->max.y = pVtxArray[pStart].position.y;
pBox->max.z = pVtxArray[pStart].position.z;
for(DWORD vc=pStart;vc<pStart+pNr;++vc)
{
if(pVtxArray[vc].position.x < pBox->min.x) pBox->min.x = pVtxArray[vc].position.x;
if(pVtxArray[vc].position.x > pBox->max.x) pBox->max.x = pVtxArray[vc].position.x;
if(pVtxArray[vc].position.y < pBox->min.y) pBox->min.y = pVtxArray[vc].position.y;
if(pVtxArray[vc].position.y > pBox->max.y) pBox->max.y = pVtxArray[vc].position.y;
if(pVtxArray[vc].position.z < pBox->min.z) pBox->min.z = pVtxArray[vc].position.z;
if(pVtxArray[vc].position.z > pBox->max.z) pBox->max.z = pVtxArray[vc].position.z;
}
// FULL 8 vertices of the AABB
pBox->boxArrayBase[0].x = pBox->min.x;
pBox->boxArrayBase[0].y = pBox->min.y;
pBox->boxArrayBase[0].z = pBox->min.z;
pBox->boxArrayBase[1].x = pBox->max.x;
pBox->boxArrayBase[1].y = pBox->max.y;
pBox->boxArrayBase[1].z = pBox->max.z;
pBox->boxArrayBase[2].x = pBox->max.x;
pBox->boxArrayBase[2].y = pBox->max.y;
pBox->boxArrayBase[2].z = pBox->min.z;
pBox->boxArrayBase[3].x = pBox->min.x;
pBox->boxArrayBase[3].y = pBox->max.y;
pBox->boxArrayBase[3].z = pBox->min.z;
pBox->boxArrayBase[4].x = pBox->min.x;
pBox->boxArrayBase[4].y = pBox->min.y;
pBox->boxArrayBase[4].z = pBox->max.z;
pBox->boxArrayBase[5].x = pBox->max.x;
pBox->boxArrayBase[5].y = pBox->min.y;
pBox->boxArrayBase[5].z = pBox->max.z;
pBox->boxArrayBase[6].x = pBox->max.x;
pBox->boxArrayBase[6].y = pBox->min.y;
pBox->boxArrayBase[6].z = pBox->min.z;
pBox->boxArrayBase[7].x = pBox->min.x;
pBox->boxArrayBase[7].y = pBox->max.y;
pBox->boxArrayBase[7].z = pBox->max.z;
for(int i=0;i<8;++i) pBox->boxArray = pBox->boxArrayBase;
pBox->created = true;
}
// updating the AABB
bool UpdateAABB(BOUNDINGBOX *pBox)
{
if(!pBox->created) return false;
// 8 AABB corners need to be transformed by the latest world matrix
// now find the 2 extents
pBox->min.x = pBox->boxArray[0].x;
pBox->min.y = pBox->boxArray[0].y;
pBox->min.z = pBox->boxArray[0].z;
pBox->max.x = pBox->boxArray[0].x;
pBox->max.y = pBox->boxArray[0].y;
pBox->max.z = pBox->boxArray[0].z;
for(int vc=0;vc<8;++vc)
{
if(pBox->boxArray[vc].x < pBox->min.x) pBox->min.x = pBox->boxArray[vc].x;
if(pBox->boxArray[vc].x > pBox->max.x) pBox->max.x = pBox->boxArray[vc].x;
if(pBox->boxArray[vc].y < pBox->min.y) pBox->min.y = pBox->boxArray[vc].y;
if(pBox->boxArray[vc].y > pBox->max.y) pBox->max.y = pBox->boxArray[vc].y;
if(pBox->boxArray[vc].z < pBox->min.z) pBox->min.z = pBox->boxArray[vc].z;
if(pBox->boxArray[vc].z > pBox->max.z) pBox->max.z = pBox->boxArray[vc].z;
}
return true;
}
// update the world matrix
bool CD3dmeshInst::UpdateWorldMatrix()
{
if(!mDynamic) return false;
if(!mIsMoved && !mIsRotated && !mIsScaled) return false;
if(mIsMoved)
{
D3DXMatrixIdentity(&mMatTranslate);
D3DXMatrixTranslation(&mMatTranslate, mWorldPos.x, mWorldPos.y, mWorldPos.z);
}
if(mIsRotated)
{
D3DXMatrixIdentity(&mMatRotateX);
D3DXMatrixRotationX(&mMatRotateX, D3DXToRadian(mRot.x));
D3DXMatrixIdentity(&mMatRotateY);
D3DXMatrixRotationY(&mMatRotateY, D3DXToRadian(mRot.y));
D3DXMatrixIdentity(&mMatRotateZ);
D3DXMatrixRotationZ(&mMatRotateZ, D3DXToRadian(mRot.z));
}
if(mScale)
{
D3DXMatrixIdentity(&mMatScale);
D3DXMatrixScaling(&mMatScale, mScale, mScale, mScale);
}
mMatWorld = (D3DXMATRIXA16)(mMatScale*mMatRotateX*mMatRotateY*mMatRotateZ*mMatTranslate);
D3DXMatrixInverse(&mMatWorldInv, NULL, &mMatWorld);
D3DXMatrixTranspose(&mMatWorldInvTransp, &mMatWorldInv);
return true;
}
// update the bounding volume based on new world matrix
bool CD3dmeshInst::UpdateBVWorldSpace()
{
// WORLD MATRIX should be already updated
if(!mDynamic) return false;
// FULL mesh
if(mIsMoved || mIsRotated || mIsScaled) // TO BE SPECIFIED LATER
{
mBoundingRadius = mBoundingRadiusBase * mScale;
for(int i=0;i<8;++i) D3DXVec3TransformCoord(&mBoundingBox.boxArray, &mBoundingBox.boxArrayBase, &mMatWorld);
if(!UpdateAABB(&mBoundingBox)) return false;
}
return true;
}
Rotation, translation etc. of the mesh all work fine, I use the same updated mMatWorld matrix for rendering the mesh through my shaders without problems. Maybe something wrong with updating/ transforming the boundingbox corners/ extents? radians and degrees?
Help );