[rec.games.programmer] 3D rotation update

murrayk@prism.CS.ORST.EDU (04/11/91)

Ok, here we go.  First of all I would like to thank all the people that
were kind and knowledged enough to reply to my cry for help.  I received a
lot of mail and postings that helped me to find some new books to look
through and some actually sent me some code.  I tried to reply to all of
you who sent me something or posted something, but I am sure that I missed
a few...so if you didn't already hear thanks, then thanks.

Next, in most of the replys I got people rehashed just what I have already
been doing.  Here is my most immediate problem in a lot more detail.  

I can draw and rotate an object on the screen around the x, y and z-axis
all day long.  The only problem is that each axis that I rotate
around is the corresponding axis of the monitor (what you actually see).
Now, what I want to do is to be able to rotate the object around its own
three axes (virtual axes).  For example, say the object is a tetrehedron
with its base in the xy plane (the yz plane is sticking in your face) and
its top point in your face.  The object is situated so that the z-axis is a
line running though the top point and the middle of the base.  Now say that
I rotate this object around the x axis about 30 degrees so that the point
is now partially up the screen.  Now if I was to rotate the object about
the z-axis as my code now exists, the top point of the tetrehedron would
sweep out a circle on the screen.  This problem could be solved by doing
the rotations in a certain order, but that screws up as soon as you rotate
about the third axis.  What the object should do if it is rotated about the
z-axis (its z-axis) would be to spin along the imaginary line running
though its top point and its base.  But alas, I cannot get this to happen.

In consulting a few graphical technique books, I found out exactly how to
do a rotation about an arbitrary line.  I figured that if I kept the axes
of the object in the data of the object itself and rotated the axes along
with the object, then I would be able to do an arbitrary rotation about
those axes and voila, it would work.  I tried this and have had no luck.
My code has been gone over with a fine toothed comb (my own and a friends)
and no problem can be found.

If anyone has experience in this area of 3D rotation, please keep posting.
If I am just missing a small point, don't flame me.  I will see it soon
enough.  I am bound to find out what I am missing eventually.  All your
help is appreciated.

Thanks a lot, Keith Murray


--------------------------------------------------------------------------------
	CHAOS Software			Software for someone...
						
	1360 NW VanBuren		Keith Murray  a.k.a. Slammer
	Corvallis, OR  97330		murrayk@prism.cs.orst.edu
--------------------------------------------------------------------------------

2fmlcalls@kuhub.cc.ukans.edu (04/11/91)

> If anyone has experience in this area of 3D rotation, please keep posting.
> If I am just missing a small point, don't flame me.  I will see it soon
> enough.  I am bound to find out what I am missing eventually.  All your
> help is appreciated.
> 
> Thanks a lot, Keith Murray

I got a bit lost in your process you described.  Let me try to explain a
process I used as clearly as I can.

Lets take a square.  We all know its shape and (as opposed to a cube) it has
few points.  As emntioned in an earlier post, you want an array of 'triples'
(the x, y, and z coords for each point) and a sequence to connect the dots.  If
the points are A,B,C,D then we could come up with values like this:
A = (-10, 10, 0)
B = (10, 10, 0)
C = (10, -10, 0)
D = (-10, -10, 0)
If you plot these on a piece of graph paper (ignoring the last 'z' component)
you get a square 20 x 20 about the origin.  Connect A to B to C to D to A. 
There's the dot-to-dot.
These 'local' coordinates are important because they define a simple rotational
axis for the shape (you can rotate about any arbitrary point, but putting 0,0,0
as the center of gravity just makes sense).
So, the above points might be thought of as the source points.

Since you seem to understand transform matrices, I'll skip that rather tedious
part.  But basically, you pop in sin and cos values for the angle(s) you want
to rotate all these points about.  The transformation entails putting feeding
source points into the matrix and extracting transformed points.  If you feed
in these original points AS THEY ARE assigned above, the transformation will be
about the local origin (say, for example the square is rolling and tumbling
about its own axis).  The points you get out lets call tA, tB, tC, and tD -
small t for the local transformation.

Now you do the global transformation (as if the observer is rotating, tumbling
etc.).  First you need to translate (shift) the points tA, tB, tC, tD by the
amount that they are distant from the observer.  If the global position of the
square is a point P(distX, distY, distZ), then add distX to the x component of
tA, tB, tC, tD.  Not that we are translating the transformed points and not the
original 'raw' source points.  All four points of the square have now been:
1) rotated about their own axis and
2) shifted in space to represent their distance from the observer.
The now shifted points we could call tsA, tsB, tsC, tsD.  That is, these are
the original points after rotating and then shifting.

