Jump to content
  • Advertisement

Archived

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

ParityCheck

How 2 use D3DXIntersect?

This topic is 5340 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

The DX8 documentation isn''t much help in places. I was wondering if anyone could tell me how to use D3DXIntersect for detecting collisions betwen two meshes or point to tutorials of the subject. I''m using VC6, ;-)

Share this post


Link to post
Share on other sites
Advertisement
D3DXIntersect tests to see if there is an intersection between a ray and a mesh, not two meshes.

Depending on how accurate you want your collision detection to be, you may be able to get away with just testing to see if the bounding volumes of the two meshes collided.

As far as tutorials go, you can find a few right here on gamedev. Also, you can use google and search for "collision detection" and you''ll see a lot of usefull links.

neneboricua

Share this post


Link to post
Share on other sites
Well its not that I don't under stand what its for. The thing is that I'm not so sure as to how to practically use it. I'm a total newbie to this guys and like I don't seem to understand the parameters that are passed to this fnction d3dxintersect. The thing is that I want to text whether one 3D mesh intersects with another 3D mesh.

I checked out almost all of gamedev, but I can't find any tutorial that specifically deals with collision detection in DX. I'm using DX8 and VC6, maybe I've missed something, but I haven't found any tutorials dealing with collision detection in DX8.

At the moment I'm not very concerned with the accuracy. Just wanna know how to work this function any help please.


[edited by - ParityCheck on November 13, 2003 9:21:34 AM]

Share this post


Link to post
Share on other sites
Just use D3DXComputeBoundingSphere and/or D3DXComputeBoundingBox if you''re not as concerned with accuracy. Spheres and boxes are a lot easier to do Collision Detection with than an arbitrary mesh, and thus save a lot of processor speed.

Share this post


Link to post
Share on other sites
quote:
Original post by ParityCheck
Well its not that I don''t under stand what its for. The thing is that I''m not so sure as to how to practically use it. I''m a total newbie to this guys and like I don''t seem to understand the parameters that are passed to this fnction d3dxintersect. The thing is that I want to text whether one 3D mesh intersects with another 3D mesh.


D3DXIntersect isn''t used for collision detection between meshes. It''s used for ray casting and ray tracing.
quote:

I checked out almost all of gamedev, but I can''t find any tutorial that specifically deals with collision detection in DX. I''m using DX8 and VC6, maybe I''ve missed something, but I haven''t found any tutorials dealing with collision detection in DX8.

You really don''t need tutorials for collision detection written specifically in DX to be usefull. Collision detection is really independent of the API you use. Granted, some of the D3DX functions make implementing collision detection easier but any generic article on collision detection should get you up and running.

The easiest collision detection you could have between two objects whould be to check if their bounding spheres intersected. Use D3DXComputeBoundingSphere to calculate a sphere that fits around your mesh. If you think about it, detecting if there is a collision between two spheres is pretty easy. The code would look something like this:

bool DetectCollision( const D3DXVECTOR3 &vCenter1, FLOAT fRadius1, const D3DXVECTOR3 &vCenter2, FLOAT fRadius2 )
{
D3DXVECTOR3 vTemp;
D3DXVec3Subtract( &vTemp, &vCenter2, &vCenter1 );
FLOAT distance = D3DXVec3Length( &vTemp );
if( distance <= fRadius1+fRadius2 )
{
return true;
}
return false;
}

Here, vCenter1 is the center of the bounding sphere of your first mesh and fRadius1 is the bounding sphere''s radius. vCenter2 and fRadius2 are the same but for the other mesh. If the distance between the centers of the two spheres is less than the sum of the spheres radii (I think that''s how you spell the plural for radius), then there is a collision, otherwise there is not.

Hope this helps,
neneboricua

Share this post


Link to post
Share on other sites
I''ve tried the code mentioned above but my program exits upon reaching the code module. I tried to check whats the problem and it appears that the code exits at D3DXVec3Length(&vTemp).


bool CDirectX::DetectCollision()
{
BotFactory->GetMeshBoundingSphere(pBotCenter, pBotRadius);
aBullet->GetMeshBoundingSphere(pBulletCenter, pBulletRadius);

D3DXVECTOR3 vTemp;
D3DXVec3Subtract(&vTemp, pBulletCenter, pBotCenter);
float distance = D3DXVec3Length(&vTemp);

if(distance<= *pBotRadius+*pBulletRadius)
return true;
else
return false;

};



pBulletCenter and pBotCenter are pointers I''ve declared and are initialising by this function in my mesh class:



D3DXComputeBoundingSphere(lpMesh,lpMesh->GetNumVertices(),D3DFVF_XYZ, pCenter, pRadius)




Another weird thing is that the radii returned by the D3DXComputeBoundingShpere line is zero??

what could be the problem guys

Share this post


Link to post
Share on other sites
The problem is that you're not using D3DXComputeBoundingSphere correctly. Note that you should only compute the bounding sphere of a mesh once (during initialization).

Also, take a look at the parameters to the function. The first one is a pointer to the position of the first vertex, not a pointer to the mesh itself. You've got the second parameter right. The third one is the size of the FVF for the mesh. Do what the documentation says and use the D3DXGetFVFVertexSize function for this parameter. The code to compute the bounding sphere of a mesh would look something like this:

HRESULT MyMesh::ComputeBoundingSphere()
{
HRESULT hr;

VertexType *pVertices = NULL;
if( FAILED( hr = m_pMesh->LockVertexBuffer( D3DLOCK_READONLY, (VOID**)&pVertices ) ) )
return DXTRACE_ERR_MSGBOX( "LockVertexBuffer", hr );

if( FAILED( hr = D3DXComputeBoundingSphere( pVertices, m_pMesh->GetNumVertices(), D3DXGetFVFVertexSize(m_pMesh->GetFVF()), &m_vCenter, &m_fRadius ) ) )
return DXTRACE_ERR_MSGBOX( "D3DXComputeBoundingSphere", hr );

m_pMesh->UnlockVertexBuffer();

return S_OK;
}


