Code archives/3D Graphics - Maths/Lib to create an OBB and test if a point or entity is inside its space

This code has been declared by its author to be Public Domain code.

Download source code

Lib to create an OBB and test if a point or entity is inside its space by Bill Stanbrook
(Posted 20 years ago)
This lib allows you to create and configure an Oriented Bounding Box (a box that is not locked to the dimensional axiis), and then test if a point or an entity has intruded into the OBB's space.

; This lib allows you to create and configure an OBB, and then test if a point or an entity has intruded into the OBB's space.

; An OBB is an Oriented Bounding Box. It is not locked to the dimensional axiis and consequently can be rotated.
; An AABB is an Axially Aligned Bounding Box. It is aligned to the dimensional axiis and consequently cannot be rotated.

; Note that an OBB is really just an AABB that exists in a different coordinate space. To test if a point has intruded into an OBB's space, you transform the point into the OBB's coordinate space and then perform the same box intrusion test that you would use with an AABB.



Function CreateOBB( x#, y#, z#, pitch#, yaw#, roll#, width#, height#, depth#, parent = 0 )
; Creates an OBB and returns its entity handle. Note that an OBB is just a pivot entity.
; The position, rotation, and size of the OBB will be set using the supplied values. Note that these values are initially applied in global space, but will be relative to the parent space after the obb has been created.
; An optional parent entity can be specified. The obb will be attached to this parent, and its position, rotation, and size will update when the position, rotation, and\or size of the parent changes.

	Local obb_pivot = CreatePivot( parent )
	PositionEntity obb_pivot, x#, y#, z#, True
	RotateEntity obb_pivot, pitch#, yaw#, roll#, True
	ScaleEntity obb_pivot, width#, height#, depth#, True
	Return obb_pivot
End Function



Function PointInOBB( obb_pivot, x#, y#, z# )
; Tests if the specified x, y, z, point is inside the space of the specified OBB pivot entity.
; If so, a true result is returned. If not, a false result is returned.

	TFormPoint x#, y#, z#, 0, obb_pivot
	x# = TFormedX() : y# = TFormedY() : z# = TFormedZ()
	If ( x# >= -1.0 ) And ( x# <= 1.0 )
		If ( y# >= -1.0 ) And ( y# <= 1.0 )
			If ( z# >= -1.0 ) And ( z# <= 1.0 )
				Return True
			EndIf
		EndIf
	EndIf
	Return False
End Function



Function EntityInOBB( obb_pivot, entity_to_test )
; Tests if the specified entity to test is inside the space of the specified OBB pivot entity.
; If so, a true result is returned. If not, a false result is returned.

	TFormPoint EntityX#( entity_to_test, True ), EntityY#( entity_to_test, True ), EntityZ#( entity_to_test, True ), 0, obb_pivot
	x# = TFormedX() : y# = TFormedY() : z# = TFormedZ()
	If ( x# >= -1.0 ) And ( x# <= 1.0 )
		If ( y# >= -1.0 ) And ( y# <= 1.0 )
			If ( z# >= -1.0 ) And ( z# <= 1.0 )
				Return True
			EndIf
		EndIf
	EndIf
	Return False
End Function


;_______________________________________________________
; *** EXAMPLE ***



Graphics3D 800, 600, 0, 2
SetBuffer BackBuffer()
HidePointer

CreateLight()

Global G_user = CreatePivot()
Const C_USER_MOVE_SPEED# = 10.0

Global G_camera = CreateCamera( G_user )
CameraZoom G_camera, 1.6
Const C_MOUSELOOK_SPEED# = 0.4

Global G_test_ball = CreateSphere( 8, G_camera )
MoveEntity G_test_ball, 0.0, 0.0, 5.0
ScaleEntity G_test_ball, 0.05, 0.05, 0.05, True

; Create the OBB pivot and set it's transformation data.
Global G_obb = CreateOBB( 1.0, 50.0, 30.0, 20.0, 60.0, 190.0, 60.0, 20.0, 10.0 )

; -- Create a cube to display the position of the OBB.
Global G_display_cube = CreateCube( G_obb )
PositionEntity G_display_cube, 0.0, 0.0, 0.0
RotateEntity G_display_cube, 0.0, 0.0, 0.0
ScaleEntity G_display_cube, 1.0, 1.0, 1.0
EntityAlpha G_display_cube, 0.5
;^^^^^^

EntityColor CreatePlane(), 0,128,255

Global G_mouse_speed_x#, G_mouse_speed_y#

PositionEntity G_user, 0.0, 10.0, -20.0, True

Local elapsed
Global G_deltatime#
Global G_old_time = MilliSecs()

Repeat

	; -- Update timing.
	elapsed = MilliSecs() - G_old_time
	If elapsed > 100 Then elapsed = 100
	G_deltatime# = elapsed / 1000.0
	G_old_time = MilliSecs()
	;^^^^^^

	G_mouse_speed_x# = MouseXSpeed()
	G_mouse_speed_y# = MouseYSpeed()
	
	MouseLook
	MoveUser

	; -- Do the OBB test.
	If EntityInOBB( G_obb, G_test_ball )
		EntityColor G_test_ball, 0.0, 255.0, 0.0
	Else
		EntityColor G_test_ball, 200.0, 0.0, 0.0
	EndIf
	;^^^^^^
	
	UpdateWorld
	RenderWorld
	Color 200, 0, 0
	Text 10, 10, "Press W, A, S, D, F, C keys to move. Press ESCAPE to exit."
	Text 10, 30, "The ball's color will change from red to green when it intrudes into the OBB."
	Flip
Until KeyHit( 1 )

End



Function MouseLook()
	TurnEntity G_user, 0.0, -G_mouse_speed_x# * C_MOUSELOOK_SPEED#, 0.0
	TurnEntity G_camera, G_mouse_speed_y# * C_MOUSELOOK_SPEED#, 0.0, 0.0
	MoveMouse GraphicsWidth() / 2, GraphicsHeight() / 2
	;MouseXSpeed() : MouseYSpeed()
End Function



Function MoveUser()
	Local move_x#, move_y#, move_z#
	
	If KeyDown( 32 ) ; right - D key
		move_x# = 1.0
	ElseIf KeyDown( 30 ) ; left - A key
		move_x# = -1.0
	EndIf
	
	If KeyDown( 33 ) ; up - F key
		move_y# = 1.0
	ElseIf KeyDown( 46 ) ; down - C key
		move_y# = -1.0
	EndIf
	
	If KeyDown( 17 ) ; forwards - W key
		move_z# = 1.0
	ElseIf KeyDown( 31 ) ; backwards - S key
		move_z# = -1.0
	EndIf
	
	MoveEntity G_user, ( move_x# * C_USER_MOVE_SPEED# ) * G_deltatime#, ( move_y# * C_USER_MOVE_SPEED# ) * G_deltatime#, ( move_z# * C_USER_MOVE_SPEED# ) * G_deltatime#
End Function
; The code can be found at: http://www.blitzbasic.com/codearcs/codearcs.php?code=1920