Sunday, June 1, 2008

C++ - Direct X 9.0 - Overlap Tests (Mesh)

This is a code snippet, that I put together to handle mesh-overlapping, so if the view of a player's model is obstructed by something such as a tree, this will cause that tree to have an applied transparency. The code snippet can be used however you want, and broken up/restructured to be more organized -- however, please give me credit if you use it. Thanks.
D3DXVECTOR3 vCenter;
  
// Lock the Vertex Buffer
if(SUCCEEDED(pMesh->LockVertexBuffer(D3DLOCK_READONLY, (BYTE**)&Ptr)))
{
     // Computer Bounding Sphere Radius
     D3DXComputeBoundingSphere((void*)Ptr, pMesh->GetNumVertices(), 
          pMesh->GetNumBytesPerVertex(), &vCenter, &fObjectRadius);
     fObjectRadius = D3DXVec3Length(&vCenter) + fObjectRadius;

     // Unlock the Vertex Buffer
     pMesh->UnlockVertexBuffer();
}
This calculates the Radius, for use in the below Overlap test, your radius will never change, since this mesh isn't adjusting in size.
D3DXVECTOR3 vObjectPosVS, vPlayerPosVS;
  
D3DXVec3TransformCoord( &vObjectPosVS, &matView, &vObjectPosWS );
D3DXVec3TransformCoord( &vPlayerPosVS, &matView, &vPlayerPosWS );
At this point, we're transforming the coordinates from World-space to View-space, and then if the object obstructs the player, apply transparency.
if ( ( vObjectPosVS.z + fObjectRadius > 0 ) && ( vObjectPosVS.z - 
    fObjectRadius < vPlayerPosVS.z ) )
{
    D3DXVECTOR3 vPositionsVS [4];
    D3DXVECTOR3 vPositionsSS [4];
    D3DXVECTOR2 vObjectMaxSS;
    D3DXVECTOR2 vObjectMinSS;
    D3DXVECTOR2 vPlayerMaxSS;
    D3DXVECTOR2 vPlayerMinSS;
  
    // Calculate the area the object bounding volume takes up in view space
    vPositionsVS[0] = D3DXVECTOR3( vObjectPosVS.x + fObjectRadius, 
         vObjectPosVS.y, vObjectPosVS.z );
    vPositionsVS[1] = D3DXVECTOR3( vObjectPosVS.x - fObjectRadius, 
         vObjectPosVS.y, vObjectPosVS.z );
    vPositionsVS[2] = D3DXVECTOR3( vObjectPosVS.x, vObjectPosVS.y + 
         fObjectRadius, vObjectPosVS.z );
    vPositionsVS[3] = D3DXVECTOR3( vObjectPosVS.x, vObjectPosVS.y - 
         fObjectRadius, vObjectPosVS.z );
  
    // Calculate the area the object bounding volume takes up in screen space
    D3DXVec3TransformCoordArray( vPositionsSS, sizeof(D3DXVECTOR3), 
         vPositionsVS, sizeof(D3DXVECTOR3), &matProjection, 4 );
    vObjectMaxSS.x = vPositionsSS[0].x;
    vObjectMinSS.x = vPositionsSS[1].x;
    vObjectMaxSS.y = vPositionsSS[2].y;
    vObjectMinSS.y = vPositionsSS[3].y;
  
    // Calculate the area the player bounding volume takes up in view space
    vPositionsVS[0] = D3DXVECTOR3( vPlayerPosVS.x + fPlayerRadius, 
         vPlayerPosVS.y, vPlayerPosVS.z );
    vPositionsVS[1] = D3DXVECTOR3( vPlayerPosVS.x - fPlayerRadius, 
         vPlayerPosVS.y, vPlayerPosVS.z );
    vPositionsVS[2] = D3DXVECTOR3( vPlayerPosVS.x, vPlayerPosVS.y + 
         fPlayerRadius, vPlayerPosVS.z );
    vPositionsVS[3] = D3DXVECTOR3( vPlayerPosVS.x, vPlayerPosVS.y - 
         fPlayerRadius, vPlayerPosVS.z );
  
    // Calculate the area the player bounding volume takes up in screen space
    D3DXVec3TransformCoordArray( vPositionsSS, sizeof(D3DXVECTOR3), 
         vPositionsVS, sizeof(D3DXVECTOR3), &matProjection, 4 );
    vPlayerMaxSS.x = vPositionsSS[0].x;
    vPlayerMinSS.x = vPositionsSS[1].x;
    vPlayerMaxSS.y = vPositionsSS[2].y;
    vPlayerMinSS.y = vPositionsSS[3].y;
  
    // Check for overlap
    if ( vObjectMaxSS.x < vPlayerMinSS.x )
        return;
    if ( vObjectMaxSS.y < vPlayerMinSS.y )
        return;
    if ( vObjectMinSS.x > vPlayerMaxSS.x )
        return;
    if ( vObjectMinSS.y < vPlayerMaxSS.y )
        return;
  
    // If we got here, the object is obstructing and should be made transparent
}