[bb] Lib to create an OBB and test if a point or entity is inside its space by Zethrax [ 1+ years ago ]

Started by BlitzBot, June 29, 2017, 00:28:41

Previous topic - Next topic

BlitzBot

Title : Lib to create an OBB and test if a point or entity is inside its space
Author : Zethrax
Posted : 1+ years ago

Description : 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, andor 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


Code :
Code (blitzbasic) Select
; The code can be found at: http://www.blitzbasic.com/codearcs/codearcs.php?code=1920

Comments :


Stevie G(Posted 1+ years ago)

 Not bad For info, this will only work for scaled entities rather than scaled meshes.  You'd need to use mesh depth, height and width instead of default 1.0 for a more robust check.  Note that from what you have it's also easy to get the penetration depth and collision normal of a point in rect by using the axis of least separation theory.You could also do the axis checking by just using ..  "If  abs(x#) <=1.0" etc..Stevie