-
Math Question
First, I want to say that math is not exactly my strong point. In fact, I am terrible at anything above basic algebra.
I am trying to create a collision detection routine that will compute the angle of deflection. i.e. a ball hitting a wall. I can do this simply by reversing the sign of the direction vector, but this only works for a flat surface. I will have some curved / angled walls that I will need to calculate for. I know I need to start off by finding the angle between the ball's direction vector and the plane normal but I am not exactly sure how to go about this.
If anyone can explain or point me to a good tutorial??
-
You calculate the normal by computing the first derivative at the point of intersection. Then you can just do an incident angle reflection against the hyper plane orthogonal to that normal.
In practive this computation would be pretty expensive for a game, I'm sure there are some type of approximations, though I don't know of anything specifically.
-
Well, I came up with a function to calculate the reflection angle based on the objects velocity vector and the normal of the intersected face of the mesh. I pluged it into a small console app to test it and the numbers seem to work.
Code:
int main() {
D3DXVECTOR3 OldVelocity(4.0f, -2.0f, 1.0f), // Object velocity vector before collision
PlaneNormal(0.0f, 1.0f, 0.0f), // Direction plane is facing
NewVelocity; // Object velocity vector after collision
std::cout<<OldVelocity.x <<"," <<OldVelocity.y <<"," <<OldVelocity.z <<"\n";
float dot = (D3DXVec3Dot(&-OldVelocity, &PlaneNormal) );
NewVelocity = (2 * dot) * PlaneNormal + OldVelocity;
std::cout<<NewVelocity.x <<"," <<NewVelocity.y <<"," <<NewVelocity.z <<"\n";
std::cin.get();
return 0;
}
Whatever numbers i assign to OldVelocity get mirrored over whatever numbers I assign to PlaneNormal, which is exactly what I need.
My only problem now is how to get the normal of the face that was intersected. I know I can use D3DXIntersect to get the index value of the face, but how do I get the face normal from this?
-
Here's what I have managed to come up with
Code:
bool CCollisionManager::FindNewVelocity(LPDIRECT3DDEVICE9 pDevice,
CMeshInstance* pMesh,
D3DXVECTOR3* pObjectPosition,
D3DXVECTOR3* pOldVelocity,
D3DXVECTOR3* pNewVelocity) {
BOOL Hit = FALSE;
float u, v, dist;
DWORD FaceIndex;
D3DXVECTOR3 ObjectDirection,
PrevObjectDirection,
Velocity = -(*pOldVelocity);
D3DXVECTOR3 PrevObjectPosition = *pObjectPosition - *pOldVelocity;
D3DXVec3Normalize(&ObjectDirection, &PrevObjectDirection);
// Get the normal of the intersected mesh face
// First, Get the vertex and index buffers for the mesh
LPDIRECT3DVERTEXBUFFER9 pVB;
LPDIRECT3DINDEXBUFFER9 pIB;
pMesh->GetMesh()->GetVertexBuffer(&pVB);
pMesh->GetMesh()->GetIndexBuffer(&pIB);
WORD *pIndices = NULL;
WORD *pIntersectedFaceIndex = NULL;
cstmVertex::PositionNormalTextured *pVertices = NULL;
cstmVertex::PositionNormalTextured *pIntersectedFaceVertex = NULL;
pIB->Lock(0, 0, (void**)&pIndices, 0);
pVB->Lock(0, 0, (void**)&pVertices, 0);
// Now find which mesh face was intersected
pDevice->SetTransform(D3DTS_WORLD, pMesh->GetTransform() );
D3DXIntersect(pMesh->GetMesh(),
&PrevObjectPosition,
&ObjectDirection,
&Hit,
&FaceIndex,
&u, &v, &dist,
NULL, NULL);
pIntersectedFaceIndex = &pIndices[3 * FaceIndex];
pIntersectedFaceVertex = &pVertices[*pIntersectedFaceIndex];
pVB->Unlock();
pIB->Unlock();
// Get the normal for the face
D3DXVECTOR3 PlaneNormal(pIntersectedFaceVertex->Nx,
pIntersectedFaceVertex->Ny,
pIntersectedFaceVertex->Nz);
// compute new velocity vector
if (Hit == TRUE) {
float dot = (D3DXVec3Dot(&Velocity, &PlaneNormal) );
*pNewVelocity = (2 * dot) * PlaneNormal + *pOldVelocity;
} else {
*pNewVelocity = *pOldVelocity;
}
return Hit;
}
Everything seems to work fine except for two issues :
- If there is a collision on any axis other than X I get a seg fault
- no mater which face was intersected, I allways get a face normal of (0.0, -1.0, 0.0)
I adapted this from the DX9 SDK sample 'Pick.cpp'
Anyone have any ideas as to what is going on? I've tried everything I can think of and am still at a loss.
Am I even on the right track here? Or is there a better way of getting the face normal?