- SEPTiC DEMO'S COLLEGE -- 

                                 Lesson 11 
                                 ?????????? 
                         Written by Vicious / Septic 

                                  7 Jan 94 



                                  Introduction 
                                  ????????? 
Welcome to the first lesson in grade school! Now we are starting to finally 
get into the interesting parts, do you think is not it? Today, I will 
namely, to explain three-dimensional vector-rotation as when it came to some 
years ago created a revolution in the demo world and still is used today 
assiduously in the demos. 
   If this text seems difficult or even impossible to comprehend will you 
do not worry. It may take a while (and by some readings) whether to 
fully understand how it all works, and it has been very helpful to have read 
math in high school in a couple of years. 
   But, here we go running instead of talking ... 


                                    Theory 
                                    ????? 
When people talk about vectors in the demo world believe it is usually a "vector - 
Objects ", ie an object uppbygggt of vectors. A vector is actually 
(mathematically speaking) a viewer with specific length pointing to a point. 
Pointer can be described by specifying the length and angle, and it can see 
similar to this: 

      9 | 
      8 | 
      7 | 
      6 | 
      5 | 
      4 | _ 
      3 | / | 
      2 | / 
      1 | / 
      0 | /) a_________________ 
        0 1 2 3 4 5 6 7 8 9 

This vector points to a point that has the coordinates 2 and 4. If the vector 
would be described, would normally say that the length was 4.47 and 
angle of 63.4 degrees. The length is obtained by Pythagoras bullet here, and the angle through 
tangent. 
   Those here vectors of length and angle is not normal when you do 
vector rotations on the computer (which logically should be, because 
it is called VECTOR-rotation). Instead Removing vector is presented using 
by its end point, which in our case is in point 2; 4, ie X-coordinate 
2, and Y-coordinate is 4. 

      9 | 
      8 | 
      7 | 
      6 | 
      5 | 
      4 | * (2, 4) 
      3 | 
      2 | 
      1 | 
      0 |____________________ 
        0 1 2 3 4 5 6 7 8 9 

As you see, we have now a standard item in our two-dimensional 
coordinate system. If we were to take and rotate it around the origin (0, 0) so that 
it moves on a circular orbit around zero instead, we soon 
why we are not using a vector normal representation system with 
height, angle. Then we would for any point be required to produce X and Y 
height of Pythagoras rate, and therefore need to calculate two squares and a 
square root to produce the new point's coordinates. 
   Now will instead our knowledge of trigonometry to use! If we 
assume that our point is at its starting position, we can easily count 
on this starting point to 360 different angles by using the sine and cosine. 
Let me first make a change in the coordinate system: 

      9 | 
      8 | 
      7 | 
      6 | 
      5 | 
      4 | 
      3 | 
      2 | 
      1 | 
      0 |____*_______________ 
        0 1 2 3 4 5 6 7 8 9 

Hmmmm, what would it be good for? I put zero simply 
Y-coordinate, but kept the X-coordinate and thus low point came on 
2; 0 instead of 2, 4. Well, soon you will see that it all becomes very 
easier to think if we move down the point like this, because we may 
find out how long the point is. We can imagine that the point is established 
tied with a thread of origin, and that thread has the length L. (L'd therefore 
2 in this case ...) 
   We assume that zero degrees is parallel with our X-axis here, and 
so we say that we will rotate the point to the angle a. The panel would then see 
like about: 

      9 | 
      8 | 
      7 | 
      6 | 
      5 | 
      4 | 
      3 | 
      2 | * 
      1 | / 
      0 | /) a_________________ 
        0 1 2 3 4 5 6 7 8 9 

Since we know the length of the vector (it is, in reality, only 
X-coordinate when we set Y to zero), we see that the new X-coordinate 
can be calculated with the cosine: 

      2 | * 
       | / | 
       | / | 
       | / | 
       | L / | y 
      1 | / | 
       | / | 
       | / | 
       | / | 
       | / _ | 
      0 | /) a_____ |_|__________ 
        0 x 1 2 

The length L is, as I said, like all the time, because the thread that we have 
matured point of always have to be equally long. To obtain the new 
X-value now, we use the tigonometriska link that says cos 
a = nearby certificate divided by the hypotenuse. We must therefore X = L * COS (a). 
   We can then do almost the same thing to figure out the new Y-coordinate, 
by using their relationship a = opposing certificate divided by 
hypotenuse. Then we get Y = L * SIN (a). 
   As I mentioned before, so is the length equivalent to X, as we sat 
