Thread: Math Question

  1. #1
    Darkness Prevails Dark_Phoenix's Avatar
    Join Date
    Oct 2006
    Location
    Houston, Texas
    Posts
    174

    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??
    Using Code::Blocks and Windows XP

    In every hero, there COULD be a villain!

  2. #2
    Crazy Fool Perspective's Avatar
    Join Date
    Jan 2003
    Location
    Canada
    Posts
    2,640
    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.

  3. #3
    Darkness Prevails Dark_Phoenix's Avatar
    Join Date
    Oct 2006
    Location
    Houston, Texas
    Posts
    174
    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?
    Using Code::Blocks and Windows XP

    In every hero, there COULD be a villain!

  4. #4
    Darkness Prevails Dark_Phoenix's Avatar
    Join Date
    Oct 2006
    Location
    Houston, Texas
    Posts
    174
    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?
    Last edited by Dark_Phoenix; 01-21-2007 at 09:44 AM.
    Using Code::Blocks and Windows XP

    In every hero, there COULD be a villain!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. another exercise question
    By luigi40 in forum C# Programming
    Replies: 3
    Last Post: 11-28-2005, 03:52 PM
  2. opengl DC question
    By SAMSAM in forum Game Programming
    Replies: 6
    Last Post: 02-26-2003, 09:22 PM
  3. More a math question than an algorithm
    By Gustaff in forum C Programming
    Replies: 1
    Last Post: 01-28-2003, 01:10 PM
  4. Stupid Math Question....really stupid
    By ToLazytoSignIn in forum A Brief History of Cprogramming.com
    Replies: 9
    Last Post: 01-16-2003, 07:36 PM
  5. Math Question
    By DarkEldar77 in forum C++ Programming
    Replies: 2
    Last Post: 09-17-2001, 12:52 PM