Sign in to follow this  

2d collision detection for 3d objects

This topic is 3458 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

I'm working on having a box bounce off another box, while trying to avoid using external libraries where possible (had to use one for graphics, and thats all i want to use.) Basically i'm thinking i know whats going on, but how to fix it is being a pain to work out in my head, while i have an idea, just would like some input from people outside of me. What is happening is that when the box1 hits box2 the values for velocity (held within a vector obj1vel) are all being modified, as apposed to one direction only. So if box1 is moving up and right and hits box 2 on the bottom face of the box, instead of simply bouncing and changing the velocity of the y axis, changing both the y and x velocities. I believe it is because (at this time) i'm not checking to see if both sets of values are within the box at all times, and that when the second set of values are internal to the side's space that it captures this and modifies accordingly. This is what i'm starting to work on, and the obj1vel was a recent addition to the code, but not yet implemented properly.

int CollisionDetection( D3DXVECTOR3 obj1Pos,
			D3DXVECTOR3 obj2Pos,
			D3DXVECTOR3 obj1Vel,
			float obj1Size,
			float obj2Size,
			D3DXVECTOR3 obj1scale,
			D3DXVECTOR3 obj2scale)
{
	//create object2's boundaries
	double obj2Left = obj2Pos.x - (obj2Size * obj2scale.x);
	double obj2Right = obj2Pos.x + (obj2Size * obj2scale.x);
	double obj2Bottom = obj2Pos.y - (obj2Size * obj2scale.y);
	double obj2Top = obj2Pos.y + (obj2Size * obj2scale.y);
	//double obj2Front = obj2Pos.z - (obj2Size * obj2scale.z);
	//double obj2Back = obj2Pos.z + (obj2Size * obj2scale.z);
	
	//create object1's boundaries
	double obj1Left = obj1Pos.x - (obj1Size * obj1scale.x);
	double obj1Right = obj1Pos.x + (obj1Size * obj1scale.x);
	double obj1Bottom = obj1Pos.y - (obj1Size * obj1scale.y);
	double obj1Top = obj1Pos.y + (obj1Size * obj1scale.y);
	//double obj1Front = obj1Pos.z - (obj1Size * obj1scale.z);
	//double obj1Back = obj1Pos.z + (obj1Size * obj1scale.z);

	//cut out for the moment to allow me to play with the individual rules
	/*if (obj1Right > obj2Left && obj1Left < obj2Right &&
		obj1Top > obj2Bottom && obj1Bottom < obj2Top &&
		obj1Back > obj2Front && obj1Front < obj2Back)*/

	int action = 0;
	
	if ((obj1Right >= obj2Left) && (obj1Top <= obj2Top) && (obj1Top > obj2Bottom)
		|| (obj1Left <= obj2Right) && (obj1Top <= obj2Top) && (obj1Top > obj2Bottom))
	{
		//adds 1 to the result to indicate that a change in xv is needed
		action += 1;
	}
	if (((obj1Top >= obj2Bottom) && (obj1Left >= obj2Left) && (obj1Left <= obj2Right))
		|| ((obj1Top >= obj2Bottom) && (obj1Right <= obj2Right) && (obj1Right >= obj2Left)))
	{
		//adds 2 to the result to indicate that a change in yv is needed
		action += 2;
	}

	return action; //returns no action if no rules are met.
}





Share this post


Link to post
Share on other sites
If I understand your code correctly then the first the first if would do the following:


//y-axis
7|
6| 2222222
5| 2 2
4| 112111 2
3| 1 2222222
2| 1 1
1| 111111
0|__________
0123456789 //x-axis

I hope you can see that box 1 hits box 2 from the bottom left (more bottom though).

You'd expect that only yv is changed but:

(obj1Right >= obj2Left) && (obj1Top <= obj2Top) && (obj1Top > obj2Bottom)

becomes true, since

obj1Right = 6 and obj2Left = 3 -> (obj1Right >= obj2Left) = true
obj1Top = 4 and obj2Top = 6 -> (obj1Top <= obj2Top) = true
obj1Top = 4 and obj2Bottom = 3 -> (obj1Top > obj2Bottom) = true

Thus, action += 1; is executed.

Your code is likely no to work if box1 comes from the top. So you should perhaps change your approach and first detect if the boxes overlap on both x and the y axis. If they do, use the bigger overlap and use the other axis as the reflection vector (for simplicity). Then just reflect the velocity vector about that.

Basically it's just (very simple, just axis aligned, no rotation according to center of mass):

if(overlapx > overlapy) //you hit the top or bottom
{
velocity.y *= -1;
}
else if(overlapx < overlapy) //you hit the left or right side
{
velocity.x *= -1;
}
else //you hit a corner, i.e. overlaps on x and y are equal
{
velocity.y *= -1;
velocity.x *= -1;
}


Btw, have a look at this tutorial for 2D rectangle collision response.

Share this post