Y-coordinate to zero. So we can write on the two links to: 

    X = X * COS (a) 
    Y = X * SIN (a) 

Now we have learned to rotate a point which lies on the X-axis, but usually is 
is not the case as simple. From the beginning we had our vector item 
coordinate 2, 4, so then we have to do something about the Y-section, too. 
   We are in the same way (fixed on the contrary :-) and put X to zero instead: 

      9 | 
      8 | 
      7 | 
      6 | 
      5 | 
      4 | * 
      3 | 
      2 | 
      1 | 
      0 |____________________ 
        0 1 2 3 4 5 6 7 8 9 

Now, the length L instead equal to Y, and the rotation angle of a becoming a 90  
because the Y axis is 90 degrees from the x-axis. If we put this in 
the same coordinate before, so we get the new formulas: 

    X = Y * COS (90  + a) 
    Y = Y * SIN (90  + a) 

We can optimize the two terms a bit if we are some trigonometric 
laws which say that COS (90  + a) =- SIN (a) and SIN (90  + a) = COS (a). If we change 
this in the two expressions, we must: 

    X = Y *- SIN (a) <=> X =- Y * SIN (a) 
    Y = Y * COS (a) 

There you go ... So far so good! Now we have two terms to rotate a point 
located on the X-axis, and two specifically to rotate a point a 
on the Y axis. If you want to rotate a point that is free out there in the 
two-dimensional space now, we must use all the expressions of 
to calculate the total komposanten for X and Y. What we do is to 
adding up the equations for X and the formulas for Y: 

    New X = X * COS (a)-Y * SIN (a) 
    New Y = X * SIN (a) + Y * COS (a) 

This is now a basic formula for two-dimensional rotation (which is the same 
thing that rotation around the Z-axis in a three-dimensional coordinate system) and 
if we use it on our paragraph 2, 4 and rotate it to the angle of 30 , so 
we get the following: 

    New X = 2 * COS (30 ) -4 * SIN (30 ) 
    New Y = 2 * SIN (30 ) +4 * COS (30 degrees) 

    New X =- 0.27 
    New Y = 4.46 

Punk's new coordinates are then -0.27; 4.46 when we rotate 30 degrees. 

But, what about now with three dimensions instead? Well, in a 
three-dimensional coordinate system adds an axis, Z axis, 
pointing straight into the screen. One point of such a system requires three pieces 
coordinates instead of two. A describing its position in the X-point, one in 
Y-point and one of the Z-point. 

        y 
      9 | 
      8 | 
      7 | 
      6 | 
      5 | 
      4 | z 
      3 | / 3 
      2 | / 2 
      1 | / 1 
      0 | / 0__________________x 
        0 1 2 3 4 5 6 7 8 9 

   The rotation we have in the past (in two dimensions) is really a 
Z-rotation as we rotated around the Z axis. If you want to rotate around the y-axis 
instead, so you can imagine that it spins its coordinate system so that 
Y pointing inwards instead of Z in this way: 

        z 
      9 | 
      8 | 
      7 | 
      6 | 
      5 | 
      4 | 
      3 | 
      2 | 
      1 | 
      0 |____________________ x 
      / 0 1 2 3 4 5 6 7 8 9 
     / 1 
    / 2 
   / 3 
  y 

What I have done here is simply that the Y axis has fallen forward and 
Z-axis residue behind and set themselves up vertically on the image. Now we have 
exactly the same coordinate when we rotated two-dimensional with the 
except that Z has replaced Y. 
   The question then is now only: Can we ignore the Y coordinate and rotate the Z and X 
with the same formula as we did with the X and Y when we ignored Z? 
   The answer is YES! Of course we can! We just change the Y to Z in our 
formulas, and therefore, the formula for Y-rotation: 

    X = X * COS (a)-Z * SIN (a) 
    Z = X * SIN (a) + Z * COS (a) 

Very simple and convenient, that is. Here are the formulas to rotate in X, Y 
and Z stages: 

Rotate around the X-axis: 
------------------- 
Z = Z * COS (a)-Y * SIN (a) 
Y = Z * SIN (a) + Y * COS (a) 

Rotate around the y-axis: 
------------------- 
X = X * COS (a)-Z * SIN (a) 
Z = X * SIN (a) + Z * COS (a) 

Rotate around the Z-axis: 
------------------- 
X = X * COS (a)-Y * SIN (a) 
Y = X * SIN (a) + Y * COS (a) 

Now we have only one problem left to solve, namely HOW TO BE ABLE TO SHOW 
THREE-DIMENSIONAL POINTS ON SCREEN a two-dimensional? 

