Alright, well there was a problem I encountered while trying to get the sphere to rotate like I got the panels to. For the panels, I rotated their centers in World space every time, but with an object like a sphere, any transformations done on its vertices are done in Object space. One way I got around this was to never rotate the actual object, but to treat each vertex of the sphere like a separate point in World space by editing vertex data in a mesh I made of the sphere. Then I'd switch out the root limb of the object for the edited sphere mesh. Of course, if you wanted the camera to move at all, you'd have to transform everything into View space and then rotate each vertex. It gets a little complicated.
Actually, I'm curious how you took the 3D coordinates and turned them into 2D coordinates. The first thing that comes to mind is touching DBPro's icky vectors and getting the view and projection matrices to work on it. We could both do some learning.
Here's an example demonstrating how to edit the vertex data of the sphere to get it to rotate the way we want it to:
set display mode 1024,768,32,1
sync on
`Create Vector and Matrix types because DBPro Vectors and Matrices 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
`To get around a DBPro limitation...
`Global return variables
global v as Vector
global m as Matrix
`Create types for the clickable surfaces and the center that controls it all
type Panel
Obj as integer
Pos as Vector
endtype
type RotatingSphere
Vel as Vector
Deceleration as float
endtype
`Texture constants for the panels
#constant NORMAL_IMG 1
#constant HOVER_IMG 2
#constant CLICK_IMG 3
`Create the textures for the panels
create bitmap 1,10,10
ink rgb(255,128,128),0
box 0,0,10,10
get image NORMAL_IMG,0,0,1,1
ink rgb(255,64,64),0
box 0,0,10,10
get image HOVER_IMG,0,0,1,1
ink rgb(255,0,0),0
box 0,0,10,10
get image CLICK_IMG,0,0,1,1
delete bitmap 1
ink rgb(255,255,255),0
`Setup an empty array to contain any number of panels
dim Panels(0) as Panel : empty array Panels(0)
#constant PANEL_COUNT 5
`Temporary matrix for intermediate transformations
temp as Matrix
for Panel=0 to PANEL_COUNT-1
array insert at bottom Panels(0)
Panels(Panel).Obj=Panel+1
CreateYRotationMatrix(rnd(360)) : temp=m
CreateXRotationMatrix(rnd(360)) : MultiplyMatrices(temp,m)
`m now contains a matrix that will transform a vector around both the X and Y axes
SetVec(0,0,3,1) : TransformVec(m,v)
Panels(Panel).Pos=v
`Actually setup the new panel object
make object plane Panels(Panel).Obj,0.5,0.5
texture object Panels(Panel).Obj,NORMAL_IMG
position object Panels(Panel).Obj,v.x,v.y,v.z
next a
`Setup controlling sphere
Sphere as RotatingSphere
SetVec(0,0,0,1) : Sphere.Vel=v
Sphere.Deceleration=0.95
`...and the object for the sphere
make object sphere 100,3,30,30
set object wireframe 100,1
`Create a mesh containing the sphere's data. We'll transform the vertices of the mesh in World space, and then switch this
`mesh in for the sphere object's root limb. No one will ever know the difference....
make mesh from object 1,100
lock vertexdata for mesh 1
VertexCount=get vertexdata vertex count()
position camera 0,0,0,-7 : point camera 0,0,0,0
do
set cursor 0,0
print screen fps()
`Apply the deceleration by multiplying the sphere's rotational velocities by the deceleration factor
ScaleVec(Sphere.Vel,Sphere.Deceleration)
Sphere.Vel=v
`Constantly clear out mousemovex() and mousemovey() even when the values aren't being used. Otherwise, you'll just
`get a really big movement whenever you do use them.
mmx#=mousemovex()
mmy#=mousemovey()
`If either the right or the middle mouse button is down, apply the movement to the sphere's velocity
if mouseclick()&&0x06
dec Sphere.Vel.x,mmy#/30
dec Sphere.Vel.y,mmx#/30
endif
`Create a matrix to transform the panel positions according to the sphere's new velocity. The matrix is in m.
CreateYRotationMatrix(Sphere.Vel.y) : temp=m
CreateXRotationMatrix(Sphere.Vel.x) : MultiplyMatrices(temp,m)
`Get the panel that's under the cursor
UnderCursor=pick object(mousex(),mousey(),1,PANEL_COUNT)
for Panel=0 to PANEL_COUNT-1
`Put the panel in its new place
v=Panels(Panel).Pos
TransformVec(m,v) : Panels(Panel).Pos=v
position object Panels(Panel).Obj,v.x,v.y,v.z
`Handle panel texturing (normal, hover, or click).
texture object Panels(Panel).Obj,NORMAL_IMG
if UnderCursor=Panels(Panel).Obj
texture object Panels(Panel).Obj,HOVER_IMG
`If the left mouse button is down, the panel was clicked on
if mouseclick()&&0x01 then texture object Panels(Panel).Obj,CLICK_IMG
endif
`Draw a line from the center of the panel to the center of the sphere
LineBetween(Panels(Panel).Obj,100)
next Panel
`Transform all of the vertices in the sphere and then switch out the mesh
for Vertex=0 to VertexCount-1
v.x=get vertexdata position x(Vertex)
v.y=get vertexdata position y(Vertex)
v.z=get vertexdata position z(Vertex)
v.w=1.0
TransformVec(m,v)
set vertexdata position Vertex,v.x,v.y,v.z
next Vertex
change mesh 100,0,1
sync
loop
end
`A bunch of Vector and Matrix functions I wrote a while back to deal with DBPro's lack of good vectors
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 ScaleVec(vec as Vector,scale as float)
v.x=vec.x*scale
v.y=vec.y*scale
v.z=vec.z*scale
v.w=1.0
endfunction
`Just multiplies a matrix by a vector
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 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
`Rotates around the X Axis
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
`Rotates around the Y Axis
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
`Not needed
`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
function LineBetween(Obj1,Obj2)
line object screen x(Obj1),object screen y(Obj1),object screen x(Obj2),object screen y(Obj2)
endfunction
To really understand what's going on requires a knowledge of trig, vectors, matrices, and vector spaces. I'm going to try to come up with a really, really abridged crash course.
Of course, if you already know some of this stuff, that's just wonderful, but if not, and my course doesn't help enough, I can try to go more in-depth.
Trig gets covered in most high school algebra classes, so I won't go over that, but if it's new, just check wikipedia for Trigonometric Functions, and there's an in-depth article on it.
Vectors, for our purposes, are essentially a group of three coordinates (X,Y,Z). The vectors I use in the example have a fourth component, W, but that's used for other things. For these purposes, W should always contain 1.0. For example, we'd use the vector: [4,2,5,1] to represent the 3D coordinate (4,2,5).
Matrices are also covered in most high school algebra classes, and so I won't go over how to multiply them together, which is something you'll need to know how to do. The matrices I'm using here are 4x4 and are transform matrices, meaning they are intended to transform a vector in some way (Note: Transforming a vector with a matrix works the same as multiplying a 4x4 matrix by a 4x1 matrix, and a transformation can be a rotation, a translation, or a scaling of a vector).
A vector space is essentially represented by three axes, a Right vector, an Up vector, and a Look vector, or X, Y, and Z axes. In world space, the axis vectors are [1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1], or when drawn as a matrix, you can see
[1,0,0,0]
[0,1,0,0]
[0,0,1,0]
[0,0,0,1]
, which is the identity matrix you probably learned about, where the left most column (not row) is the Right vector, the next is the Up, and the next is the Look. When you use the
position object function, you specify coordinates in world space. Each object has its own vector space, called object space, or model space. In this space, all of the vertices are given as coordinates in reference to the center of the object, and not the world. There's another space called view space, or camera space, in which everything is given in reference to the camera's position and orientation. There's even another space called clip space, or screen space, in which everything is still around the camera, but has been distorted to look like it shrinks with distance. This is the final output of the camera, and is the space you always look at the world through.
Now that I've kinda explained that, we can see how to use it all. We use transform matrices to
transform vectors (coordinates) from one space to another. In 3D graphics lingo, an object's World Matrix is a transform matrix that will transform a vector from that object's space into world space when multiplied together. The View Matrix is a matrix that takes any world vector and transforms it into View space, and the Projection Matrix takes view coordinates and puts them into Clip space. You get the idea.
But a transform matrix doesn't always have to change spaces. You can use it to perform any rotation, translation, or scaling you want to (but for translation and scaling, it's much less computationally expensive just to add some number or multiply some number with the coordinates. Matrices are usually used just for rotation.). In the example, I rotate the panels' centers around the world's axes, by creating a matrix that represents the desired rotation. I've written little commands to do this simply. I also rotate the sphere's vertices directly in world space, so I don't have to deal with object space. In the example, these lines of code create the rotation matrix I use to do all this:
CreateYRotationMatrix(Sphere.Vel.y) : temp=m
CreateXRotationMatrix(Sphere.Vel.x) : MultiplyMatrices(temp,m)
First, I create a matrix representing only the Y axis component of the rotation and then I multiply it by a matrix representing the X component. When you multiply matrices together, you create a kind of "matrix stack", in which the first matrix on the stack is the last to take effect on the vector you're transforming. In this case, the X rotation takes place before the Y.
Whew, I've written a lot, so I'm going to take a break and wait for your questions.