Having trouble trying to implement the 3D collision technique (Solved)

Started by
7 comments, last by Zakwayda 17 years, 4 months ago
Hi guys i am doing a 3D Pacman game in DX9 and c++, i have got all my models in a AABB 'Axis Aligned Bounding Box', but now i want to get the test collision function working properly. my Bounding Box code is as follows: - boundingVolumes.h

#ifndef _BOUNDING_VOLUMES_
#define _BOUNDING_VOLUMES_

#include <d3dx9.h>
#include <string>
#include <limits>

// Colors
const D3DXCOLOR      BLACK( D3DCOLOR_XRGB(  0,   0,   0) );
const D3DXCOLOR      BLUE ( D3DCOLOR_XRGB(  0,   0, 255) );

class CBoundingVolumes
{
public:
	CBoundingVolumes(void);
	virtual ~CBoundingVolumes(void);

	//////////////////
	// Struct
	/////////////////
	struct sBoundingBox
	{
		sBoundingBox();
		D3DXVECTOR3 _min;
		D3DXVECTOR3 _max;
	};

	sBoundingBox    s_BoundingBox;

	D3DMATERIAL9 WHITE_MTRL;
	D3DMATERIAL9 RED_MTRL;
	D3DMATERIAL9 GREEN_MTRL;
	D3DMATERIAL9 BLUE_MTRL;
	D3DMATERIAL9 YELLOW_MTRL;
	
	LPD3DXMESH BoxMesh;

	/////////////////////
	// Functions
	////////////////////
		D3DMATERIAL9 BoundingVolumes_InitMtrl(D3DXCOLOR a, D3DXCOLOR d, D3DXCOLOR s, D3DXCOLOR e, float p);
		void BoundingVolumes_CreateBox(LPDIRECT3DDEVICE9 device, ID3DXMesh* mesh);
		void BoundingVolumes_RenderBox(LPDIRECT3DDEVICE9 device);
		bool BoundingVolumes_Box_Compute(ID3DXMesh* mesh, sBoundingBox* box);
private:
};
#endif // _BOUNDING_VOLUMES_





boundingVolumes.cpp

#include "boundingvolumes.h"
#include <vector>

CBoundingVolumes::CBoundingVolumes(void)
{
	  BLUE_MTRL   = BoundingVolumes_InitMtrl(BLUE, BLUE, BLUE, BLACK, 2.0f);
	  BoxMesh    = 0;
}
CBoundingVolumes::~CBoundingVolumes(void)
{
	BoxMesh->Release();
}
D3DMATERIAL9 CBoundingVolumes::BoundingVolumes_InitMtrl(D3DXCOLOR a, D3DXCOLOR d, D3DXCOLOR s, D3DXCOLOR e, float p)
{
	D3DMATERIAL9 mtrl;
	mtrl.Ambient  = a;
	mtrl.Diffuse  = d;
	mtrl.Specular = s;
	mtrl.Emissive = e;
	mtrl.Power    = p;
	return mtrl;
}
CBoundingVolumes::sBoundingBox::sBoundingBox()
{
	// infinite small 
	_min.x = INFINITY;
	_min.y = INFINITY;
	_min.z = INFINITY;

	_max.x = -INFINITY;
	_max.y = -INFINITY;
	_max.z = -INFINITY;
}
void CBoundingVolumes::BoundingVolumes_RenderBox(LPDIRECT3DDEVICE9 device)
{
	// Draw bounding volume in Blue
	D3DMATERIAL9 color = BLUE_MTRL;
	color.Diffuse.a = 0.10f; // 10% opacity

	device->SetMaterial(&color);
	device->SetTexture(0, 0); // disable texture

	device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
	device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
	device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

	BoxMesh->DrawSubset(0);
}
bool CBoundingVolumes::BoundingVolumes_Box_Compute(ID3DXMesh* mesh, sBoundingBox* box)
{
	HRESULT hr = 0;

	BYTE* pVertices = NULL;
	hr=mesh->LockVertexBuffer(0, (void**)&pVertices);
	if (FAILED(hr))
		return FALSE;

	hr = D3DXComputeBoundingBox(   //D3D Function that calc's the bounding box for a mesh
		(D3DXVECTOR3*)pVertices, //Vertex position component is stored 1st in the vertex structure we are using
		mesh->GetNumVertices(),	 //Get the number of vertices's in the mesh
		D3DXGetFVFVertexSize(mesh->GetFVF()), //function how many bytes there are between each vertex 
		&box->_min, //Return the min and max points of the bounding box
		&box->_max);

	mesh->UnlockVertexBuffer();

	if( FAILED(hr) )
		return false;

	return true;
}
void	CBoundingVolumes::BoundingVolumes_CreateBox(LPDIRECT3DDEVICE9 device, ID3DXMesh* mesh)
{
	//******************** Compute Bounding Box
	BoundingVolumes_Box_Compute(mesh, &s_BoundingBox);
	D3DXCreateBox(
		device,
		s_BoundingBox._max.x - s_BoundingBox._min.x,
		s_BoundingBox._max.y - s_BoundingBox._min.y,
		s_BoundingBox._max.z - s_BoundingBox._min.z,
		&BoxMesh,
		0);
}





