Archived

This topic is now archived and is closed to further replies.

__Daedalus__

Intersection Question

Recommended Posts

I have an enemy that walks about my level randomly and has sensors on him. The sensor is just a ray in my 3D world. It has an arbitrary starting position and ending postion. How do I check this arbitrary ray against a static mesh? My static meshes are just ID3DXMesh* structures and are oriented in my 3D world with a D3DXMATRIX. I figure I can use D3DXIntersect which I'm quite familiar with. Do I have to change the sensor ray in to the mesh objects model space before the test will work? I figure I have to do something with the ray vector and the meshes matrix. Thanks [edited by - __Daedalus__ on May 26, 2004 6:46:05 PM]

Share this post


Link to post
Share on other sites
Yes, you do need to transform the ray into the level''s model space.
If the ray is stored in your enemy''s model space, you need to multiply the rays position and direction by the enemy''s world matrix, and then by the inverse of the level''s matrix.
D3DXVec3TransformCoord and D3DXVec3TransformNormal should help you out with that.
Steele

Share this post


Link to post
Share on other sites
Hmm, the ray begins in world space. Here's a picture - it usually helps me to illustrate things



The little thing in the bottom right is the enemy. The three bars coming out of it are sensors. It currently walks the perimiter of the level. When it collides with the outside wall it turns a little and continues on.

The code for this interesction test with the level mesh is easy enough:

BOOL CWorldEnvironment::CheckIntersectWorld( float XStart, float YStart, float ZStart, float XEnd, float YEnd, float ZEnd, float* Length )
{
BOOL Hit;
float u, v, Dist;
float XDiff, YDiff, ZDiff, Size;
DWORD FaceIndex;
D3DXVECTOR3 vecDir;

XDiff = XEnd - XStart;
YDiff = YEnd - YStart;
ZDiff = ZEnd - ZStart;

D3DXVec3Normalize(&vecDir, &D3DXVECTOR3(XDiff, YDiff, ZDiff));
D3DXIntersect( m_LevelMesh->GetMesh(), &D3DXVECTOR3(XStart,YStart,ZStart), &vecDir, &Hit, &FaceIndex, &u, &v, &Dist, NULL, NULL);

if(Hit == TRUE)
{
Size = (float)sqrt(XDiff*XDiff+YDiff*YDiff+ZDiff*ZDiff);

if(Dist > Size)
Hit = FALSE;
else
{
if(Length != NULL)
*Length = Dist;
}
}

return Hit;
}
I believe it works because the world is built around the origin and is just rendered with an identity matrix (that is, the world is never translated, rotated etc).

But the box that is in the bottom left of the image is a different story. It is built around the origin but has a world position matrix. I can't work out how to create a similar function as above that will test the box mesh and take its world position in to account.

[edited by - __Daedalus__ on May 26, 2004 6:41:21 PM]

Share this post


Link to post
Share on other sites
Yes, that was what I was talking about.
You need something like :

BOOL CWorldEnvironment::CheckIntersectBox( float XStart, float YStart, float ZStart, float XEnd, float YEnd, float ZEnd, float* Length )
{
BOOL Hit;
float u, v, Dist;
float XDiff, YDiff, ZDiff, Size;
DWORD FaceIndex;
D3DXVECTOR3 vecDir;
D3DXVECTOR3 vecOrig; // Vector's origin

D3DXMATRIX matInv;

XDiff = XEnd - XStart;
YDiff = YEnd - YStart;
ZDiff = ZEnd - ZStart;

vecOrig.x = XStart;
vecOrig.y = YStart;
vecOrig.z = ZStart;
vecDir.x = XDiff;
vecDir.y = YDiff;
vecDir.z = ZDiff;


// m_matBoxWorld is the box's world matrix

D3DXMatrixInverse( &matInv, NULL, &m_matBoxWorld);
D3DXVec3TransformCoord(&vecOrig, &vecOrig, &matInv);
D3DXVec3TransformNormal(&vecDir, &vecDir, &matInv);

D3DXVec3Normalize(&vecDir, &vecDir);

D3DXIntersect( m_BoxMesh->GetMesh(), &vecOrig, &vecDir, &Hit, &FaceIndex, &u, &v, &Dist, NULL, NULL);

if(Hit == TRUE)
{
Size = (float)sqrt(XDiff*XDiff+YDiff*YDiff+ZDiff*ZDiff);

if(Dist > Size)
Hit = FALSE;
else
{
if(Length != NULL)
*Length = Dist;
}
}

return Hit;
}

Hope that helps,
Steele.

Edit : changed getmesh object

[edited by - Crow-knee on May 26, 2004 6:56:41 PM]

Share this post


Link to post
Share on other sites