Ok. I worked on a object selection function a long time ago. I thought I had it working and when I tried to use it in a program I'm currently working on. I discovered there were errors in it. I got it to work if the X Y and Z coordinates are at 0. The angles can be whatever, but the moment its x y or z coordinates change, it stops working. I lost the page that I had gotten my information for the rotation matrix from and now all I have found decently is this.
http://en.wikipedia.org/wiki/Rotation_matrix
Here's a knockup program I put the function in. I know its not great.
sync on
sync rate 0
cls
autocam off
make object sphere 100,100
color object 100,rgb(255,255,0)
make object plain 200,1,1
lock object on 200
ghost object on 200
load image "system icons/selection.bmp",200
texture object 200,200
for o=1 to 50
make object sphere o,10
position object o,rnd(1000)-500,rnd(1000)-500,rnd(1000)-500
set object rotation zyx o
setupobjectdbc(o,1,0)
next o
nmaxspin#=-3.0 : pmaxspin#=3.0
do
mx=mousex() : my=mousey()
if keystate(17)=1 then position camera camera position x(),camera position y()+.001,camera position z()
if keystate(31)=1 then position camera camera position x(),camera position y()-.001,camera position z()
if keystate(30)=1 then position camera camera position x()-.001,camera position y(),camera position z()
if keystate(32)=1 then position camera camera position x()+.001,camera position y(),camera position z()
if clicked=0
if mouseclick()=1
mx1=mx
my1=my
clicked=1
endif
if mx=0 or mx=639
if mx=0
if xturn#>nmaxspin# then dec xturn#,.5
endif
if mx=639
if xturn#<pmaxspin# then inc xturn#,.5
endif
yrotate camera wrapvalue(camera angle y()+xturn#)
else
xturn#=0
endif
if my=0 or my=479
if my=0
if camera angle x()<315 and camera angle x()>310
yturn#=0
else
if yturn#>nmaxspin# then dec yturn#,.5
endif
endif
if my=479
if camera angle x()>45 and camera angle x()<50
yturn#=0
else
if yturn#<pmaxspin# then inc yturn#,.5
endif
endif
xrotate camera wrapvalue(camera angle x()+yturn#)
else
yturn#=0
endif
else
if mouseclick()=0
mx2=mx
my2=my
clicked=0
if mx1=mx2 and my1=my2
collide=pickobject(mx1,my1,1000,1,1,0)
if collide>0
for o=1 to 50
if o=collide
color object o,rgb(255,0,0)
else
color object o,rgb(255,255,255)
endif
next o
else
for o=1 to 50
color object o,rgb(255,255,255)
next o
endif
else
if mx1>mx2
if my1>my2
for o=1 to 50
if object screen x(o)<=mx1 and object screen x(o)>=mx2 and object screen y(o)<=my1 and object screen y(o)>=my2
color object o,rgb(255,0,0)
else
color object o,rgb(255,255,255)
endif
next o
else
for o=1 to 50
if object screen x(o)<=mx1 and object screen x(o)>=mx2 and object screen y(o)<=my2 and object screen y(o)>=my1
color object o,rgb(255,0,0)
else
color object o,rgb(255,255,255)
endif
next o
endif
else
if my1>my2
for o=1 to 50
if object screen x(o)<=mx2 and object screen x(o)>=mx1 and object screen y(o)<=my1 and object screen y(o)>=my2
color object o,rgb(255,0,0)
else
color object o,rgb(255,255,255)
endif
next o
else
for o=1 to 50
if object screen x(o)<=mx2 and object screen x(o)>=mx1 and object screen y(o)<=my2 and object screen y(o)>=my1
color object o,rgb(255,0,0)
else
color object o,rgb(255,255,255)
endif
next o
endif
endif
endif
endif
line mx1,my1,mx1,my
line mx1,my1,mx,my1
line mx,my1,mx,my
line mx1,my,mx,my
`This section is just getting it to work with a 3d object instead of a 2d selection box
remstart
if mx>mx1
if 480-my>480-my1
scale object 200,(mx-mx1)*100,((480-my)-(480-my1))*100,100
position object 200,(mx1-320)+((mx-mx1)/2),((480-my1)-240)+(((480-my)-(480-my1))/2),400
else
scale object 200,(mx-mx1)*100,((480-my1)-(480-my))*100,100
position object 200,(mx1-320)+((mx-mx1)/2),((480-my)-240)+(((480-my1)-(480-my))/2),400
endif
else
if 480-my>480-my1
scale object 200,(mx-mx1)*100,((480-my)-(480-my1))*100,100
position object 200,(mx-320)+((mx1-mx)/2),((480-my1)-240)+(((480-my)-(480-my1))/2),400
else
scale object 200,(mx-mx1)*100,((480-my1)-(480-my))*100,100
position object 200,(mx-320)+((mx1-mx)/2),((480-my)-240)+(((480-my1)-(480-my))/2),400
endif
endif
remend
endif
timesync(10)
loop
function pickobject(mx,my,distance,num,flag,exclude)
cax#=camera angle x()
cay#=camera angle y()
cx#=camera position x()
cy#=camera position y()
cz#=camera position z()
fov#=62
my=screen height()-my
xdist#=(screen width()/2)/tan(fov#/2)
ydist#=(screen height()/2)/tan(fov#/2)
xwidth#=(mx-(screen width()/2))/1.15
ywidth#=(my-(screen height()/2))/1.4
yang#=atanfull(ydist#,ywidth#)
ypos#=((cy#+((ydist#+distance)/tan(yang#)))*cos(cax#))+((cz#+distance)*(-1*sin(cax#)))
zpos#=((cy#+((ydist#+distance)/tan(yang#)))*sin(cax#))+((cz#+distance)*cos(cax#))
xang#=atanfull(xdist#,xwidth#)
xpos#=((cx#+((xdist#+distance)/tan(xang#)))*cos(cay#))+(zpos#*sin(cay#))
zpos#=((cx#+((xdist#+distance)/tan(xang#)))*(-1*sin(cay#)))+(zpos#*cos(cay#))
object=intersectObjectDBC(num,flag,cx#,cy#,cz#,xpos#,ypos#,zpos#,exclude)
endfunction object
function timesync(time)
a=timer()
if a-b>=time
b=timer()
sync
endif
endfunction
`~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`=================================================================================================================
`Sparky's Collision Commands
`=================================================================================================================
`~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
remstart
Commands:
setupObjectDBC(<objNum>,<GroupNum>,<Collision Type>)
-objNum: the object you want to setup
-groupNum: the group that you want this object to belong to
if you're not using groups then this value is ignored
-collisionType: sets the type of collision to use with this object
0 - polygon collision, will check with every polygon in the object
1 - sphere collision, will create an ellipse around the object and check collisions with that
2 - box collision, will create a box around the object for collisions.
Mesh 255, memblock 255 and memblock 254 must not be in use.
This command sets up an object for collision, need only be called once for each object.
this command will also work when the object has been scaled before calling it
but any further scaling of the object will not be updated in the collision (not even with update object)
setupComplexObjectDBC(<objNum>,<GroupNum>,<FacesPerNode>)
-objNum: the object you want to setup
-groupNum: the group that you want this object to belong to
if you're not using groups then this value is ignored
-FacesPerNode: sets the maximum number of faces per tree node, usually the smaller this value the better the performance
but I'll give you the option of changing this value to see if another value works better for your object.
If you are unsure of this option just use a value of 2.
Mesh 255, memblock 255 and memblock 254 must not be in use.
almost exactly the same as setup object except this command will setup optimized polygon collision on a
complex (high poly) object so that you get much better performance for these types of object.
realistically you probably won't notice any difference between this and normal polygon collision
for objects of less than 30-40 polys, but higher polycounts definately benifit from higher performance.
You can think of it as splitting the object up into little bits, of size specified by facesPerNode,
and only checking collision with sections near the ray, therefore cutting out alot of polygons.
updateObjectDBC(<objNum>)
-objNum: the object you want to update
memblock 255 must not be in use.
Will update the collision data with the object's new position and rotation.
Should be called for any object that is changed before a collision
- for example if you want to move an object and check collision, move agian
and check collision again, then update should be called after both moves.
however, if you move an object, move it again, then check collision, you only
need to call the update method after the second move.
intersectObjectDBC(<obj/groupNum>,<GroupFlag>,<oldx>,<oldy>,<oldz>,<x>,<y>,<z>,<excludeObj>)
-obj/groupNum: the object or group you want to check for collision use 0 for all objects or groups
-GroupFlag: set this to 0 if you want to work with objects or 1 if you want to work with groups
-oldx...z: the start and end points of the ray to check.
-excludeObj: an object to exclude from the collision check (excludes a single object from both
object and group checks)
returns: if checking groups or all objects then the object number collided with is returned
if checking a specific object then a 1 is returned if a collision occured.
in either case, returns 0 if no collision occured.
will check if the ray starting at oldx#,oldy#,oldz# and ending at
x#,y#,z# collides with the specified object or group (obj=0 for all).
does not collide with backfaces, will return the number of the object
hit first, or 0 for no collision.
setObjectCollisionOffDBC(<objNum>)
-objNum: the object you want to turn off collision.
turns off collision with this object in both object and group collisions.
setObjectCollisionOnDBC(<objNum>)
-objNum: the object you want to turn on collision.
turns on collision with this object in both object and group collisions.
the default setting from setup object is ON.
collisionStatusDBC(<objNum>)
-objNum: the object you want to know the status of.
returns the current collision setting for this object, 1 for on, 0 for off.
getStaticCollisionX()
returns the x co-ordinate of actual collision point
getStaticCollisionY()
returns the y co-ordinate of actual collision point
getStaticCollisionZ()
returns the z co-ordinate of actual collision point
getCollisionNormalX()
returns the x component of the collision normal
getCollisionNormalY()
returns the y component of the collision normal
getCollisionNormalZ()
returns the z component of the collision normal
getCollisionBounceX()
returns the x component of the bounce vector
getCollisionBounceY()
returns the y component of the bounce vector
getCollisionBounceZ()
returns the z component of the bounce vector
The bounce vector is the vector (like the normal) representing the direction
the ray would end up if it bounced off the collision point (like a bullet ricohet)
remend
function LoadSparkys()
load dll "DBCollision.dll", 1
endfunction
function setupObjectDBC(objNum,groupNum,objectType)
commonSetup(objNum)
vertData = get memblock ptr(3)
objectData = get memblock ptr(2)
call dll 1,"setupObject",objNum,groupNum,objectType,vertData,objectData
delete memblock 3
endfunction
function setupComplexObjectDBC(objNum,groupNum,facesPerNode)
commonSetup(objNum)
vertData = get memblock ptr(3)
objectData = get memblock ptr(2)
call dll 1,"setupComplexObject",objNum,groupNum,facesPerNode,vertData,objectData
delete memblock 3
endfunction
function commonSetup(objNum)
if dll exist(1)=0 then load dll "DBCcollision.dll",1
if memblock exist(2)=0 then make memblock 2,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 2,0,x#
write memblock float 2,4,y#
write memblock float 2,8,z#
write memblock float 2,12,angx#
write memblock float 2,16,angy#
write memblock float 2,20,angz#
position object objNum,0,0,0
rotate object objNum,0,0,0
make mesh from object 2,objNum
make memblock from mesh 3,2
delete mesh 2
position object objNum,x#,y#,z#
rotate object objNum,angx#,angy#,angz#
endfunction
function updateObjectDBC(objNum)
if memblock exist(2)=0 then make memblock 2,24
write memblock float 2,0,object position x(objNum)
write memblock float 2,4,object position y(objNum)
write memblock float 2,8,object position z(objNum)
write memblock float 2,12,object angle x(objNum)
write memblock float 2,16,object angle y(objNum)
write memblock float 2,20,object angle z(objNum)
objectData = get memblock ptr(2)
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#
Here's the function. Please help. the section I'm concerned with is the xpos#=code : ypos#=code : zpos#=code
function pickobject(mx,my,distance,num,flag,exclude)
cax#=camera angle x()
cay#=camera angle y()
cx#=camera position x()
cy#=camera position y()
cz#=camera position z()
fov#=62
my=screen height()-my
xdist#=(screen width()/2)/tan(fov#/2)
ydist#=(screen height()/2)/tan(fov#/2)
xwidth#=(mx-(screen width()/2))/1.15
ywidth#=(my-(screen height()/2))/1.4
yang#=atanfull(ydist#,ywidth#)
ypos#=((cy#+((ydist#+distance)/tan(yang#)))*cos(cax#))+((cz#+distance)*(-1*sin(cax#)))
zpos#=((cy#+((ydist#+distance)/tan(yang#)))*sin(cax#))+((cz#+distance)*cos(cax#))
xang#=atanfull(xdist#,xwidth#)
xpos#=((cx#+((xdist#+distance)/tan(xang#)))*cos(cay#))+(zpos#*sin(cay#))
zpos#=((cx#+((xdist#+distance)/tan(xang#)))*(-1*sin(cay#)))+(zpos#*cos(cay#))
object=intersectObjectDBC(num,flag,cx#,cy#,cz#,xpos#,ypos#,zpos#,exclude)
endfunction object
EDIT:
Nvm, got it. It was a real simple solution although i'm not sure how it worked.
function pickobject(mx,my,distance,num,flag,exclude)
cax#=camera angle x()
cay#=camera angle y()
cx#=camera position x()
cy#=camera position y()
cz#=camera position z()
fov#=62
my=screen height()-my
xdist#=(screen width()/2)/tan(fov#/2)
ydist#=(screen height()/2)/tan(fov#/2)
xwidth#=(mx-(screen width()/2))/1.15
ywidth#=(my-(screen height()/2))/1.4
yang#=atanfull(ydist#,ywidth#)
ypos#=(((ydist#+distance)/tan(yang#))*cos(cax#))+(distance*(-1*sin(cax#)))
zpos#=(((ydist#+distance)/tan(yang#))*sin(cax#))+(distance*cos(cax#))
xang#=atanfull(xdist#,xwidth#)
xpos#=(((xdist#+distance)/tan(xang#))*cos(cay#))+(zpos#*sin(cay#))
zpos#=(((xdist#+distance)/tan(xang#))*(-1*sin(cay#)))+(zpos#*cos(cay#))
xpos#=xpos#+cx#
ypos#=ypos#+cy#
zpos#=zpos#+cz#
object=intersectObjectDBC(num,flag,cx#,cy#,cz#,xpos#,ypos#,zpos#,exclude)
endfunction object