The last` step is to pop the sines and cosines for the OBSERVERS roll, pitch,
and yaw into a transform matrix  and run tsA, tsB, tsC, tsD through.  What you
get out we can call tsTA, tsTB, tsTC, tsTD.

These are the final points.  Use your similar triangles and clipping on these
points.  And there it is.

For the next frame, add rolls, pitches and yaws to the roll, pitch and yaw of
the object and observer.  Figure your new distance point P.  And run the whole
gauntlet again with the source points.

A final note.  As pointed out in same earlier post, so long as you maintain
your original source points and never modify them, you'll get no accumualted
round-off errors (read - a parallelogram or rhombus).  The points you derive
from all the transofroms can be tossed after you draw the scene.  In fact, you
may have realized that after the first rotation (about the objects axis) you
need not keep this copy of points when you translate them and then when you
rotate about the observer).

Also, rotations and distance are cumulative.  If the square is rotated 10
degrees off North and rotates +5 degrees in one loop through the game, you put
15 degrees (not 5) into the transform matrix.

john calhoun

meekins@anaconda.cis.ohio-state.edu (timothy lee meekins) (04/11/91)

In article <1991Apr10.191212.5249@lynx.CS.ORST.EDU> murrayk@prism.CS.ORST.EDU writes:

<snip!>

>I can draw and rotate an object on the screen around the x, y and z-axis
>all day long.  The only problem is that each axis that I rotate
>around is the corresponding axis of the monitor (what you actually see).
>Now, what I want to do is to be able to rotate the object around its own
>three axes (virtual axes).  For example, say the object is a tetrehedron
>with its base in the xy plane (the yz plane is sticking in your face) and
>its top point in your face.  The object is situated so that the z-axis is a
>line running though the top point and the middle of the base.  Now say that
>I rotate this object around the x axis about 30 degrees so that the point
>is now partially up the screen.  Now if I was to rotate the object about
>the z-axis as my code now exists, the top point of the tetrehedron would
>sweep out a circle on the screen.  This problem could be solved by doing
>the rotations in a certain order, but that screws up as soon as you rotate
>about the third axis.  What the object should do if it is rotated about the
>z-axis (its z-axis) would be to spin along the imaginary line running
>though its top point and its base.  But alas, I cannot get this to happen.
>
>In consulting a few graphical technique books, I found out exactly how to
>do a rotation about an arbitrary line.  I figured that if I kept the axes
>of the object in the data of the object itself and rotated the axes along
>with the object, then I would be able to do an arbitrary rotation about
>those axes and voila, it would work.  I tried this and have had no luck.
>My code has been gone over with a fine toothed comb (my own and a friends)
>and no problem can be found.
>

Rotating about an arbitray axis is a simple thing, but as you have noticed,
it is not the solution to your problem.

>If anyone has experience in this area of 3D rotation, please keep posting.
>If I am just missing a small point, don't flame me.  I will see it soon
>enough.  I am bound to find out what I am missing eventually.  All your
>help is appreciated.


Well, you're not missing a small point. You are most likely experiencing
gimbal lock, a term developed in aeronautical engineering (I believe) when
using euler angles (x,y,z rotations). Your description of ordering the 
rotations to make it work about one axis and a different rotation ordering
for axis definately sounds a like the euler angle problem. I would suggest
that you use Quaternions instead of Euler angles. Basically, you convert
your 3 rotations into 4-D space, perform the rotation, then map back. But,
a better method would be to learn directly how quaternions work and not
even perform the mapping. In which case, you specify the axis of rotation.
For more information, see "Animating Rotation with Quaternion Curves" in
SIGGRAPH '85 proceedings. Source code for quaternions is provided with
Graphics Gems by Andrew Glassner and is available by FTP somewhere.

-tim

--
+---------------------------S-U-P-P-O-R-T-----------------------------------+
|/ Tim Meekins                  <<>> Snail Mail:           <<>>  Apple II  \|
|>   meekins@cis.ohio-state.edu <<>>   8372 Morris Rd.     <<>>  Forever!  <|
|\   timm@pro-tcc.cts.com       <<>>   Hilliard, OH 43026  <<>>            /|

minar@reed.edu (04/15/91)

All this talk about how to do 3d rotations is nice. But I'm lazy.
Is there source code / a C library that will allow me to do 3d projections?
I just want to write the objects up - I don't want to worry with the details
on how they get onto the screen.  Has someone written 3d projections
suitable for real time usage, say if I were to write a game like Battlezone
or Elite?