Autograph
Autograph
thumb_mca
thumb_mca
thumb_cupid
thumb_cupid
thumb_knights
thumb_knights
thumb_job_boxes
thumb_job_boxes
thumb_kelly_hoppen
thumb_kelly_hoppen
thumb_rivermuse
thumb_rivermuse
thumb_ibm_gpsa
thumb_ibm_gpsa
open portfolio
3D Collision detection
March 23rd, 2010

Wooo, ok so as I’m writing this I feel like a load has been lifted from my shoulders. Over the past few weeks I have been producing a game with has been using newly learned skills with Papervision3D.

One of the biggest challenges has been the collision detection between a point and a plane. With alot of research, playing with code and a few lenghthy talks with fellow developers I now have a piece of code that is working nicely.

Below are some of the solutions which I have descovered. I also want to say thanks to Seb Lee-Delisle and Marc Binsted for their help and code examples.

Seb has written a few interesting articles about Predictive collision detection techniques and Predicting circle line collisions which i highly recomend a read. At first Vector math blew my mind but with some time I have been able to get my head around it and get a better understanding of it.

Now I dont like to make things easy for myself, not only am I using a 3D engine but my planes are rotated on the Z axis (they were rotating on the Y axis as well but that was just causing way to many problems). So because of the Z axis rotation I couldnt just work out if the point falls within an area using half the planes height and width. But first it was a case of working out the distance between the point and the plane, and to get there I needed to get the dot product. The below example uses the Number3D class within Papervision3D.

// GET THE DISTANCE FROM A POINT TO THE PLANE'S WORLD POSITION AS A DOT PRODUCT
   public function distanceToWorldPoint( p:Number3D ):Number
   {
// 	TEMP BECOMES THE VECTOR BETWEEN THE POINT AND THE PLANES POSITION
//	copyFrom COPIES THE X,Y,Z PROPERTIES OF P
	this.temp.copyFrom( p );
 
//	MINUS THE POSITION FROM TEMP - THE SAME AS -= OPERATOR
	this.temp.minusEq( this.w_position );
 
//	RETURN THE DOT PRODUCT BETWEEN THE POINT AND THE PLANE
	return Number3D.dot( this.temp, this.normal );
   }

Once I had the dot product of the current distance I then had to work out the distance in the next frame, by adding the points velocity of the points co-ordinates. With these two values you can get the time that collision would occur, but I only needed to know when the point was close to the plane. When I knew this I could then check to see if my point was within the planes triangle using the below function.

// CHECK TO SEE IF A POINT IS WITHIN A TRIANGLE
   static public function pointInTriangle2( p:Number3D, a:Number3D, b:Number3D, c:Number3D ):Boolean
   {
//	COMPUTE VECTORS
	var v0:Number3D 	= Number3D.sub( c, a )
	var v1:Number3D		= Number3D.sub( b, a )
	var v2:Number3D 	= Number3D.sub( p, a )
 
//	COMPUTE DOT PRODUCTS
	var dot00:Number	= Number3D.dot( v0, v0 )
	var dot01:Number 	= Number3D.dot( v0, v1 )
	var dot02:Number 	= Number3D.dot( v0, v2 )
	var dot11:Number 	= Number3D.dot( v1, v1 )
	var dot12:Number 	= Number3D.dot( v1, v2 )
 
//	COMPUTE BARYCENTRIC COORDINATES
	var invDenom:Number	= 1 / ( dot00 * dot11 - dot01 * dot01 )
	var u:Number 		= ( dot11 * dot02 - dot01 * dot12 ) * invDenom
	var v:Number 		= ( dot00 * dot12 - dot01 * dot02 ) * invDenom
 
//	Check if point is in triangle
	return (u > 0) &amp;&amp; (v > 0) &amp;&amp; (u + v < 1)
   }

I managed to find this and another techniques of calculation whether a point was in a triangle and can be found here, there is a nice little example on the site showing you how the calculations work.

Leave a Reply

You must be logged in to post a comment.