Getting Intersected Triangle

Started by
10 comments, last by L. Spiro 11 years, 2 months ago
I'm triangle to use raycasting to get the intersected triangle, here is the code that I'm using:


LPD3DXMESH pMesh = GetMesh();
pMesh->CloneMeshFVF( D3DXMESH_MANAGED, pMesh->GetFVF(), d3ddev, &pMesh );

LPDIRECT3DVERTEXBUFFER9 pVB;
LPDIRECT3DINDEXBUFFER9 pIB;

pMesh->GetVertexBuffer( &pVB );
pMesh->GetIndexBuffer( &pIB );

WORD* pIndices;
D3DVERTEX* pVertices;

// Lock
pIB->Lock( 0, 0, ( void** )&pIndices, 0 );
pVB->Lock( 0, 0, ( void** )&pVertices, 0 );

BOOL pHit;
DWORD pFaceIndex;
FLOAT pU, pV, pDist;
D3DXIntersect(pMesh, &rayFrom, &rayTo, &pHit, &pFaceIndex, &pU, &pV, &pDist, NULL, NULL);
if (pHit)
{
    DWORD dwNumFaces = pMesh->GetNumFaces();
    for(DWORD i = 0; i < dwNumFaces; i++)
    {
        D3DXVECTOR3 v0 = pVertices[pIndices[3 * i + 0]].p;
        D3DXVECTOR3 v1 = pVertices[pIndices[3 * i + 1]].p;
        D3DXVECTOR3 v2 = pVertices[pIndices[3 * i + 2]].p;


        if ( D3DXIntersectTri(&v0, &v1, &v2, &rayFrom, &rayTo, &pU, &pV, &pDist) )
        {
             // Intersected triangle found
        }
    }
}

// Unlock
pMesh->UnlockVertexBuffer();
pMesh->UnlockIndexBuffer();
Why the above code doesn't work as expected?
I'm not getting a valid intersected triangle in (v0, v1, v2).
Advertisement

Is 'pHit' ever true? What is the HRESULT of D3DXIntersect()?

Have you checked the validity of the data behind two Lock()-pointers? If you assign the indices to a WORD, the buffer should be created as a 16 bit buffer.

Also, I don't see why you would test all faces individually once D3DXIntersect() has determined an intersection.

Is 'pHit' ever true? What is the HRESULT of D3DXIntersect()?

I'm getting intersected triangle in (v0, v1, v2) but it's invalid, D3DXIntersect() HRESULT is S_OK.

Have you checked the validity of the data behind two Lock()-pointers? If you assign the indices to a WORD, the buffer should be created as a 16 bit buffer.

I tried using byte* instead of WORD*, same problem.

Also, I don't see why you would test all faces individually once D3DXIntersect() has determined an intersection.

I use break; after working on the intersection:


if ( D3DXIntersectTri(&v0, &v1, &v2, &rayFrom, &rayTo, &pU, &pV, &pDist) )
{
     // Process intersection...
     break;
}

You've called the 3rd parameter passed to D3DXIntersect, "rayTo", which worries me slightly. The 3rd parameter is actually the direction of the ray, which is a vector, not a point in space. If rayTo is actually a point, you'll need to pass in (rayTo - rayFrom).

Also, you shouldn't need to scan through the faces after the initial test, the output value in pFaceIndex should contain the index of the face hit, if D3DXIntersect returns a hit.

[size="2"]Currently working on an open world survival RPG - For info check out my Development blog:[size="2"] ByteWrangler

@Postie:

First, I use bullet physics raycasting to check for intersection, then I use D3DXIntersect() to get the intersected triangle, rayFrom and rayTo are D3DXVECTOR3 that I use with bullet physics raycasting.

I changed the code to something like this:


LPD3DXMESH pMesh = GetMesh();
pMesh->CloneMeshFVF( D3DXMESH_MANAGED, pMesh->GetFVF(), d3ddev, &pMesh );

WORD* pIndices;
D3DVERTEX* pVertices;
pMesh->LockVertexBuffer(D3DLOCK_READONLY, (void**)&pVertices);
pMesh->LockIndexBuffer(D3DLOCK_READONLY, (void**)&pIndices);

