Posted: 26th Mar 2003 14:10
He is my function to perform 3d object selection. It works for all camera rotations.

The first code is the function source and should be added to your project.

+ Code Snippet
Rem *** Include File: fnMousePick.dba ***
Rem Created: 26/03/2003 09:31:08

Rem Included in Project: C:\Program Files\Dark Basic Software\Dark Basic Professional\Projects\Mouse Pick\Mouse Pick.dbpro

Global vx#
Global vy#
Global vz#

Function ProjectMouse(dist#)
Remstart
ProjectMouse - Written By Jason Clogg
               based on DBv1 code snippet I created on Dark Basic Archive
               Credit to Kensupen for the vector code from his 3D Mouse Selection

               This function returns the 3d Coords of the mouse for a given distance from the camera
               the co-ords are returned in the global variables vx#,vy#, & vz#
               To perform object intersection correctly using this function you must call it twice to
               get a nearpoint for the mouse and a farpoint.

               example
                  ProjectMouse(1):sx#=vx#:sy#=vy#:sz#=vz#
                  ProjectMouse(5000):ex#=vx#:ey#=vy#:ez#=vz#
                  for check=FirstObject to LastObject
                     ObjDist#=intersect object(check,sx#,sy#,sz#,ex#,ey#,ez#)
                     if ObjDist#>0
                        ' object 'check' has been hit
                     endif
                  next check
remend
Local DKMatView As Integer
Local DKVector As Integer
Local DKLineEnd As Integer
DKVector=1
DKLineEnd=2
DKMatView=3
r=Make Matrix4(DKMatView)
r=Make Vector3(DKVector)
r=Make Vector3(DKLineEnd)

px#=(((dist#*.8)+.8)*2)/screen width()
py#=(((dist#*.6)+.6)*2)/screen height()

CAX#=camera angle x()
CAY#=camera angle y()
CAZ#=camera angle z()

CPX#=camera position x()
CPY#=camera position y()
CPZ#=camera position z()

mx#=mousex()
my#=mousey()
rem calculate forward vector for camera
X#=(mx#*px#)-((dist#*.8)+.8)
Y#=((dist#*.6)+.6)-(my#*py#)
Z#=dist#

View Matrix4 DKMatView
r#=Inverse Matrix4(DKMatView, DKMatView)

Set Vector3 DKVector, dist#*X#, dist#*Y#, dist#*Z#
Transform Coords Vector3 DKLineEnd, DKVector, DKMatView
vx#=x vector3(DKLineEnd)
vy#=y vector3(DKLineEnd)
vz#=z vector3(DKLineEnd)

res=delete vector3(DKMatView)
res=delete vector3(DKVector)
res=delete vector3(DKLineEnd)
EndFunction

Function NearestObjIntersection(FirstObject,LastObject)
Remstart
NearestObjIntersection - Written By Jason Clogg

This function returns the object number of the nearest object selected by the mouse cursor

example
   HitObj=NearestObjIntersection(firstobject,lastobject)
   if HitObj>0 then
      'Object has been hit
   endif
remend
HitObj=0
NearObjDist#=99999999
projectMouse(1):sx#=vx#:sy#=vy#:sz#=vz#
projectMouse(5000):ex#=vx#:ey#=vy#:ez#=vz#
for check=FirstObject to LastObject
rem Check intersection with each object
ObjDist#=intersect object(check,sx#,sy#,sz#,ex#,ey#,ez#)
if ObjDist#>0
   rem if intersection occurs only store object number if nearer than current nearest
   if ObjDist#0 then
   color object HitObj,rgb(255,0,0)
endif



text 0,0,"3d Object Selection Code " + str$(screen fps())+ " " + str$(HitObj)
text 0,15,"Written By Jason Clogg"
text 0,30,"Keyboard Controls"
text 0,45,"Cursor keys Rotate camera on x/y axis"
text 0,60,"'a,d' Rotate camera on z axis"
text 0,75,"mousebutton 2 and mouse the move forwards/backwards"
text 0,90,"mousebutton 1 to select object"

sync
if HitObj>0 then color object HitObj,rgb(0,255,0)

loop

end


Seems to run resonably fast, even for a few hundred objects.

Cheers,

Jason
Posted: 26th Mar 2003 14:13
The 2 sections of code appear to have merged. I will post them invividualy

First the Function

+ Code Snippet
Rem *** Include File: fnMousePick.dba ***
Rem Created: 26/03/2003 09:31:08

Rem Included in Project: C:\Program Files\Dark Basic Software\Dark Basic Professional\Projects\Mouse Pick\Mouse Pick.dbpro

Global vx#
Global vy#
Global vz#

Function ProjectMouse(dist#)
Remstart
ProjectMouse - Written By Jason Clogg
               based on DBv1 code snippet I created on Dark Basic Archive
               Credit to Kensupen for the vector code from his 3D Mouse Selection

               This function returns the 3d Coords of the mouse for a given distance from the camera
               the co-ords are returned in the global variables vx#,vy#, & vz#
               To perform object intersection correctly using this function you must call it twice to
               get a nearpoint for the mouse and a farpoint.

               example
                  ProjectMouse(1):sx#=vx#:sy#=vy#:sz#=vz#
                  ProjectMouse(5000):ex#=vx#:ey#=vy#:ez#=vz#
                  for check=FirstObject to LastObject
                     ObjDist#=intersect object(check,sx#,sy#,sz#,ex#,ey#,ez#)
                     if ObjDist#>0
                        ' object 'check' has been hit
                     endif
                  next check
remend
Local DKMatView As Integer
Local DKVector As Integer
Local DKLineEnd As Integer
DKVector=1
DKLineEnd=2
DKMatView=3
r=Make Matrix4(DKMatView)
r=Make Vector3(DKVector)
r=Make Vector3(DKLineEnd)

px#=(((dist#*.8)+.8)*2)/screen width()
py#=(((dist#*.6)+.6)*2)/screen height()

CAX#=camera angle x()
CAY#=camera angle y()
CAZ#=camera angle z()

CPX#=camera position x()
CPY#=camera position y()
CPZ#=camera position z()

mx#=mousex()
my#=mousey()
rem calculate forward vector for camera
X#=(mx#*px#)-((dist#*.8)+.8)
Y#=((dist#*.6)+.6)-(my#*py#)
Z#=dist#

View Matrix4 DKMatView
r#=Inverse Matrix4(DKMatView, DKMatView)

Set Vector3 DKVector, dist#*X#, dist#*Y#, dist#*Z#
Transform Coords Vector3 DKLineEnd, DKVector, DKMatView
vx#=x vector3(DKLineEnd)
vy#=y vector3(DKLineEnd)
vz#=z vector3(DKLineEnd)

res=delete vector3(DKMatView)
res=delete vector3(DKVector)
res=delete vector3(DKLineEnd)
EndFunction

Function NearestObjIntersection(FirstObject,LastObject)
Remstart
NearestObjIntersection - Written By Jason Clogg

This function returns the object number of the nearest object selected by the mouse cursor

example
   HitObj=NearestObjIntersection(firstobject,lastobject)
   if HitObj>0 then
      'Object has been hit
   endif
remend
HitObj=0
NearObjDist#=99999999
projectMouse(1):sx#=vx#:sy#=vy#:sz#=vz#
projectMouse(5000):ex#=vx#:ey#=vy#:ez#=vz#
for check=FirstObject to LastObject
rem Check intersection with each object
ObjDist#=intersect object(check,sx#,sy#,sz#,ex#,ey#,ez#)
if ObjDist#>0
   rem if intersection occurs only store object number if nearer than current nearest
   if ObjDist#<NearObjDist#
      NearObjDist#=ObjDist#
      HitObj=check
   endif
else
endif

next check
EndFunction HitObj
Posted: 26th Mar 2003 14:13
Now the sample project

+ Code Snippet
autocam off
backdrop on
sync rate 0
sync on

color backdrop rgb(10,10,10)

make matrix 1,1000.0,1000.0,40,40
position matrix 1,-500,0,-500


randomize timer()

`Generate random Objects for selection

for i= 10 to 300
make object box i,rnd(50)+20,rnd(20)+20,rnd(20)+1
position object i,rnd(2000)-1000,rnd(2000)-1000,rnd(2000)-1000
rotate object i,rnd(360),rnd(360),rnd(360)
color object i,rgb(0,255,0)
next i

camerax#=0
cameray#=0
cameraz#=0

position camera 0,cy#,cz#

`Main Program Loop
do
if inkey$()="a" then cameraz#=wrapvalue(cameraz#+2)
if inkey$()="d" then cameraz#=wrapvalue(cameraz#-2)
if upkey()=1 then camerax#=wrapvalue(camerax#+2)
if downkey()=1 then camerax#=wrapvalue(camerax#-2)
if leftkey()=1 then cameray#=wrapvalue(cameray#-2)
if rightkey()=1 then cameray#=wrapvalue(cameray#+2)
if mouseclick()=2
   move camera (mousey()-(screen height()/2))/-20
endif

rotate camera camerax#,cameray#,cameraz#

if mouseclick()=1
HitObj=NearestObjIntersection(10,300)
if HitObj>0 then
   color object HitObj,rgb(255,0,0)
endif



text 0,0,"3d Object Selection Code " + str$(screen fps())+ " " + str$(HitObj)
text 0,15,"Written By Jason Clogg"
text 0,30,"Keyboard Controls"
text 0,45,"Cursor keys Rotate camera on x/y axis"
text 0,60,"'a,d' Rotate camera on z axis"
text 0,75,"mousebutton 2 and mouse the move forwards/backwards"
text 0,90,"mousebutton 1 to select object"

sync
if HitObj>0 then color object HitObj,rgb(0,255,0)

loop

end



Cheers,

Jason
Posted: 26th Mar 2003 15:39
Very nice. Mind if I use it in one of my games? I'll put you in the credits then.
Posted: 26th Mar 2003 16:24
Feel free. Good to see it's of use to someone.
Posted: 26th Mar 2003 16:34
Thnx your the best
Posted: 7th Apr 2003 22:12
Hello

Apparently in 1280 by 1024 the code function no correctly.
Can you tell me why?

Sorry for my english.
Posted: 9th Apr 2003 4:14
can that be written in DB Classic?
Posted: 9th Apr 2003 14:42
No in db classic the vector3 doesn't exits

Posted: 9th Apr 2003 15:38
Excellent Jason

@Rich

- Can you make this a sticky as this feature is requested very often.
Posted: 9th Apr 2003 19:53
What's a sticky ????

Sorry for my english.

Posted: 10th Apr 2003 10:50
Jason Clogg, Thanks man! This is a perfect code. i've been looking for something like this for a long time but all i found was for objects with the same size.

Jason can i use it in my project i'll put you in the credits.

(Sorry for the bad English)
Posted: 10th Apr 2003 13:05
Hmm. I am also want to be in the credits. This code based on my snippet.
http://www.realgametools.net/forums/index.php?board=8;action=display;threadid=10236
http://www.realgametools.net/forums/index.php?board=3;action=display;threadid=11626
Posted: 11th Apr 2003 13:42
sweet!! me too. Perfect for my rts game!
Posted: 11th Apr 2003 22:16
@delorme

A sticky is a topic which always stays at the top of the forums - these are used for important announcements or issues which come up often.
Posted: 12th Apr 2003 9:14
DMiTR0S thank you as well. I see you have done allot of work on your code, wich Jason used to make this own. maybe whitout you this wasn't possible.

I will also put you in the credits. but the firs beta of my project will be out not sooner then few months.
i'll post a linke and more information about it when i'll be closer
to finshe the first beta.

(Sorry for the bad English)
Posted: 12th Apr 2003 9:42
@Rob K
Thank's for your explain

@DMiTR0S
Your code is code in 1024*768 but work not correctly in 1280*1024 can you help me so that the code work correctly in 1280*1024

Sorry for my english.

Posted: 12th Apr 2003 11:35
delorme it works on 1280x1024, but you have to change 4 lines of code
in Function ProjectMouse(Dist#): (==> means change to) :-s

px#=(((dist#*.8)+.8)*2)/screen width()
==> px#=(((dist#*.752)+.752)*2)/screen width()

py#=(((dist#*.6)+.6)*2)/screen height()
==> py#=(((dist#*.599)+.599)*2)/screen height()

X#=(mx#*px#)-((dist#*.8)+.8)
==> X#=(mx#*px#)-((dist#*.752)+.752)

Y#=((dist#*.6)+.6)-(my#*py#)
==> Y#=((dist#*.599)+.599)-(my#*py#)
Posted: 12th Apr 2003 16:42
Ok VERY THANK'S x-d

For DMiTROS
in 1280*1024 the value is

DKAspectratio#=1.5
not 1.33333333333
...
DKCameraspaceX#=(-0.8321*DKNMouseX#*DKAspectratio#)*DKMaxY#
not -1.0

Thank's for your help
Posted: 12th Apr 2003 17:06
AspectRatio#=(Screen Width()*1.0)/(Screen Height()*1.0)