right and now to create the bounding boxes for my models i do

//in pacman.h
#include "../BoundingVolume/boundingvolumes.h"
CBoundingVolumes *pBoundingBox;
// in pacman.cpp
        pBoundingBox = NULL;
	pBoundingBox = new CBoundingVolumes();
	pBoundingBox->BoundingVolumes_CreateBox(device,pModel->mesh);
        pBoundingBox->BoundingVolumes_RenderBox(device);


Up till now all the above is working brill, its this bit i need help with :) so now in my Game.cpp update function i want to check for collisions. here is where i create my game objects and update everything i.e. CPacMan *pPacman; // Pointer to a PacMan object So we come to the bit that is bugging the hell out off me :( i know that the function to check for 2 coliding BoundingBoxes is: bool Game::Check_For_Collisions(pBox1,pBox2) { if ( pBox1._min.x > pBox2._max.x || pBox2._min.x > pBox1._max.x ||pBox1._min.y > pBox2._max.y || pBox2._min.y > pBox1._max.y ||pBox1._min.z > pBox2._max.z || pBox2._min.z > pBox1._max.z ) { return false; } return true; } but how do i declare 'bool Check_For_Collisions(? pBox1,? pBox2);' properly what do i add for ?. and when i want to call it Check_For_Collisions(pPacman->?????,pPill->?????); [Edited by - Prog101 on December 16, 2006 11:21:29 AM]
Advertisement
Just to help us along a bit, could you give us some more info? What specifically are you having trouble with? Do you already know that the AABBs are being computed correctly? Do they render correctly?

Some more details would be helpful.
Sorry jyk i was just trying to get it all on properly so it could be understood, sorry if i have posted too much code but it will help all other newbies :)

