Success!
Play around with this:
set display mode 1024,768,32,1
sync on
hide mouse
autocam off
`Type for returning angles
type Euler
x as float
y as float
z as float
endtype
global e as Euler
`For conversions between degrees and radians
#constant DEGTORAD 3.14159265/180.0
`The player
make object box 1,4,2,8
`Axes - These will always stay at the origin
make object box 2,10,0.05,0.05 : color object 2,0xFFFF0000
make object box 3,0.05,10,0.05 : color object 3,0xFF00FF00
make object box 4,0.05,0.05,10 : color object 4,0xFF0000FF
`Random cubes
for a=5 to 20
make object cube a,5
rotate object a,rnd(360),rnd(360),rnd(360)
position object a,rnd(100)-50,rnd(100)-50,rnd(100)-50
next a
PlayerVelocity as float
do
set cursor 0,0
print "Spacebar - Reorient"
print "W - Forward"
print "S - Backward"
`Reorient the world when the spacebar is pressed
if spacekey()=1 and SpaceHold=0
SpaceHold=1
ReorientWorld(1,5,20) `Reorient objects 5 - 20 around 1
endif
if spacekey()=0 and SpaceHold=1 then SpaceHold=0
`Mouse look
xrotate object 1,wrapvalue(object angle x(1)+mousemovey()/3.0)
yrotate object 1,wrapvalue(object angle y(1)+mousemovex()/3.0)
`W/S = Forward/Backward
if keystate(17) then inc PlayerVelocity,0.1
if keystate(31) then dec PlayerVelocity,0.1
`Cap velocity
if abs(PlayerVelocity)>1.4 then PlayerVelocity=Sign(PlayerVelocity)*1.4
`Apply Velocity
move object 1,PlayerVelocity
`Reduce Velocity
PlayerVelocity=0.95*PlayerVelocity
`Deal with camera
CameraFollowObject(0,1,0,4,-15,20,0,0)
sync
loop
end
function ReorientWorld(Center,StartObject,EndObject)
InverseWorld =1
World =2
TempMatrix =3
TempVector =4
a=make matrix4(InverseWorld)
a=make matrix4(World)
a=make matrix4(TempMatrix)
a=make vector4(TempVector)
`Apparently multiply matrix4 takes arguments in transformation order and not in the correct mathmatical order...
`I spent a while doing the same thing as below, but exactly backwards because it makes mathmatical sense. Oh DBPro...
`Build the inverse world matrix of the center object (the player)
rotate x matrix4 World,object angle x(Center)*DEGTORAD
rotate y matrix4 TempMatrix,object angle y(Center)*DEGTORAD : multiply matrix4 World,World,TempMatrix
rotate z matrix4 TempMatrix,object angle z(Center)*DEGTORAD : multiply matrix4 World,World,TempMatrix
translate matrix4 TempMatrix,object position x(Center),object position y(Center),object position z(Center)
multiply matrix4 World,World,TempMatrix
a=inverse matrix4(InverseWorld,World)
`Just put the player at the center of the world. It's easier than actually doing the matrix transform for the same answer.
position object Center,0,0,0
rotate object Center,0,0,0
for Object=StartObject to EndObject
`Build the object's world matrix and apply the inverse transform to it
rotate x matrix4 World,object angle x(Object)*DEGTORAD
rotate y matrix4 TempMatrix,object angle y(Object)*DEGTORAD : multiply matrix4 World,World,TempMatrix
rotate z matrix4 TempMatrix,object angle z(Object)*DEGTORAD : multiply matrix4 World,World,TempMatrix
translate matrix4 TempMatrix,object position x(Object),object position y(Object),object position z(Object)
multiply matrix4 World,World,TempMatrix
multiply matrix4 World,World,InverseWorld
`The following is my solution to apply your own world matrix to an object:
`Transform an empty vector to get the new position
set vector4 TempVector,0,0,0,1
transform vector4 TempVector,TempVector,World
position object Object,x vector4(TempVector),y vector4(TempVector),z vector4(TempVector)
`Get euler angles out of the new world matrix
ExtractAngles(World)
rotate object Object,e.x,e.y,e.z
next Object
a=delete matrix4(InverseWorld)
a=delete matrix4(World)
a=delete matrix4(TempMatrix)
a=delete vector4(TempVector)
endfunction
function ExtractAngles(mat)
e.y=-asin(get matrix4 element(mat,2))
if abs(get matrix4 element(mat,2))>0.999999 `Floating point inaccuracies scare me
e.x=atanfull(get matrix4 element(mat,4),get matrix4 element(mat,8))
e.z=0
exitfunction
endif
e.x=atanfull(get matrix4 element(mat,6),get matrix4 element(mat,10))
e.z=atanfull(get matrix4 element(mat,1),get matrix4 element(mat,0))
endfunction
function Sign(x as float)
if x>0 then exitfunction 1
if x<0 then exitfunction -1
endfunction 0
function CameraFollowObject(Camera,Object,FollowX#,FollowY#,FollowZ#,XAng#,Yang#,ZAng#)
position camera Camera,object position x(Object),object position y(Object),object position z(Object)
set camera to object orientation Camera,Object
turn camera right Camera,90
move camera FollowX#
pitch camera up Camera,90
move camera FollowY#
pitch camera down Camera,90
turn camera left Camera,90
move camera FollowZ#
pitch camera down Camera,XAng#
turn camera right Camera,YAng#
roll camera left Camera,ZAng#
endfunction
If you press the spacebar, the entire scene will reorient around the player, who will be placed and oriented at the origin. Twas no easy task dealing with DBPro matrices. I hate them.
I hope this helps, and feel free to ask about anything. Now you can adapt this to do whatever object switching you had in mind.
Edit: You can see that the lighting on all of the objects is a little strange, but that's because the lights in the scene don't get reoriented with the objects. Make sure to do that.