Sign in to follow this  

Collision Detection with Skinned Mesh

This topic is 2044 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am using a method to detect collision between two boundary boxes, when I load two meshes (static box) by using D3DXLoadMeshFromX() it detect EXACTLY when a collision occur, however when I load the same mesh by using D3DXLoadMeshHierarchyFromX() it detect collision before the collision occur (by a small amount of space).

How can I get D3DXLoadMeshHierarchyFromX() to work as D3DXLoadMeshFromX() when detecting collision on boundary boxes?

The photo appear here show what happens in SKINNED MESH ONLY, the problem doesn't occur with static mesh which can be loaded by using D3DXLoadMeshFromX()
[img]http://img694.imageshack.us/img694/3111/pngcollision.png[/img] Edited by Medo3337

Share this post


Link to post
Share on other sites
Can you give us a bit more information on the method you are using to detect collisions, the images are not that clear, but showing us a bit of code will probably get you a faster answer.

Aimee.

Share this post


Link to post
Share on other sites
Here is the method I am using to detect collision between two boundary boxes:

bool DetectCollisionOnBoundaryBox(LPD3DXMESH mesh1, LPD3DXMESH mesh2, D3DXMATRIX mesh1_WorldMatrix, D3DXMATRIX mesh2_WorldMatrix)
{
HRESULT hr;
// Mesh 1
BYTE* pVertices=NULL;

hr = mesh1->LockVertexBuffer(D3DLOCK_READONLY, (LPVOID*)&pVertices);
if (FAILED(hr))
return false;
D3DXVECTOR3 min, max;
D3DXComputeBoundingBox((D3DXVECTOR3*)pVertices, mesh1->GetNumVertices(), D3DXGetFVFVertexSize(mesh1->GetFVF()), &min, &max);
mesh1->UnlockVertexBuffer();

// Mesh 2
BYTE* pVertices2=NULL;

hr = mesh2->LockVertexBuffer(D3DLOCK_READONLY, (LPVOID*)&pVertices2);
if (FAILED(hr))
return FALSE;
D3DXVECTOR3 otherMin, otherMax;
D3DXComputeBoundingBox((D3DXVECTOR3*)pVertices2, mesh2->GetNumVertices(), D3DXGetFVFVertexSize(mesh2->GetFVF()), &otherMin, &otherMax);
mesh2->UnlockVertexBuffer();


// We have min and max values, use these to get the 8 corners of the boundingbox
D3DXVECTOR3 mesh1_cornersInModelSpace[8];
mesh1_cornersInModelSpace[0] = D3DXVECTOR3( min.x, min.y, min.z ); // xyz
mesh1_cornersInModelSpace[1] = D3DXVECTOR3( max.x, max.y, max.z ); // Xyz
mesh1_cornersInModelSpace[2] = D3DXVECTOR3( min.x, min.y, min.z ); // xYz
mesh1_cornersInModelSpace[3] = D3DXVECTOR3( max.x, max.y, max.z ); // XYz
mesh1_cornersInModelSpace[4] = D3DXVECTOR3( min.x, min.y, min.z ); // xyZ
mesh1_cornersInModelSpace[5] = D3DXVECTOR3( max.x, max.y, max.z ); // XyZ
mesh1_cornersInModelSpace[6] = D3DXVECTOR3( min.x, min.y, min.z ); // xYZ
mesh1_cornersInModelSpace[7] = D3DXVECTOR3( max.x, max.y, max.z ); // XYZ


// We have min and max values, use these to get the 8 corners of the boundingbox
D3DXVECTOR3 mesh2_cornersInModelSpace[8];
mesh2_cornersInModelSpace[0] = D3DXVECTOR3( otherMin.x, otherMin.y, otherMin.z ); // xyz
mesh2_cornersInModelSpace[1] = D3DXVECTOR3( otherMax.x, otherMax.y, otherMax.z ); // Xyz
mesh2_cornersInModelSpace[2] = D3DXVECTOR3( otherMin.x, otherMin.y, otherMin.z ); // xYz
mesh2_cornersInModelSpace[3] = D3DXVECTOR3( otherMax.x, otherMax.y, otherMax.z ); // XYz
mesh2_cornersInModelSpace[4] = D3DXVECTOR3( otherMin.x, otherMin.y, otherMin.z ); // xyZ
mesh2_cornersInModelSpace[5] = D3DXVECTOR3( otherMax.x, otherMax.y, otherMax.z ); // XyZ
mesh2_cornersInModelSpace[6] = D3DXVECTOR3( otherMin.x, otherMin.y, otherMin.z ); // xYZ
mesh2_cornersInModelSpace[7] = D3DXVECTOR3( otherMax.x, otherMax.y, otherMax.z ); // XYZ

// Now we transform each corner by the world matrix
D3DXVECTOR3 mesh1_cornersInWorldSpace[8];
for( int i = 0; i < 8; i++ )
D3DXVec3TransformCoord( &mesh1_cornersInWorldSpace[i], &mesh1_cornersInModelSpace[i], &mesh1_WorldMatrix );

D3DXVECTOR3 mesh2_cornersInWorldSpace[8];
for( int i = 0; i < 8; i++ )
D3DXVec3TransformCoord( &mesh2_cornersInWorldSpace[i], &mesh2_cornersInModelSpace[i], &mesh2_WorldMatrix );


D3DXVECTOR3 minBoundsWorldSpace=mesh1_cornersInWorldSpace[0];
D3DXVECTOR3 maxBoundsWorldSpace=mesh1_cornersInWorldSpace[0];
for (int i=1;i<8;i++)
{
minBoundsWorldSpace.x=min(minBoundsWorldSpace.x,mesh1_cornersInWorldSpace[i].x);
minBoundsWorldSpace.y=min(minBoundsWorldSpace.y,mesh1_cornersInWorldSpace[i].y);
minBoundsWorldSpace.z=min(minBoundsWorldSpace.z,mesh1_cornersInWorldSpace[i].z);

maxBoundsWorldSpace.x=max(maxBoundsWorldSpace.x,mesh1_cornersInWorldSpace[i].x);
maxBoundsWorldSpace.y=max(maxBoundsWorldSpace.y,mesh1_cornersInWorldSpace[i].y);
maxBoundsWorldSpace.z=max(maxBoundsWorldSpace.z,mesh1_cornersInWorldSpace[i].z);
}

D3DXVECTOR3 minBoundsWorldSpace2=mesh2_cornersInWorldSpace[0];
D3DXVECTOR3 maxBoundsWorldSpace2=mesh2_cornersInWorldSpace[0];
for (int i=1;i<8;i++)
{
minBoundsWorldSpace2.x=min(minBoundsWorldSpace2.x,mesh2_cornersInWorldSpace[i].x);
minBoundsWorldSpace2.y=min(minBoundsWorldSpace2.y,mesh2_cornersInWorldSpace[i].y);
minBoundsWorldSpace2.z=min(minBoundsWorldSpace2.z,mesh2_cornersInWorldSpace[i].z);

maxBoundsWorldSpace2.x=max(maxBoundsWorldSpace2.x,mesh2_cornersInWorldSpace[i].x);
maxBoundsWorldSpace2.y=max(maxBoundsWorldSpace2.y,mesh2_cornersInWorldSpace[i].y);
maxBoundsWorldSpace2.z=max(maxBoundsWorldSpace2.z,mesh2_cornersInWorldSpace[i].z);
}


if ((minBoundsWorldSpace.x < maxBoundsWorldSpace2.x) && (maxBoundsWorldSpace.x > minBoundsWorldSpace2.x) &&
(minBoundsWorldSpace.y < maxBoundsWorldSpace2.y) && (maxBoundsWorldSpace.y > minBoundsWorldSpace2.y) &&
(minBoundsWorldSpace.z < maxBoundsWorldSpace2.z) && (maxBoundsWorldSpace.z > minBoundsWorldSpace2.z))
return true;
else
return false;
}