In this code, m_pMesh is a pointer to a D3D mesh object. m_vCenter is D3DXVECTOR3 that contains the center of the bounding sphere, and m_fRadius is a FLOAT that contains the radius of the bounding sphere. These are all class member variables, but you can change them to whatever you want.

Also note that "VertexType" is a struct defined by your app. You need to know what information is stored in the vertices of your mesh to create this type. The standard vertex type look something like this:

struct VertexType
{
D3DXVECTOR3 position;
D3DXVECTOR3 normal;
FLOAT tu, tv;
};

This vertex structure has space for a position, normal, and texture coordinates. If you're not sure what vertex format your model uses, you can force it to use the vertex structure you want by using ID3DXMesh::CloneMeshFVF() to make a copy of the original mesh but make the copy use your vertex structure instead. Take a look at the EnhancedMesh or OptimizedMesh samples that come with the SDK if you need more info on how to mess with .x models

neneboricua

[edited by - neneboricua19 on November 19, 2003 12:47:22 PM]

Share this post


Link to post
Share on other sites
I''ve tried the mentioned code and made alterations but now my program seems to exit upon creration of my mesh. Below is my

Mesh object constructor


CMesh::CMesh(LPDIRECT3DDEVICE8 alpDevice, char *pMeshPath)
{
lpDevice = alpDevice;
Status = new CText(lpDevice);

LPD3DXMESH pMesh=NULL;
LPD3DXBUFFER lpMatBuffer = NULL;

if(FAILED(D3DXLoadMeshFromX(pMeshPath, D3DXMESH_SYSTEMMEM, lpDevice, NULL, &lpMatBuffer, &nMaterials, &pMesh)))
return;

D3DXMATERIAL* d3dXMaterial = (D3DXMATERIAL*)lpMatBuffer->GetBufferPointer();

lpTexture = new LPDIRECT3DTEXTURE8[nMaterials];
d3dMaterial = new D3DMATERIAL8[nMaterials];

for(DWORD i =0; i<nMaterials; i++)
{
d3dMaterial[i] = d3dXMaterial[i].MatD3D;
d3dMaterial[i].Ambient = d3dMaterial[i].Diffuse;

if(FAILED(D3DXCreateTextureFromFile(lpDevice,d3dXMaterial[i].pTextureFilename, &lpTexture[i])))
lpTexture[i] = NULL;

}

lpMatBuffer->Release();
lpMatBuffer = NULL;

pMesh->CloneMeshFVF(D3DXMESH_MANAGED, D3D_MYVERTEX2,lpDevice, &lpMesh);

SetBoundingSphere();
WriteToLog("SetBoundingSphere() -> OK");

pMesh->Release();
pMesh = NULL;

D3DXComputeNormals(lpMesh,NULL);


};



The setboundingsphere() function is where trouble is, below is my setbounding sphere function. Its being called only once

during initislising of the object.


CMesh::SetBoundingSphere()
{
myVertex *pVertices = NULL;
lpMesh->LockVertexBuffer( D3DLOCK_READONLY, (BYTE**)&pVertices);
WriteToLog("lpMesh->LockVertexBuffer->OK");
D3DXComputeBoundingSphere( pVertices, lpMesh->GetNumVertices(), D3DXGetFVFVertexSize(lpMesh->GetFVF()), pCenter,

pRadius) //<--- My program exits here????

lpMesh->UnlockVertexBuffer();
};



the program exits at the D3DXComputeBoundingSphere code and pCenter and pRadius are two class variabvles holding the center

and radius of bounding sphere respectively. I''d really appreciate help on this guys

Share this post


Link to post
Share on other sites
You should REALLY check the HRESULT values that D3D returns. Also, what does the debug spew say? The debug spew will tell you why a particular function has failed. In case you weren''t aware of it, you should do all your development work using the Debug Runtimes. You can easily switch between the Debug and Retail Runtimes by going to Control Panel->DirectX and then clicking on the Direct3D tab. Make sure that the Debug Output Level is at the maximum and put a bullet beside the "Debug Runtime" options. Now D3D will output debug messages that will tell you exactly why certain functions have failed.

In your SetBoundingSphere function, the data type for the variable "pVertices" should be D3D_MYVERTEX2, because that''s what you cloned the mesh to use.

One thing I noticed is that in your constructor, it seems like you''ve assumed that every material will definately have a textrue associated with it. This might be fine in your case but there are models out there that use textures with some materials and don''t use textures with others. Just something to keep in mind. If you know that all the models you will be loading have textures associated with each material, then everything''s fine.

Hope this helps,
neneboricua

Share this post


Link to post
Share on other sites
i just wanted to point out that in your first argument to the
ComputeBoundingSphere call.

youll have to change it a bit to get it to work properly if you are using DX9. it should go something like this.





D3DXComputeBoundingBox(&pVertices->v_position , m_pMesh->GetNumVertices(), //continued

D3DXGetFVFVertexSize(m_pMesh->GetFVF()),&m_Box_Min, &m_Box_Max );//ended




this is for a bounding box of course, but you have to be certain to reference your position property in your struct, and be sure if your struct doesnt contain a D3DXVECTOR3 to hold position, that you cast it to one during the call.


(D3DXVECTOR3)(&pVertices->v_position),



thanks for your replies neneboricua19, they have been helpful to me.

Dredd
________________________________________

"To die with your sword still in its sheath is most regrettable" -- Miyomoto Musashi




[edited by - Dreddnafious Maelstrom on December 2, 2003 4:43:15 PM]

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!