Well, it CAN be solved with Pythagoras rate, but since Pythagoras rate 
avoid when you want to be quick calculations (because it contains 
roots and kvadreringar), we must find another way. 
   If we imagine that we have our point well into the screen and off 
from us, so we might be there is a thread from our eye out for 
point while cutting the screen plan. Where the thread cutting the screen becomes 
Thus point's real projected coordinate. 
   How should I now find out where the thread cutting the screen now? Yes, by 
uniformity, we can without major problems picking up a simple one. 
   Let us draw a picture of how things might look if we imagine 
we look at our space from above: 

                  X-point 
      <---------------------------> 
                    x1 
           ------------------* "- Our point is this 
           | / 
           | / 
           | / / | \ 
           | / | X1 = point X-coordinate 
         z | / | Z = point Z-coordinate 
           | / | D = Distance to screen 
           | / | Z-point X2 = point new X-COORD. 
           | / | 
           | X2 / | 
      _____|________/________ | 
           | / Screen | 
           | / | 
           | / | 
         d | / | 
           | / | 
           | / | 
           | / \ | / 
           | / 
           o <-Here are the viewer 

If we imagine that this view is drawn from the top, so we telescopic down on 
our point, we see that two EQUIANGULAR triangles formed, and thus is 
uniform. 
   As you can see I have a letter D between the viewer and the screen. 
This is distance. If we make a comparison by looking at a painting so 
we see not so good if we look forward till it. So we need a distance 
to the screen as we watch. 
   We are interested in the value X2, which is the point in question 
value projected on the screen. Uniform unit tells us that part X1 
relate to the Z + d who X2 to d: 

       X1 X2 
      ---- ---- = 
      Z + d d 

X2 thus becomes: 

             X1 * d 
        X2 = ---- 
              Z + d 

This obviously also for the Y-coordinate. It becomes only the X1 and X2 
against Y1 and Y2 in the formula instead. 
   To be able to zoom the image can however replace the distance in the numerator against 
a deep-value. The formulas for the X and Y see something like this instead: 

             X1 * DEPTH 
        X2 = ------- 
             Z + DIST 

             Y1 * DEPTH 
        Y2 = ------- 
             Z + DIST 

The depth can then vary to make objects larger or smaller. 
The distance will not be changed sometime, but is set to a fixed value. 
Z + distance may not be zero, because it means that the projected 
the point has zero distance to the eye, therefore, is inside the eye, and 
it would surely be a physical impossibility. Moreover, the village DIVISION ZERO, 
hehe .... 

   There, it was everything you need to be able to rotate points in a 
three-dimensional space! 


                                  Register 
                                  ???????? 
Since vectors is pure mathematics there are no records to 
up today. All calculations are taken care of the CPU! 


                               Program example 
                               ??????????????? 
What do we have something small and well here today then? Yes, an old PEACH from 
demos of the older class, namely a line-vektorkub! There you might think is 
acid, but somewhere we must of course start when you show vector graphics. 
   Okay, should we look at how the program works now, then ... 
   First and foremost, we have as normal a main-routine first waiting for a 
special breaks position to sync the vector to 50 frames / sec. When 
screen beam come to the right place we freakin front side we drew our 
vector of the routine Swap Pages. The page we just proved then becomes instead 
"ritsida", ie, the side we should draw on. 
   Then we jump to a completely normal routine, which cleardensity-clearing our ritsida 
and then the first interesting routine, Rotate. 
   We jump down and telescopic of what it directly ... 
   Well, what have we here for small and good? Well, first I put a bit 
pointer, and on our coordinates and a 2d-coordinate location, plus sinus and 
cosinustabellen. 2d-coordinate location is needed because we do not destroy 
our original coordinates. The 2d-coordinate location is stored the coordinates 
we should use when we draw the lines then. 
   After I set pekarna I read X, Y and Z coordinates in a 
single sweep to the D0, D1 and D2. Then I store (temporarily) X-value and 
then pick spots for X-rotation. I multiply it by 2 and get 
Since the cosine of the angle * 16,384. I multiply that with Z and then 
I do the same with the Y settled with sinus. The two values (which is 16,384 for 
large) is then treated, so that subtracted from the Y and Z then I shift with 14 
(to divide by 16384) and then we get the new Z-coordinate. 
   Since I do much the same way with the Y-coordinate (the following formulas 
X-rotation) and gets a new Y-value. These new values must 
then used in both the second rotation, which is much the same 
way. 
   After all revolutions, a small kodsnutt which converts 3d 
