AABB to AABB collision time function

BlitzMax Forums/BlitzMax Programming/AABB to AABB collision time function

Rico(Posted 2008) [#1]
I think my terminology is correct with the AABBs. I suppose I really mean 2D rectangles.
Has anyone got or know of a function that given two rectangles and their respective velocities (in x and y components) will return the time of collision and the position of both rectangles at this time? It would also return false or true depending on whether the objects actually collide as well.
I've been looking around the net and I keep getting close but not finding the banana yet

Thanks - Rico


ImaginaryHuman(Posted 2008) [#2]
I presume you'd trace lines from the corners of the boxes and see if they overlap?


Arowx(Posted 2008) [#3]
It would probably be easier to use spheres, then I think you would just need to check to find the closest point along their vectors and check the distance between to see if it was under their combined radii.

Checking via spheres would allow for a very fast check which could then be supplemented with 'AABB rectangle collision checking'.

Here is an example of this approach...



Hope this helps, let me know how you get on as I will probably need the BlitzMax solution for this shortly? ;0)


Rico(Posted 2008) [#4]
Thanks Merx and Human. I'll get to it. I have now managed to find an AABB to AABB collision function in a book (that coincidentally just arrived from Amazon today!). I haven't had much time to look throught it yet. All the example code is in C but I should be able to convert it to BlitzMax (though my knowlede of C isn't great). It looks like a really good book for polygonal collision detection and determining collision time. Its called Real Time Collision Detection by Christer Ericson. Everyone loves it on the net - which is why I ordered it (though I wasn't really sure exactly what was in it until now).
Before I can do much though I need to know how to change variables that you pass to a function - inside that function. Without using Global Variables

do e.g
x=1;y=2
change(x,y)
'hopefully now x=3;y=5

Function change(a:int,b:int)
       a=a+2;b=b+2
end function
 


I know in C you put an & sign before the variable in the function definition.

Thanks - Rico


Arowx(Posted 2008) [#5]
Ok in C++ that's passing by reference, you are passing the actual variable as opposed to passing by value where only the numeric value of the variable is transfered.

In BlitzMax you can use pointers to pass the Address of the variable and this can then be used to alter the value of the variable.

e.g.
x=1;y=2

Print x + " " + y
change(Varptr x, Varptr y)
Print x + " " + y
'hopefully now x=3;y=5

Function change(a:Int Ptr,b:Int Ptr)
       a[0]=a[0]+2;b[0]=b[0]+2
End Function


The odd array syntax is used to access the values of the variable pointers.

There may be a better way to write this, but hope it helps.

Regards


Rico(Posted 2008) [#6]
OK well I've got this function which finds the time of collision between two AABB's (rectangles). It seems to work. I've done my best to convert it to Blitz (I'm no expert). It returns whether a collision has occured and 'tf' contains the time of the first collision, and 'tl' the time of the last collision - the time at which the rectangles no longer collide.
Basically you multiply the x-vector and y-vector of each object with 'tf' to get the position when they first collide.
Here is the Code and functions: Blitz may have Max and Min functions but they weren't documented very well in the help section so I wrote my own.

Type rect
	Field x1#,y1#,x2#,y2#
	Field w#,h#
	Field xv#,yv#
End Type

	 
Function MovingBoxColl(a:rect,b:rect,tf:Float Ptr,tl:Float Ptr)
	If rectsoverlap(a.x1,a.y1,a.w,a.h,b.x1,b.y1,b.w,b.h)
		tf[0]=0;tl[0]=0
		Return True
	EndIf
	'calculate relative velocity
	rvx#=b.xv-a.xv
	rvy#=b.yv-a.yv
	'initialise points of first and last contact
	tf[0]=0; tl[0]=1
	'for X axis determine the times of first and last contact, if any
	If rvx<0
		If b.x2<a.x1 Then Return False ' Non-intersecting and moving apart
		If a.x2<b.x1 Then tf[0]=RMax((a.x2-b.x1)/rvx,tf[0])
		If b.x2>a.x1 Then tl[0]=RMin((a.x1-b.x2)/rvx,tl[0])
	EndIf
	If rvx>0
		If b.x1>a.x2 Then Return False ' Non-intersecting and moving apart
		If b.x2<a.x1 Then tf[0]=RMax((a.x1-b.x2)/rvx,tf[0])
		If a.x2>b.x1 Then tl[0]=RMin((a.x2-b.x1)/rvx,tl[0])
	EndIf
	'No overlap possible if time of first contact occurs after time of last contact
	If tf[0]>tl[0] Then Return False
	 'for Y axis determine the times of first and last contact, if any
	If rvy<0
		If b.y2<a.y1 Then Return False ' Non-intersecting and moving apart
		If a.y2<b.y1 Then tf[0]=RMax((a.y2-b.y1)/rvy,tf[0])
		If b.y2>a.y1 Then tl[0]=RMin((a.y1-b.y2)/rvy,tl[0])
	EndIf
	If rvy>0
		If b.y1>a.y2 Then Return False ' Non-intersecting and moving apart
		If b.y2<a.y1 Then tf[0]=RMax((a.y1-b.y2)/rvy,tf[0])
		If a.y2>b.y1 Then tl[0]=RMin((a.y2-b.y1)/rvy,tl[0])
	EndIf
	'No overlap possible if time of first contact occurs after time of last contact
	If tf[0]>tl[0] Then Return False

	Return True	
End Function

Function RMax:Float(a:Float,b:Float)
	If b>a Then Return b
	Return a
End Function

Function RMin:Float(a:Float,b:Float)
	If b<a Then Return b
	Return a
End Function

Function rectsoverlap:Int(x0:Int,y0:Int,w0:Int,h0:Int,x2:Int,y2:Int,w2:Int,h2:Int)
	If x0>(x2+w2)Or(x0+w0)<x2 Then Return False
	If y0>(y2+h2)Or(y0+h0)<y2 Then Return False
	Return True
End Function




Rico(Posted 2008) [#7]
Hi - Just found out that to pass variable to a function by reference
you can use Var. - Instead of Var Ptr and then indexing the pointer in the function.

e.g

Rem
Var is a composite type containing a reference to a variable of the 
specified Type.
End Rem

' the following illustrates parsing function parameters by reference

Function ReturnMultiplevalues(a Var,b Var,c Var)
	a=10
	b=20
	c=30
	Return
End Function

Local x,y,z

ReturnMultipleValues(x,y,z)

Print "x="+x	'10
Print "y="+y	'20
Print "z="+z	'30