Hey there, I don't think I've seen you around lately. Good to see you.
I've been breaking my head over this for the last 48 hours, and I think I've come up with a workable solution. Of course, I don't know if you still need this, but it was a good exercise for me nonetheless.
set display mode 1024,768,32,1
sync on
`Custom Vector and Matrix types because DBPro's native commands suck
type Vector
x as float
y as float
z as float
w as float
endtype
type Matrix
_11 as float : _12 as float : _13 as float : _14 as float
_21 as float : _22 as float : _23 as float : _24 as float
_31 as float : _32 as float : _33 as float : _34 as float
_41 as float : _42 as float : _43 as float : _44 as float
endtype
`v and m are used for function returns. Any function needing to return a Vector or a Matrix fills v or m.
global v as Vector
global m as Matrix
make object cube 1,6
make object cube 2,1
hide object 2
make matrix 1,100,100,10,10
position matrix 1,-50,-3,-50
Radius#=25.0
`UpVec as Vector
ObjectPos as Vector `Camera position in object space
WorldPos as Vector `Camera position in world space
`SetVec(0,1,0,1) : UpVec=v
SetVec(0,0,-Radius#,1) : ObjectPos=v
OldObjectToWorld as Matrix `Transforms from object space to world space (before the cube turns at all)
NewObjectToWorld as Matrix `Transforms from object space to world space (after the cube turns)
NewWorldToObject as Matrix `Transforms from world space to object space (after the cube turns)
WorldToView as Matrix `I think you get the idea of these matrices by now...
ViewToWorld as Matrix
MouseRotation as Matrix `Matrix representing the rotation caused by the mouse
do
set cursor 0,0
print screen fps()
mmx=mousemovex()
mmy=mousemovey()
`Get WorldToView Matrix
CreateXRotationMatrix(-camera angle x(0)) : WorldToView=m
CreateYRotationMatrix(-camera angle y(0)) : MultiplyMatrices(WorldToView,m) : WorldToView=m
`Get ViewToWorld Matrix
CreateYRotationMatrix(camera angle y(0)) : ViewToWorld=m
CreateXRotationMatrix(camera angle x(0)) : MultiplyMatrices(ViewToWorld,m) : ViewToWorld=m
`Get OldObjectToWorld Matrix
CreateYRotationMatrix(object angle y(1)) : OldObjectToWorld=m
CreateXRotationMatrix(object angle x(1)) : MultiplyMatrices(OldObjectToWorld,m) : OldObjectToWorld=m
`Rotate object based on input
xrotate object 1,wrapvalue(object angle x(1)+2.5*(upkey()-downkey()))
yrotate object 1,wrapvalue(object angle y(1)+2.5*(rightkey()-leftkey()))
`Get NewObjectToWorld Matrix
CreateYRotationMatrix(object angle y(1)) : NewObjectToWorld=m
CreateXRotationMatrix(object angle x(1)) : MultiplyMatrices(NewObjectToWorld,m) : NewObjectToWorld=m
`Get NewWorldToObject Matrix
CreateXRotationMatrix(-object angle x(1)) : NewWorldToObject=m
CreateYRotationMatrix(-object angle y(1)) : MultiplyMatrices(NewWorldToObject,m) : NewWorldToObject=m
`While holding the right mouse button,
if mouseclick()=2
`Get MouseRotation Matrix
CreateYRotationMatrix(mmx/10.0) : MouseRotation=m
CreateXRotationMatrix(mmy/10.0) : MultiplyMatrices(MouseRotation,m) : MouseRotation=m
`Take the camera's object space position and bring it into world space
TransformVec(OldObjectToWorld,ObjectPos)
`Take the world space position and bring it into view space
TransformVec(WorldToView,v) `The vector should now contain the coordinates (0,0,-Radius#)
`Do the mouse rotation
TransformVec(MouseRotation,v)
`Take the new view coordinates and bring them back into world space
TransformVec(ViewToWorld,v) : WorldPos=v
`Take the new world space coordinates and bring them into object space (after the cube rotation was applied)
TransformVec(NewWorldToObject,v) : ObjectPos=v
`If not holding the right mouse button,
else
`Just rotate the camera's position along with the object, by transforming the camera's object space position into world space using the rotated cube's transform matrix
TransformVec(NewObjectToWorld,ObjectPos) : WorldPos=v
endif
`Adjust the camera's world space position by the object's
SetVec(object position x(1),object position y(1),object position z(1),1) : AddVec(WorldPos,v) : WorldPos=v
position camera 0,WorldPos.x,WorldPos.y,WorldPos.z
`Using point camera causes the camera to remain right-side-up at all times. I might want to fool around with getting a custom up vector working.
point camera 0,object position x(1),object position y(1),object position z(1)
sync
loop
end
`Some Vector/Matrix manipulation commands
function SetVec(x as float,y as float,z as float,w as float)
v.x=x : v.y=y : v.z=z : v.w=w
endfunction
function AddVec(vec1 as Vector,vec2 as Vector)
v.x=vec1.x+vec2.x
v.y=vec1.y+vec2.y
v.z=vec1.z+vec2.z
v.w=1.0
endfunction
function MultiplyMatrices(mat1 as Matrix,mat2 as Matrix)
m._11=mat1._11*mat2._11+mat1._12*mat2._21+mat1._13*mat2._31+mat1._14*mat2._41
m._12=mat1._11*mat2._12+mat1._12*mat2._22+mat1._13*mat2._32+mat1._14*mat2._42
m._13=mat1._11*mat2._13+mat1._12*mat2._23+mat1._13*mat2._33+mat1._14*mat2._43
m._14=mat1._11*mat2._14+mat1._12*mat2._24+mat1._13*mat2._34+mat1._14*mat2._44
m._21=mat1._21*mat2._11+mat1._22*mat2._21+mat1._23*mat2._31+mat1._24*mat2._41
m._22=mat1._21*mat2._12+mat1._22*mat2._22+mat1._23*mat2._32+mat1._24*mat2._42
m._23=mat1._21*mat2._13+mat1._22*mat2._23+mat1._23*mat2._33+mat1._24*mat2._43
m._24=mat1._21*mat2._14+mat1._22*mat2._24+mat1._23*mat2._34+mat1._24*mat2._44
m._31=mat1._31*mat2._11+mat1._32*mat2._21+mat1._33*mat2._31+mat1._34*mat2._41
m._32=mat1._31*mat2._12+mat1._32*mat2._22+mat1._33*mat2._32+mat1._34*mat2._42
m._33=mat1._31*mat2._13+mat1._32*mat2._23+mat1._33*mat2._33+mat1._34*mat2._43
m._34=mat1._31*mat2._14+mat1._32*mat2._24+mat1._33*mat2._34+mat1._34*mat2._44
m._41=mat1._41*mat2._11+mat1._42*mat2._21+mat1._43*mat2._31+mat1._44*mat2._41
m._42=mat1._41*mat2._12+mat1._42*mat2._22+mat1._43*mat2._32+mat1._44*mat2._42
m._43=mat1._41*mat2._13+mat1._42*mat2._23+mat1._43*mat2._33+mat1._44*mat2._43
m._44=mat1._41*mat2._14+mat1._42*mat2._24+mat1._43*mat2._34+mat1._44*mat2._44
endfunction
function TransformVec(mat as Matrix,vec as Vector)
v.x=vec.x*mat._11+vec.y*mat._12+vec.z*mat._13+vec.w*mat._14
v.y=vec.x*mat._21+vec.y*mat._22+vec.z*mat._23+vec.w*mat._24
v.z=vec.x*mat._31+vec.y*mat._32+vec.z*mat._33+vec.w*mat._34
v.w=vec.x*mat._41+vec.y*mat._42+vec.z*mat._43+vec.w*mat._44
endfunction
function CreateXRotationMatrix(ang as float)
m._11=1.0 : m._12=0.0 : m._13=0.0 : m._14=0.0
m._21=0.0 : m._22=cos(ang) : m._23=-sin(ang) : m._24=0.0
m._31=0.0 : m._32=sin(ang) : m._33=cos(ang) : m._34=0.0
m._41=0.0 : m._42=0.0 : m._43=0.0 : m._44=1.0
endfunction
function CreateYRotationMatrix(ang as float)
m._11=cos(ang) : m._12=0.0 : m._13=sin(ang) : m._14=0.0
m._21=0.0 : m._22=1.0 : m._23=0.0 : m._24=0.0
m._31=-sin(ang) : m._32=0.0 : m._33=cos(ang) : m._34=0.0
m._41=0.0 : m._42=0.0 : m._43=0.0 : m._44=1.0
endfunction
`function CreateZRotationMatrix(ang as float)
` m._11=cos(ang) : m._12=-sin(ang) : m._13=0.0 : m._14=0.0
` m._21=sin(ang) : m._22=cos(ang) : m._23=0.0 : m._24=0.0
` m._31=0.0 : m._32=0.0 : m._33=1.0 : m._34=0.0
` m._41=0.0 : m._42=0.0 : m._43=0.0 : m._44=1.0
`endfunction
My solution uses a lot of complex math, but it works. I kinda wish there was an easier solution. If you need help understanding anything please ask.
Edit:
Some things I forgot to mention:
This demo uses the
point camera command, which will always keep the camera right-side-up, so while pitching the cube down, the camera will turn itself around after it reaches the very top of its orbit. That might be a problem if you want true free-flight. I think I might mess around with trying to impose my own up vector on the camera to correct this, but the native DBPro command set makes this very difficult. We'll see.
...I thought I had more things, but I'm going blank right now... I'll post back later if I remember.
Oh, and if someone has a way to do the same thing, while avoiding all that nasty math,
please share.
Let me know if this is at least close to what you were going for.