BOOL pHit;
DWORD pFaceIndex;
FLOAT pU, pV, pDist;
HRESULT hr = D3DXIntersect(pMesh, &rayFrom, &rayTo, &pHit, &pFaceIndex, &pU, &pV, &pDist, NULL, NULL);
assert(hr == S_OK);
if (pHit)
{
    D3DXVECTOR3 v0 = pVertices[pIndices[3 * pFaceIndex + 0]].p;
    D3DXVECTOR3 v1 = pVertices[pIndices[3 * pFaceIndex + 1]].p;
    D3DXVECTOR3 v2 = pVertices[pIndices[3 * pFaceIndex + 2]].p;
}

pMesh->UnlockVertexBuffer();
pMesh->UnlockIndexBuffer();

Anything wrong with the above code?

UP! Any help would be appreciated, I'm still having this problem.

@Postie:

First, I use bullet physics raycasting to check for intersection, then I use D3DXIntersect() to get the intersected triangle, rayFrom and rayTo are D3DXVECTOR3 that I use with bullet physics raycasting.

You didn’t address the issue he mentioned at all, and doing so would have likely solved your problem by now.
You are passing a starting point for the ray and an ending point for the ray when you are supposed to be passing a starting point and a direction.
D3DXIntersect() doesn’t care if the same ray points work in Bullet. Justifying passing incorrect parameters by saying, “But it works in Bullet,” is not going to convince DirectX to start working.

Bullet takes a ray start point and a ray end point (which means it is not actually a ray but a line segment).
DirectX D3DXIntersect() takes a ray start point and a ray direction. As was already pointed out to you.

L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

@L. Spiro:

So that means I have to pass (rayTo - rayFrom) as a direction.

I tried:


HRESULT hr = D3DXIntersect(pMesh, &rayFrom, &(rayTo - rayFrom), &pHit, &pFaceIndex, &pU, &pV, &pDist, NULL, NULL);
assert(hr == S_OK);
if (pHit)
{
    D3DXVECTOR3 v0 = pVertices[pIndices[3 * pFaceIndex + 0]].p;
    D3DXVECTOR3 v1 = pVertices[pIndices[3 * pFaceIndex + 1]].p;
    D3DXVECTOR3 v2 = pVertices[pIndices[3 * pFaceIndex + 2]].p;
}

Still not getting a valid intersected triangle.

I expected as much but I did not want to overload you.

Also you need to normalize the direction vector, which means you should store it in a temporary. This helps with debugging anyway, which is a skill you need to be a good developer in the first place.

I expect you have yet another problem which is much more complicated to explain.

Are you drawing the target object with a world matrix other than identity?

If so you need to translate the ray into the frame-of-reference of that object (and each object in your scene when you have more than one) before doing the ray cast.

That means translating the ray’s position by the inverse world matrix of each object, and translating the ray’s direction vector by the inverse transpose of the inverse world matrix.

L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

When I switch to Wirefire mode, I notice that I'm getting a valid intersected triangle for the terrain ONLY, but none of the other meshes are getting a valid intersected triangle.

Here is the code that I tried:


// Get ray direction
D3DXVECTOR3 direction = rayTo - rayFrom;
D3DXVec3Normalize(&direction, &direction);

// Inverse matrix
D3DXMATRIX matWorld = mesh->worldMatrix();
D3DXMATRIX matInverse;
D3DXMatrixInverse(&matInverse, NULL, &matWorld);

D3DXVECTOR3 modelRayOrigin, modelRayDir;
D3DXVec3TransformCoord(&modelRayOrigin, &hits.origin, &matInverse);
D3DXVec3TransformNormal(&modelRayDir, &direction, &matInverse);

hr = D3DXIntersect(pMesh, &modelRayOrigin, &modelRayDir, &pHit, &pFaceIndex, &pU, &pV, &pDist, NULL, NULL);
assert(hr == S_OK);

This topic is closed to new replies.

Advertisement