Box-Sphere Intersection Routine

Blitz3D Forums/Blitz3D Programming/Box-Sphere Intersection Routine

Has anyone got a quick and dirty routine to test whether a sphere is intersecting with a box? I tried using Dave Bird's Area Collision lib in the code archives, but it doesn't seem to be 100% accurate.

I know you could use perhaps use MeshesIntersect etc, but I would prefer to use a purely mathematical solution if possible.

Found one - looks nice and simple:

http://www.acm.org/tog/GraphicsGems/gems/BoxSphere.c

Also these links might be useful for anyone looking for various interection routines:

http://www.realtimerendering.com/int/
http://www.magic-software.com/Intersection.html

Doesn't blitz3d already have something for this?

Gah. It seems the above routine is not 100% accurate either. It is slightly out on corners. So my request for help still applies, if anyone has a 100% working routine.

Something this elementary, posted on the ACM site, should work.

Notice that the box must be axis-aligned, i.e. the edges parallel to the coordinate axes.

If this is not true then you need to find the coordinates of the sphere's center in 'box space'.

Doh! The ACM routine contained a SQR() function, which I mistakenly assumed to be the same as the Blitz SQR() function - but of course it's not, it actually a 'square of' function and not a square root function.

Here's the working routine:
; Sphere-Box Intersection Routine

; Blitz version by simon@..., based on code found at <a href="http://www.acm.org/tog/GraphicsGems/gems/BoxSphere.c" target="_blank">http://www.acm.org/tog/GraphicsGems/gems/BoxSphere.c</a>
; See also <a href="http://www.realtimerendering.com/int/" target="_blank">http://www.realtimerendering.com/int/</a> and <a href="http://www.magic-software.com/Intersection.html" target="_blank">http://www.magic-software.com/Intersection.html</a> for some more (non-Blitz flavoured) intersection routines

; This routine is a fast, accurate way of testing to see whether a solid sphere intersects a solid axis-aligned box.
; Useful to act as an activation zone in games - i.e. if sphere is in invisible zone then activate event.

; Use mouse to rotate camera, left and right mouse buttons to move camera forward/backward
; Move sphere by using cursor keys and r/f for rise/fall
; When the sphere touches the box, a 'collision' message should appear in the top-left hand corner of the screen

; Initialise
width=640
height=480

Graphics3D width,height,0,2
SetBuffer BackBuffer()

MoveMouse width/2,height/2

cam=CreateCamera()
PositionEntity cam,0,100,-100
RotateEntity cam,30,0,0

light=CreateLight()

; Set dimensions for box/sphere, then create them using these dimensions
bx#=0 ; box x
by#=0 ; box y
bz#=0 ; box z
bw#=50 ; box width
bh#=50 ; box height
bd#=50 ; box depth
sx#=0 ; sphere x
sy#=0 ; sphere y
sz#=0 ; sphere z
sr#=5 ; sphere radius

box=CreateCube()
EntityColor box,255,255,0
FitMesh box,0,0,0,bw,bd,bh
PositionEntity box,bx,by,bz

sphere=CreateSphere()
EntityColor sphere,255,0,0
ScaleEntity sphere,sr,sr,sr

PositionEntity sphere,sx#,sy#,sz#

While Not KeyDown(1)

	; Move camera
	mxs=mxs+MouseXSpeed()
	mys=mys+MouseYSpeed()

	RotateEntity cam,mys,-mxs,0
	MoveEntity cam,0,0,MouseDown(1)-MouseDown(2)

	; Move sphere
	If KeyDown(203) Then sx#=sx#-1
	If KeyDown(205) Then sx#=sx#+1
	If KeyDown(19) Then sy#=sy#+1
	If KeyDown(33) Then sy#=sy#-1
	If KeyDown(200) Then sz#=sz#+1
	If KeyDown(208) Then sz#=sz#-1

	sx#=sx#+mx#
	sy#=sy#+my#
	sz#=sz#+mz#

	PositionEntity sphere,sx#,sy#,sz#

	RenderWorld
	
	; Test to see if sphere intersects box
	If SphereBoxIntersection(sx#,sy#,sz#,sr#,bx#,by#,bz#,bw#,bh#,bd#)=True Then Text 0,0,"Collision"
	
	Flip

Wend


Function SphereBoxIntersection(sx#,sy#,sz#,sr#,bx#,by#,bz#,bw#,bh#,bd#)

	; sx#,sy#,sz# = sphere x,y,z centre co-ordinates
	; sr# = sphere radius
	; bx#,by#,bz# = box x,y,z corner co-ordinates
	; bw#,bh#,bd# = box width,height,depth

	Local dmin#=0
	Local sr2#=sr*sr
	
	; x axis
	If sx < bx

		dmin=dmin+((sx-bx)*(sx-bx))
		
	Else If sx>(bx+bw)

		dmin=dmin+(((sx-(bx+bw)))*((sx-(bx+bw))))

	EndIf

	; y axis
	If sy < by

		dmin=dmin+((sy-by)*(sy-by))
		
	Else If sy>(by+bh)

		dmin=dmin+(((sy-(by+bh)))*((sy-(by+bh))))

	EndIf

	; z axis
	If sz < bz

		dmin=dmin+((sz-bz)*(sz-bz))

	Else If sz>(bz+bd)

		dmin=dmin+(((sz-(bz+bd)))*((sz-(bz+bd))))

	EndIf

	If dmin#<=sr2# Then Return True Else Return False

End Function


Cool Just what i was looking for