Link to post
Share on other sites
The code listed in my OP is only working on a specific rule for the moment, so you are correct.

What i'm thinking of doing is calculating when an object enters the same horizontal/vertical space of the other object, and calculating for when pos+vel causes a second violation of space as it were...

I dno if thats going to help overly, but yea its an idea... btw your diagram is exactly what i'm talking about.

I'll have a read of that tutorial, seems quite in depth.

Share this post


Link to post
Share on other sites
Posting again for possible solution:



int CollisionDetection(D3DXVECTOR3 obj1Pos, D3DXVECTOR3 obj2Pos, D3DXVECTOR3 obj1Vel, float obj1Size, float obj2Size, D3DXVECTOR3 obj1scale, D3DXVECTOR3 obj2scale)
{

// Plan of attack for collision detection.
// 1 - Convert object positions into planar positions.
// 2 - Create a flag to check to see if 2x dimensions overlaps
// 3 - Create a flag to check when Obj1Pos + Obj1Vel create a third overlap.
// 4 - Flag based on the change in the third instance of overlap what direction
// needs to be modified.

double obj2Left = obj2Pos.x - (obj2Size * obj2scale.x);
double obj2Right = obj2Pos.x + (obj2Size * obj2scale.x);
double obj2Bottom = obj2Pos.y - (obj2Size * obj2scale.y);
double obj2Top = obj2Pos.y + (obj2Size * obj2scale.y);
double obj2Front = obj2Pos.z - (obj2Size * obj2scale.z);
double obj2Back = obj2Pos.z + (obj2Size * obj2scale.z);

double obj1Left = obj1Pos.x - (obj1Size * obj1scale.x);
double obj1Right = obj1Pos.x + (obj1Size * obj1scale.x);
double obj1Bottom = obj1Pos.y - (obj1Size * obj1scale.y);
double obj1Top = obj1Pos.y + (obj1Size * obj1scale.y);
double obj1Front = obj1Pos.z - (obj1Size * obj1scale.z);
double obj1Back = obj1Pos.z + (obj1Size * obj1scale.z);

double obj1LeftMoved = obj1Pos.x - (obj1Size * obj1scale.x) + obj1Vel.x;
double obj1RightMoved = obj1Pos.x + (obj1Size * obj1scale.x) + obj1Vel.x;
double obj1BottomMoved = obj1Pos.y - (obj1Size * obj1scale.y) + obj1Vel.y;
double obj1TopMoved = obj1Pos.y + (obj1Size * obj1scale.y) + obj1Vel.y;
double obj1FrontMoved = obj1Pos.z - (obj1Size * obj1scale.z) + obj1Vel.z;
double obj1BackMoved = obj1Pos.z + (obj1Size * obj1scale.z) + obj1Vel.z;

int action = 0;
bool overlapLR = false, overlapTB = false, overlapFB = false;
bool overlapAtStepLR = false, overlapAtStepTB = false, overlapAtStepFB = false;

if (obj1Right > obj2Left && obj1Left < obj2Right)
{
overlapLR = true;
}
if (obj1Top > obj2Bottom && obj1Bottom < obj2Top)
{
overlapTB = true;
}
if (obj1Back > obj2Front && obj1Front < obj2Back)
{
overlapFB = true;
}


if (obj1RightMoved > obj2Left && obj1LeftMoved < obj2Right)
{
overlapAtStepLR = true;
}
if (obj1TopMoved > obj2Bottom && obj1BottomMoved < obj2Top)
{
overlapAtStepTB = true;
}
if (obj1BackMoved > obj2Front && obj1FrontMoved < obj2Back)
{
overlapAtStepFB = true;
}

//surfaces only

if (overlapLR == true && overlapTB == true && overlapFB == false && overlapAtStepFB == true)
{
action += 4;
}
if (overlapLR == true && overlapFB == true && overlapTB == false && overlapAtStepTB == true)
{
action += 2;
}
if (overlapTB == true && overlapFB == true && overlapLR == false && overlapAtStepLR == true)
{
action += 1;
}

//edges only
if (overlapLR == false && overlapTB == false && overlapFB == true && overlapAtStepLR == true && overlapAtStepTB == true)
{
action += 3;
}
if (overlapLR == false && overlapTB == true && overlapFB == false && overlapAtStepLR == true && overlapAtStepFB == true)
{
action += 5;
}
if (overlapLR == true && overlapTB == false && overlapFB == false && overlapAtStepTB == true && overlapAtStepFB == true)
{
action += 6;
}

//corners only
if (overlapLR == false && overlapTB == false && overlapFB == false && overlapAtStepLR == true && overlapAtStepTB == true && overlapAtStepFB == true)
{
action += 7;
}

return action;
}




What does everyone think?

Edit : added corner/edge detection.

[Edited by - Kalten on June 29, 2008 7:28:20 PM]

Share this post


Link to post
Share on other sites

This topic is 3458 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this