coordinates to the 2d, and it is exactly the formula that I proved in the last 
chapter. First, we add a distance to Z, get deep-value and 
multiply it by X. Then we divide the Z + distance and the 
two-dimensional X-et seamlessly. It works the same way with Y 
then, so I need not explain closer ... 
   If we jump back and look in the main routine, we see that we are 
jump to an exciting new routine called DrawCube. 
   In DrawCube initiates I first no-address records that line the routine 
requires. (This is the same line routine that we built last time now 
will benefit :-) Then pointing at me 2d coordinates (we need 
not 3d coordinates here, because the line drawing is not done in three 
dimensions) and on a special line of data-table which I will explain 
further down. 
   We read from the line table number of lines in the polygon to know how 
many times we will loop our line drawing routine. Then we subtract 2 
as the last line is always to be drawn back to the first order 
it need not be in line with data-table, and to require DBF 
loop value-1 to loop the right number of times. 
   Then - in linjeutritnings routine that begins with. DrawPoly - I get 
first a coordinate numbers from the data line. I take it as times 8 
there is one X and one Y-coordinate as his own long word in the table. Other 
starting point is to start + (2 * 4), and hence needs to multiply 
Coordinate with the number 8. 
   After I get the X and Y in the position we got up and adds 
screen middle of them both. This is the line starting point. 
   Then I do the same with the line end point, although please note that I 
DO NOT move forward line data-pointer when I read the coordinate number! This makes 
that when we write the next line, it will hang together with previous and 
we have a coherent polygon. 
   When we designed the Number-1 lines used on the first coordinate again to 
be able to draw from the very last point to the first making 
polygon closes. 
   Back to the main routine now, then again ... Here we are again jumping to a 
routine called NewAngle. 
   NewAngle routine is pretty simple. The add simply right 
speed at the right angle and see if the angle exceeds 359 degrees. If 
it makes it to the "wrapper" around so that 360 becomes 0, 361 becomes 1 
etc ... This is achieved by subtracting 360 from the angle. 
   Finally in the main routine, we have a small kodsnutt (which is really 
not to have the main loop, because the code then easily become mushy and 
incalculable :-) This just adds another kodsnutten century 5 to the depth of 
to create a zoom effect when the cube is growing. When it reached the 360 are we 
do not add more, and then hope the ADD instruction over ... 
   If we jump down to the end of nearly source, a label named 
Coord, we see kubens coordinates. These are stored as X, Y, Z. First 
the point is therefore in the -50, -50, -50. Number of points is equal to the number of corners 
as our object is. A cube's eight corners, and therefore must therefore eight 
points. I use negative numbers because I want to rotary dials - 
shaft should be in the middle of the object, since the rotation is always happening around 
0,0,0 point. Putting a point farthest out of 50 in the X-point, and then 
a point farthest out of 50 in the X-point, we get a 100 units wide cube, where the middle 
is on the point of 0. So is the axis which also, and rotate the cube 
around its center. 
   You can change the shaft so that the tex is on the corner instead, by 
add 50 to all the coordinates. The box will then be equal, but rotate on 
an entirely different, fun way. 
   After the coordinate data is the data line. It is stored so that the first 
will there be a long word that tells how many lines polygon composed of 
and then the paragraph numbers. In the first line, we see the figures 
4,0,1,2,3. This means that we must draw a four-cornered polygon. First 
the line is drawn between the point 0 (ie, the first in the table of coordinates) and 
paragraph 1 (the second point of the coordinate table). The next line is drawn between 1 
and 2, the next between 2 and 3, and then the last, drawn between 3 and 0 
(because we bind the polygon in DrawCube routine above, if you will 
remember it ...). 
   Our cube has only had four pages in our line of data-table with 
polygons, although it actually has six sides. The reason for this is 
to all lines used by the remaining two sides have already sketched 
(because they coincide with those already drawn polygons pages), so 
therefore they need not be plotted. 
   Further down, following the line of data-table, is the sine and cosinustabellen. 
These tables, please feel free to use how you want. Otherwise, new 
tables (if you want to multiply by a higher or lower value than 
16,384, for example, better-decimal precision) created in Basic. It is just that 
generate sinus and cosinusvarden from 0  to 359  (0-2pi) and before 
store them in the table multiply by the value you want to use. Just look 
that the figures are rounded right, because some programs, using whole numbers, 
not rounded correctly, but just ignores decimal places if you do not use 
a special command that manages rounding. 
   Yep, it was probably all I needed to tell if the program because it 
others have been examined in previous lessons.