For the skinned mesh I use the following code to get LPD3DXMESH:

D3DXMESHCONTAINER_EXTENDED *meshContainer = (D3DXMESHCONTAINER_EXTENDED*)m_frameRoot->pMeshContainer;
if (meshContainer)
return (meshContainer->pSkinInfo) ? meshContainer->exSkinMesh: meshContainer->MeshData.pMesh;
return false;

Share this post


Link to post
Share on other sites
I think what's going on here is that you're calculating the bounding box for the model in it's default pose (i.e. ignoring the bones).

Some options to fix that are:

1. Don't use D3DXComputeBoundingBox(). Write your own function that does software skinning instead of just looking at vertex positions.
2. If the model uses lots of bones (like say a character) then compute the bounding box of the bones, instead of the vertices after bone transformation. There will be far fewer bones than vertices so this gains speed at the cost of some accuracy.
3. Use a pre calculated bounding box that is big enough to enclose all animations.
4. Pre calculate the bounding box for each frame of animation.

Also note that for performance purposes I'd highly recommend only calling D3DXComputeBoundingBox() once per model at load time. You won't get a different answer calling it more than once and it can be expensive, especially on high poly models.

Share this post


Link to post
Share on other sites
@Adam_42: As you can see in the picture I posted initially, the skinned model is ONLY a box but the only difference is its loaded using D3DXLoadMeshHierarchyFromX() instead of D3DXLoadMeshFromX().

There are no bones involved here.

Share this post


Link to post
Share on other sites
As far as I can tell from the documentation for those two functions the difference is that one loads animations and the other doesn't.

If there's animations implemented without using bones then options 3 and 4 I gave before are still valid.

Share this post


Link to post
Share on other sites
@Anddos: I tried on both scaled and unscaled, even I am testing on skinned mesh that's ONLY a box and I am using this skinned mesh box as boundary box to check for collision, the collision detection is still not accurate. Edited by Medo3337

Share this post


Link to post
Share on other sites

This topic is 2044 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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