All the AABB are computed correctly and are rendered properly, i have a exe of it at:
http://homepage.ntlworld.com/j.power40/html/zipfiles/exe.zip
Is this what you're looking for?
bool Game::Check_For_Collisions(const sBoundingBox& pBox1, const sBoundingBox& pBox2) {    // ...}
ok, so to do that i sill need to alter my boundingvolumes class yeah, if i take the Bounding box struct out of the class so it now looks like
#ifndef _BOUNDING_VOLUMES_#define _BOUNDING_VOLUMES_#include <d3dx9.h>#include <string>#include <limits>// Colorsconst D3DXCOLOR      BLACK( D3DCOLOR_XRGB(  0,   0,   0) );const D3DXCOLOR      BLUE ( D3DCOLOR_XRGB(  0,   0, 255) );		// Struct	struct sBoundingBox	{		sBoundingBox();		D3DXVECTOR3 _min;		D3DXVECTOR3 _max;	};class CBoundingVolumes{public:	CBoundingVolumes(void);	virtual ~CBoundingVolumes(void);	sBoundingBox    s_BoundingBox;	D3DMATERIAL9 WHITE_MTRL;	D3DMATERIAL9 RED_MTRL;	D3DMATERIAL9 GREEN_MTRL;	D3DMATERIAL9 BLUE_MTRL;	D3DMATERIAL9 YELLOW_MTRL;	LPD3DXMESH BoxMesh;	/////////////////////	// Functions	////////////////////		D3DMATERIAL9 BoundingVolumes_InitMtrl(D3DXCOLOR a, D3DXCOLOR d, D3DXCOLOR s, D3DXCOLOR e, float p);		void BoundingVolumes_CreateBox(LPDIRECT3DDEVICE9 device, ID3DXMesh* mesh);		void BoundingVolumes_RenderBox(LPDIRECT3DDEVICE9 device);		bool BoundingVolumes_Box_Compute(ID3DXMesh* mesh, sBoundingBox* box);private:};#endif // _BOUNDING_VOLUMES_

and change in boundingVolumes.cpp
sBoundingBox::sBoundingBox()
{
// infinite small
_min.x = INFINITY;
_min.y = INFINITY;
_min.z = INFINITY;

_max.x = -INFINITY;
_max.y = -INFINITY;
_max.z = -INFINITY;
}

so now in my game.cpp
//declare the funcbool Check_For_Collisions(const sBoundingBox& pBox1,const sBoundingBox& pBox2);/////////////////////////// Check_For_Collisions() /////////////////////////bool Game::Check_For_Collisions(const sBoundingBox& pBox1,const sBoundingBox& pBox2){			/*If the max x position of A is less than the min x position of B they do not collide 		If the min x position of A is greater than the max x position of B they do not collide 		and the same goes for y and z */		if (pBox1._max.x < pBox2._min.x || pBox1._min.x > pBox2._max.x			|| pBox1._max.y < pBox2._min.y || pBox1._min.y > pBox2._max.y			|| pBox1._max.z < pBox2._min.z || pBox1._min.z > pBox2._max.z)		{			return false;		} 		else		{			return true;		}}//To update the testif (Check_For_Collisions(pTree->pBoundingBox->s_BoundingBox,pPill->pBoundingBox->s_BoundingBox) == true){	//Do a responce}


[Edited by - Prog101 on December 16, 2006 9:57:51 AM]
Right i have it all setup now but i am geting a collision when i'm no where near the tree, i have put
	//Perform a collision check between pacman and the tree		if (Check_For_Collisions(pPacman->pBoundingBox->s_BoundingBox,pTree->pBoundingBox->s_BoundingBox) == true)		{			//Show a response			colhit = true;		}

colhit is coming up true when i'm no where near the tree, i declare colhit as false in init, and this is the only place where i say it to be true.
Quote:Original post by Prog101
Right i have it all setup now but i am geting a collision when i'm no where near the tree, i have put
*** Source Snippet Removed ***
colhit is coming up true when i'm no where near the tree, i declare colhit as false in init, and this is the only place where i say it to be true.
You'll need to do some debugging :-)

If you're not doing it already, render the bounding boxes onscreen to make sure they correspond correctly to the objects they represent. Then add some debug output tracking of the 'colhit' variable and the logical flow of the AABB intersection function (e.g. 'returning false because second conditional failed, values are blah blah blah').

Debugging is a process we all must go through at times. It can be a little tedious, but I think with a little effort you should have no trouble tracking down the cause of your coldet problem.

There are some other software design and style issues in your code, but for now we'll just focus on getting the algorithm working.
Got the sod working now, i was not taking into account the position of the objetcs. so what i did was

sBoundingBox pTempBox1;sBoundingBox pTempBox2;//////////////////////////////////////////////////////// Keep updating this all the time to see if anything has been hit//////////////////////////////////////////////////////	//Perform a collision check between pacman and the tree	if (Collision_Check(pPacman->get_BoundingBox(),pPacman->getPosition(),pTree->get_BoundingBox(),pTree->getPosition()) == true)	{colhit = 1;}	else	{colhit = 0;}//////////////////////////////////////////////////////// Check_For_Collisions() //////////////////////////////////////////////////////bool Game::Collision_Check(const sBoundingBox& pBox1,D3DXVECTOR3 pBox1Pos, const sBoundingBox& pBox2,D3DXVECTOR3 pBox2Pos){		/*If the max x position of box1 is less than the min x position of box2 they do not collide 		If the min x position of box1 is greater than the max x position of box2 they do not collide 		and the same goes for y and z */		pTempBox1._min = pBox1._min + pBox1Pos;	pTempBox1._max = pBox1._max + pBox1Pos;	pTempBox2._min = pBox2._min + pBox2Pos;	pTempBox2._max = pBox2._max + pBox2Pos;	if (pTempBox1._max.x < pTempBox2._min.x || pTempBox1._min.x > pTempBox2._max.x		|| pTempBox1._max.y < pTempBox2._min.y || pTempBox1._min.y > pTempBox2._max.y		|| pTempBox1._max.z < pTempBox2._min.z || pTempBox1._min.z > pTempBox2._max.z)		return false;	else		return true;}


Right now down to design issues, how would you suggest i do it better?
Quote:Original post by Prog101
Right now down to design issues, how would you suggest i do it better?
From a design perspective, the first question I would ask might be, what is the intended purpose of the CBoundingVolumes class? To me the name doesn't seem to be entirely consistent with its apparent function, but perhaps I'm missing something.

Just to get a jump start on some stylistic issues, I'll also mention that it's a little cumbersome and redundant to prefix class member functions with the function name, e.g. BoundingVolumes_InitMtrl(). Also, especially given that the function names will be shorter without the prefix, there shouldn't be a need to abbreviate words such as 'material'; IMO, clarity in this case is more important than saving a few keystrokes here and there.

This topic is closed to new replies.

Advertisement