Original Post
Hello, I've been trying to create a collision sliding effect for a loooong time now, and it is always bugged. I looked everywhere and can't figure it out. I have ray->polygon collision and it works fine, but the characters just stops when he hits the wall, instead of sliding along it. I tried fixing this by extracting and calculating mesh face normals, and using them to push the user back. This works (in most cases) fine if I slide along a straight wall, but if I hit a spehere or cylinder it doesn't work so well, I assume it's a problem with either my way of caluculating the face normals, or the way I use them to push the user back. When I hit spehere or cylinder or any other non-straight surface it will either not slide at all, or it will push me back too much creating this ugly bouncy effect, and also I can always come close enough to cylinders to see through them(which I can't with walls). Here's my collision code: So to summarize, I need someone to show me how to create a working sliding effect. Please help, I'm desperate! Thank you!
if( checkCollision( mesh, &cCamera, xMove, yMove, zMove, &length, &FaceIndex, &u, &v ) )
{
//xMove, zMove ARE SIMPLY HOW MUCH TO MOVE EACH FRAME, DEPENDING ON BUTTON PRESSED
// THE SIMPLE COLLISION, NO SLIDING, BUT WORKS
float diff;
diff = length - 5.00;
D3DXVECTOR2 vecDir;
D3DXVec2Normalize(&vecDir, &D3DXVECTOR2(xMove, zMove));
vecDir *= diff;
xMove = vecDir.x;
zMove = vecDir.y;
// END SIMPLE
// MY ATTEMPT ON SLIDING
vertex *vert;
WORD* indices = 0;
D3DXVECTOR3 indNormal, vec1, vec2, vec3, vNormal;
// CODE TO CALCULATE THE FACE NORMALS
// clonedMesh is an empty mesh containing ONLY vertex normals
// GET THE LOCATION OF NORMALS FROM INDEX BUFFER, USING faceIndex RETURNED BY THE D3DXIntersect
clonedMesh->LockIndexBuffer(0, ( LPVOID* )&indices);
indNormal.x = indices[FaceIndex*3];
indNormal.y = indices[FaceIndex*3+1];
indNormal.z = indices[FaceIndex*3+2];
clonedMesh->UnlockIndexBuffer();
// get the normals
clonedMesh->LockVertexBuffer( 0, ( LPVOID* )| );
vec1 = D3DXVECTOR3( vert[( int )indNormal.x]._nx,
vert[( int )indNormal.x]._ny,
vert[( int )indNormal.x]._nz );
vec2 = D3DXVECTOR3( vert[( int )indNormal.y]._nx,
vert[( int )indNormal.y]._ny,
vert[( int )indNormal.y]._nz );
vec3 = D3DXVECTOR3( vert[( int )indNormal.z]._nx,
vert[( int )indNormal.z]._ny,
vert[( int )indNormal.z]._nz );
clonedMesh->UnlockVertexBuffer( );
vNormal = vec1 + u*(vec3-vec2) + v*(vec3-vec1); // calculate the final face normal using 3 vertex normals
//and barycentric coordinates returned by D3DXIntersect
D3DXVec3Normalize(&vNormal, &vNormal);
float xMoveTemp = 0.0f;
float yMoveTemp = 0.0f;
float zMoveTemp = 0.0f;
// ATTEMPT TO SLIDE....
xMoveTemp += vNormal.x * diff;
xMove = xMove + xMoveTemp;
zMoveTemp += vNormal.z * diff;
zMove = zMove + zMoveTemp;
}
// COLLISION FUNCTION, I DOUBT THE PROBLEM IS HERE
BOOL checkCollision(ID3DXMesh *mesh, cCamera* cCamera, float xMove, float yMove,
float zMove, float *length, DWORD *FaceIndex, float *u, float *v)
{
float sX, sY, sZ;
float eX, eY, eZ;
float fSize = 0.0f;
float diffX, diffY, diffZ;
BOOL hit;
float dist;
DWORD faceHit;
sX = cCamera->getXLoc();
sY = cCamera->getYLoc();
sZ = cCamera->getZLoc();
eX = cCamera->getXLoc() + xMove;
eY = cCamera->getYLoc() + yMove;
eZ = cCamera->getZLoc() + zMove;
eX = ( eX != 0 ) ? eX - eX/fabs(eX) * 4.0f : 0; // ADD 4.0f TO VEL. VECTOR SO WE DON'T COME TOO CLOSE TO
//THE OTHER MESH, COZ THEN WE CAN SEE THROUGH IT
//eY = ( eY != 0 ) ? eY - eY/fabs(eY) * 4.5f : 0;
eZ = ( eZ != 0 ) ? eZ - eZ/fabs(eZ) * 4.0f : 0;
diffX = eX - sX;
diffY = eY - sY;
diffZ = eZ - sZ;
D3DXVECTOR3 vDir;
D3DXVec3Normalize(&vDir, &D3DXVECTOR3(diffX, diffY, diffZ));
D3DXIntersect(mesh, &D3DXVECTOR3(sX, sY, sZ), &vDir, &hit,
FaceIndex, u, v, &dist, 0, 0);
if(hit == TRUE)
{
fSize = (float)sqrt(diffX*diffX+diffY*diffY+diffZ*diffZ);
if(dist > fSize)
{
hit = FALSE;
}
else
{
*length = dist;
}
}
return hit;
}