TGC Codebase Backup



PickObject() function for DBC by Relativity

27th Jan 2006 11:06
Summary

This function uses Sparky's .DLL to pick an object from a 2D point, such as the mouse position.



Description

This program will allow the user to see if a vector extending from a 2D point on the screen into 3D space will pass through an object. It incorporates Sparky's .DLL with my PickScreen() function.

Sparky's .DLL has been uploaded; check the bottom of the Code page to download it.

Syntax: PickObject(XPoint,YPoint,Distance#)
XPoint - 2D X-Coordinate on the screen
YPoint - 2D Y-Coordinate on the screen
Distance# - Maximum distance to check for objects

IMPORTANT:
-This code requires Sparky's .DLL to run.
-Enhanced version of DarkBASIC is required to run this function

WARNING:
-The Box Collision in Sparky's .DLL is bugged; do not use it unless the object you are using it on will never be behind another object when using this function

INSTRUCTIONS:
-Declare all objects you want to be detected by the function as Sparky's .DLL requires (see the Command List)
-Whenever an object is moved or rotated use Sparky's updateObjectDBC() function
-Make sure you paste all the function required for Sparky's .DLL to the bottom of your program.

The PickObject() function is the first of the functions listed. Sparky's .DLL has been uploaded; check the bottom of the Code page to download it.



Code
                                    ` This code was downloaded from The Game Creators
                                    ` It is reproduced here with full permission
                                    ` http://www.thegamecreators.com
                                    
                                    `==========================================================================
`PickObject() EXAMPLE PROGRAM
`==========================================================================
`PickScreen() CODE WRITTEN BY:  SITHSPAWN (SEE CODEBASE)
`==========================================================================
`RAYCASTING .DLL WRITTEN BY:  SPARKY
`(DOWNLOAD AT http://sparky152.homestead.com/files/DBCcollisions_v1.05.zip)
`==========================================================================
`ARRANGED BY:  SITHSPAWN
`==========================================================================


`I M P O R T A N T:  SPARKY'S DLL IS REQUIRED FOR THIS FUNCTION TO WORK!!!  (SEE DOWNLOAD INFORMATION AT THE TOP OF THIS PROGRAM)
`ALSO  I M P O R T A N T:  DarkBASIC ENHANCED IS REQUIRED FOR THIS FUNCTION!!!
`AGAIN,  I M P O R T A N T:  YOU MUST DECLARE ALL OBJECTS AS SPARKY'S .DLL REQUIRES.  SEE SPARKY'S .DLL COMMAND LIST.
`LAST  I M P O R T A N T:  ANY CHANGES TO THE OBJECT YOU ARE PICKING (I.E. MOVEMENT, ROTATION) MUST BE ACCOUNTED FOR WITH
`SPARKY'S updateObjectDBC() function.

`W A R N I N G:  SPARKY'S BOX COLLISION IS BUGGED.  THEREFORE, IT IS STRONGLY ADVISED THAT YOU STAY AWAY FROM USING IT UNLESS YOU KNOW THAT
`THE OBJECT WILL NEVER BE BEHIND ANOTHER OBJECT FROM THE CAMERA'S PERSPECTIVE.



`INITIAL SETUP
SYNC ON
AUTOCAM OFF
SET DISPLAY MODE 800,600,16
RANDOMIZE TIMER()

`MAKE MATRIX FOR BASIS FOR COMPARISON
MAKE MATRIX 1,200,200,10,10
SET MATRIX WIREFRAME ON 1

`MAKE OBJECTS
MAKE OBJECT PLAIN 1,0,0
POSITION OBJECT 1,0,10,0

MAKE OBJECT CUBE 2,30
MAKE OBJECT SPHERE 3,50
MAKE OBJECT CONE 4,70

FOR OBJECT=2 TO 4
   COLOR OBJECT OBJECT,RGB(RND(255),RND(255),RND(255))
   POSITION OBJECT OBJECT,RND(200),RND(100),RND(200)
   ROTATE OBJECT OBJECT,RND(359),RND(359),RND(359)
NEXT OBJECT

`DECLARE OBJECTS WITH SPARKY'S .DLL
setupObjectDBC(2,0,0)
setupObjectDBC(3,0,1)
setupComplexObjectDBC(4,0,2)

`DECLARE AN ARRAY FOR USE WITH THE PICKSCREEN FUNCTION
DIM VECTOR#(2)

`MAIN LOOP
DO

`  CAMERA MOVEMENT
   IF UPKEY()=1 THEN MOVE OBJECT 1,3
   IF DOWNKEY()=1 THEN MOVE OBJECT 1,-3

   IF MOUSELOOK=1

      IF LEFTKEY()=1 OR RIGHTKEY()=1
         IF LEFTKEY()=1 THEN MLOOKY2#=WRAPVALUE(MLOOKY#-90)
         IF RIGHTKEY()=1 THEN MLOOKY2#=WRAPVALUE(MLOOKY#+90)
         ROTATE OBJECT 1,0,MLOOKY2#,0:MOVE OBJECT 1,3
         ROTATE OBJECT 1,MLOOKX#,MLOOKY#,0
      ENDIF

      POSITION MOUSE 400,300
      MLOOKX#=WRAPVALUE(MLOOKX#+MOUSEMOVEY())
      MLOOKY#=WRAPVALUE(MLOOKY#+MOUSEMOVEX())
      IF MLOOKX#>180 AND MLOOKX#<270 THEN MLOOKX#=270
      IF MLOOKX#<180 AND MLOOKX#>90 THEN MLOOKX#=90
      ROTATE OBJECT 1,MLOOKX#,MLOOKY#,0

      IF MOUSECLICK()=2 AND WAITMOUSE>5
         WAITMOUSE=0
         MOUSELOOK=0
         SHOW MOUSE
      ENDIF

   ELSE

      IF LEFTKEY()=1 THEN ROTATE OBJECT 1,OBJECT ANGLE X(1),WRAPVALUE(OBJECT ANGLE Y(1)-3),0
      IF RIGHTKEY()=1 THEN ROTATE OBJECT 1,OBJECT ANGLE X(1),WRAPVALUE(OBJECT ANGLE Y(1)+3),0

      IF MOUSECLICK()=2 AND WAITMOUSE>5
         WAITMOUSE=0
         MOUSELOOK=1
         HIDE MOUSE
         MLOOKX#=OBJECT ANGLE X(1) : MLOOKY#=OBJECT ANGLE Y(1)
         IF OBJECT_SELECTED>0
            updateObjectDBC(OBJECT_SELECTED)
            OBJECT_SELECTED=0
         ENDIF
      ENDIF

      `***********************************
      `PICKING THE OBJECT (THE GOOD STUFF)
      `***********************************

      IF MOUSECLICK()=1 AND WAITSELECT>5
         WAITSELECT=0
         IF OBJECT_SELECTED=0

            OBJECT_SELECTED=PICKOBJECT(MOUSEX(),MOUSEY(),1000.0)

            IF OBJECT_SELECTED>0 THEN DISTANCE#=DISTANCETOCAM(OBJECT_SELECTED)

         ELSE

            updateObjectDBC(OBJECT_SELECTED)
            OBJECT_SELECTED=0

         ENDIF
      ENDIF

      IF OBJECT_SELECTED>0

         PICKSCREEN(MOUSEX(),MOUSEY(),DISTANCE#)
         PRINT VECTOR#(0),VECTOR#(1),VECTOR#(2)
         POSITION OBJECT OBJECT_SELECTED,VECTOR#(0),VECTOR#(1),VECTOR#(2)

      ENDIF
   ENDIF


   INC WAITMOUSE
   INC WAITSELECT

   POSITION CAMERA OBJECT POSITION X(1),OBJECT POSITION Y(1),OBJECT POSITION Z(1)
   ROTATE CAMERA OBJECT ANGLE X(1),OBJECT ANGLE Y(1),OBJECT ANGLE Z(1)

   SET CURSOR 0,0
   PRINT "Select an object with the mouse to move it."
   PRINT "Click the right mouse button to use mouse look."
   PRINT "Use the arrow keys to move."
   PRINT
   PRINT "Object Selected> ",OBJECT_SELECTED
   IF OBJECT_SELECTED>0
      PRINT "X POS> ",OBJECT POSITION X(OBJECT_SELECTED)," Y POS> ",OBJECT POSITION Y(OBJECT_SELECTED)," Z POS> ",OBJECT POSITION Z(OBJECT_SELECTED)
   ENDIF

   SYNC
LOOP










`I M P O R T A N T:  SPARKY'S DLL IS REQUIRED FOR THIS FUNCTION TO WORK!!!  (SEE DOWNLOAD INFORMATION AT THE TOP OF THIS PROGRAM)
`ALSO  I M P O R T A N T:  DarkBASIC ENHANCED IS REQUIRED FOR THIS FUNCTION!!!
`AGAIN,  I M P O R T A N T:  YOU MUST DECLARE ALL OBJECTS AS SPARKY'S .DLL REQUIRES.  SEE SPARKY'S .DLL COMMAND LIST.

`W A R N I N G:  SPARKY'S BOX COLLISION IS BUGGED.  THEREFORE, IT IS STRONGLY ADVISED THAT YOU STAY AWAY FROM USING IT UNLESS YOU KNOW THAT
`THE OBJECT WILL NEVER BE BEHIND ANOTHER OBJECT FROM THE CAMERA'S PERSPECTIVE.

`THIS FUNCTION WILL GIVE YOU A POINT IN 3D SPACE A CERTAIN DISTANCE AWAY FROM THE CAMERA
`THAT CORRESPONDS TO A 2D POINT ON YOUR SCREEN.
`SYNTAX: XPOINT# IS THE 2D X POINT ON YOUR SCREEN
`        YPOINT# IS THE 2D Y POINT ON YOUR SCREEN
`        DISTANCE# IS THE MAX DISTANCE AWAY FROM THE CAMERA YOU WANT TO CALCULATE PICK OBJECT

`W A R N I N G:  THERE MUST EXIST AN OBJECT DECLARED WITH SPARKY'S .DLL OR ELSE THIS FUNCTION WILL FAIL

`RESULTS WILL BE OUTPUT BY THE FUNCTION.  THE NUMBER OF THE CLOSEST OBJECT SELECTED WILL BE OUTPUT.
`A RESULT OF 0 MEANS THAT NO OBJECT IS SELECTED

FUNCTION PICKOBJECT(XPOINT,YPOINT,DISTANCE#)

   DIM PICKOBJECTVECTOR#(2)

`  CALCULATE HALF THE SCREEN WIDTH AND HEIGHT
`  SUBTRACT 1 BECAUSE POINTS START AT (0,0), NOT (1,1)
   HALFSW#=(SCREEN WIDTH()-1)
   HALFSW#=HALFSW#/2
   HALFSH#=(SCREEN HEIGHT()-1)
   HALFSH#=HALFSH#/2

`  CALCULATE THE RATIO CONSTANTS.  REMEMBER, HEIGHT CONSTANT IS ALWAYS .6
   SW#=SCREEN WIDTH()
   SH#=SCREEN HEIGHT()
   WIDTHCONSTANT#=SW#/SH#
   WIDTHCONSTANT#=.6*WIDTHCONSTANT#


`  CALCULATE 3D COORDINATE OF SCREEN POINT ASSUMING CAMERA ISN'T ROTATED AND IS AT POSITION 0,0,0
   XPOINT#=XPOINT
   YPOINT#=YPOINT
   XPOINT#=XPOINT-HALFSW#
   YPOINT#=HALFSH#-YPOINT
   XVEC#=WIDTHCONSTANT#*(XPOINT#/HALFSW#)
   YVEC#=.6*(YPOINT#/HALFSH#)
   ZVEC#=1

`  CALCULATE LENGTH FROM CAMERA POINT TO 3D SCREEN POINT
   LENGTH#=SQRT((XVEC#*XVEC#)+(YVEC#*YVEC#)+(ZVEC#*ZVEC#))

`  MAKE VECTOR A UNIT VECTOR
   XVEC#=(XVEC#/LENGTH#)
   YVEC#=(YVEC#/LENGTH#)
   ZVEC#=(ZVEC#/LENGTH#)

`  CALCULATE POINT ON VECTOR AT DESIRED DISTANCE FROM CAMERA
   XVEC#=DISTANCE#*XVEC#
   YVEC#=DISTANCE#*YVEC#
   ZVEC#=DISTANCE#*ZVEC#

`  CALULATE X-AXIS ROTATION RELATIVE TO CAMERA
   OLDY#=YVEC#
   OLDZ#=ZVEC#

   YVEC#=(OLDY#*COS(CAMERA ANGLE X()))-(OLDZ#*SIN(CAMERA ANGLE X()))
   ZVEC#=(OLDY#*SIN(CAMERA ANGLE X()))+(OLDZ#*COS(CAMERA ANGLE X()))

`  CALCULATE Y-AXIS ROTATION RELATIVE TO CAMERA
   OLDX#=XVEC#
   OLDZ#=ZVEC#

   XVEC#=(OLDX#*COS(CAMERA ANGLE Y()))+(OLDZ#*SIN(CAMERA ANGLE Y()))
   ZVEC#=(OLDZ#*COS(CAMERA ANGLE Y()))-(OLDX#*SIN(CAMERA ANGLE Y()))

`  CALCULATE Z-AXIS ROTATION RELATIVE TO CAMERA
   OLDX#=XVEC#
   OLDY#=YVEC#

   XVEC#=(OLDX#*COS(CAMERA ANGLE Z()))-(OLDY#*SIN(CAMERA ANGLE Z()))
   YVEC#=(OLDX#*SIN(CAMERA ANGLE Z()))+(OLDY#*COS(CAMERA ANGLE Z()))

`  CALCULATE THE VECTOR RELATIVE TO THE STANDARD AXIS RATHER THAN RELATIVE TO THE CAMERA
   VECTOR#(0)=XVEC#+CAMERA POSITION X()
   VECTOR#(1)=YVEC#+CAMERA POSITION Y()
   VECTOR#(2)=ZVEC#+CAMERA POSITION Z()

`  CALCULATE RAYCASTING USING SPARKY'S .DLL (N O T E:  IF USING GROUPS, SET THE GROUP FLAG TO 1)
   OBJECT_SELECTED=intersectObjectDBC(0,0,CAMERA POSITION X(),CAMERA POSITION Y(),CAMERA POSITION Z(),VECTOR#(0),VECTOR#(1),VECTOR#(2),0)

   UNDIM PICKOBJECTVECTOR#(2)

ENDFUNCTION OBJECT_SELECTED








`MY PICKSCREEN FUNCTION

FUNCTION PICKSCREEN(XPOINT,YPOINT,DISTANCE#)

`  CALCULATE HALF THE SCREEN WIDTH AND HEIGHT
`  SUBTRACT 1 BECAUSE POINTS START AT (0,0), NOT (1,1)
   HALFSW#=(SCREEN WIDTH()-1)
   HALFSW#=HALFSW#/2
   HALFSH#=(SCREEN HEIGHT()-1)
   HALFSH#=HALFSH#/2

`  CALCULATE THE RATIO CONSTANTS.  REMEMBER, HEIGHT CONSTANT IS ALWAYS .6
   SW#=SCREEN WIDTH()
   SH#=SCREEN HEIGHT()
   WIDTHCONSTANT#=SW#/SH#
   WIDTHCONSTANT#=.6*WIDTHCONSTANT#


`  CALCULATE 3D COORDINATE OF SCREEN POINT ASSUMING CAMERA ISN'T ROTATED AND IS AT POSITION 0,0,0
   XPOINT#=XPOINT
   YPOINT#=YPOINT
   XPOINT#=XPOINT-HALFSW#
   YPOINT#=HALFSH#-YPOINT
   XVEC#=WIDTHCONSTANT#*(XPOINT#/HALFSW#)
   YVEC#=.6*(YPOINT#/HALFSH#)
   ZVEC#=1

`  CALCULATE LENGTH FROM CAMERA POINT TO 3D SCREEN POINT
   LENGTH#=SQRT((XVEC#*XVEC#)+(YVEC#*YVEC#)+(ZVEC#*ZVEC#))

`  MAKE VECTOR A UNIT VECTOR
   XVEC#=(XVEC#/LENGTH#)
   YVEC#=(YVEC#/LENGTH#)
   ZVEC#=(ZVEC#/LENGTH#)

`  CALCULATE POINT ON VECTOR AT DESIRED DISTANCE FROM CAMERA
   XVEC#=DISTANCE#*XVEC#
   YVEC#=DISTANCE#*YVEC#
   ZVEC#=DISTANCE#*ZVEC#

`  CALULATE X-AXIS ROTATION RELATIVE TO CAMERA
   OLDY#=YVEC#
   OLDZ#=ZVEC#

   YVEC#=(OLDY#*COS(CAMERA ANGLE X()))-(OLDZ#*SIN(CAMERA ANGLE X()))
   ZVEC#=(OLDY#*SIN(CAMERA ANGLE X()))+(OLDZ#*COS(CAMERA ANGLE X()))

`  CALCULATE Y-AXIS ROTATION RELATIVE TO CAMERA
   OLDX#=XVEC#
   OLDZ#=ZVEC#

   XVEC#=(OLDX#*COS(CAMERA ANGLE Y()))+(OLDZ#*SIN(CAMERA ANGLE Y()))
   ZVEC#=(OLDZ#*COS(CAMERA ANGLE Y()))-(OLDX#*SIN(CAMERA ANGLE Y()))

`  CALCULATE Z-AXIS ROTATION RELATIVE TO CAMERA
   OLDX#=XVEC#
   OLDY#=YVEC#

   XVEC#=(OLDX#*COS(CAMERA ANGLE Z()))-(OLDY#*SIN(CAMERA ANGLE Z()))
   YVEC#=(OLDX#*SIN(CAMERA ANGLE Z()))+(OLDY#*COS(CAMERA ANGLE Z()))

`  CALCULATE THE VECTOR RELATIVE TO THE STANDARD AXIS RATHER THAN RELATIVE TO THE CAMERA
   VECTOR#(0)=XVEC#+CAMERA POSITION X()
   VECTOR#(1)=YVEC#+CAMERA POSITION Y()
   VECTOR#(2)=ZVEC#+CAMERA POSITION Z()

ENDFUNCTION

`MY OBJECT DISTANCE TO CAMERA FUNCTION
FUNCTION DISTANCETOCAM(OBJNUM)
   DISTANCE#=SQRT((OBJECT POSITION X(OBJNUM)-CAMERA POSITION X())^2+(OBJECT POSITION Y(OBJNUM)-CAMERA POSITION Y())^2+(OBJECT POSITION Z(OBJNUM)-CAMERA POSITION Z())^2)
ENDFUNCTION DISTANCE#

`SPARKY'S .DLL FUNCTIONS
function setupObjectDBC(objNum,groupNum,objectType)
    commonSetup(objNum)

    vertData = get memblock ptr(254)
    objectData = get memblock ptr(255)
    call dll 1,"setupObject",objNum,groupNum,objectType,vertData,objectData

    delete memblock 254
endfunction

function setupComplexObjectDBC(objNum,groupNum,facesPerNode)
    commonSetup(objNum)

    vertData = get memblock ptr(254)
    objectData = get memblock ptr(255)
    call dll 1,"setupComplexObject",objNum,groupNum,facesPerNode,vertData,objectData

    delete memblock 254
endfunction

function commonSetup(objNum)
    if dll exist(1)=0 then load dll "DBCcollision.dll",1
    if memblock exist(255)=0 then make memblock 255,24

    x#=object position x(objNum)
    y#=object position y(objNum)
    z#=object position z(objNum)
    angx#=object angle x(objNum)
    angy#=object angle y(objNum)
    angz#=object angle z(objNum)

    write memblock float 255,0,x#
    write memblock float 255,4,y#
    write memblock float 255,8,z#
    write memblock float 255,12,angx#
    write memblock float 255,16,angy#
    write memblock float 255,20,angz#

    position object objNum,0,0,0
    rotate object objNum,0,0,0
    make mesh from object 255,objNum
    make memblock from mesh 254,255
    delete mesh 255
    position object objNum,x#,y#,z#
    rotate object objNum,angx#,angy#,angz#
endfunction

function updateObjectDBC(objNum)
    if memblock exist(255)=0 then make memblock 255,24

    write memblock float 255,0,object position x(objNum)
    write memblock float 255,4,object position y(objNum)
    write memblock float 255,8,object position z(objNum)
    write memblock float 255,12,object angle x(objNum)
    write memblock float 255,16,object angle y(objNum)
    write memblock float 255,20,object angle z(objNum)

    objectData = get memblock ptr(255)

    call dll 1,"updateObject",objNum,objectData
endfunction

function intersectObjectDBC(objNum,groupFlag,oldx#,oldy#,oldz#,x#,y#,z#,excludeObj)
    collide=call dll(1,"intersectObject",objNum,groupFlag,oldx#,oldy#,oldz#,x#,y#,z#,excludeObj)
endfunction collide

function setObjectCollisionOnDBC(objNum)
    call dll 1,"set_object_collision_on",objNum
endfunction

function setObjectCollisionOffDBC(objNum)
    call dll 1,"set_object_collision_off",objNum
endfunction

function collisionStatusDBC(objNum)
    result=call dll(1,"collisionstatus",objNum)
endfunction result

function getStaticCollisionX()
    result#=call dll(1,"getStaticCollisionX")
endfunction result#

function getStaticCollisionY()
    result#=call dll(1,"getStaticCollisionY")
endfunction result#

function getStaticCollisionZ()
    result#=call dll(1,"getStaticCollisionZ")
endfunction result#

function getCollisionNormalX()
    result#=call dll(1,"getCollisionNormalX")
endfunction result#

function getCollisionNormalY()
    result#=call dll(1,"getCollisionNormalY")
endfunction result#

function getCollisionNormalZ()
    result#=call dll(1,"getCollisionNormalZ")
endfunction result#