Glenzing, Fast Polys, etc

                    ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
                    ³         W E L C O M E         ³
                    ³  To the VGA Trainer Program   ³ ³
                    ³              By               ³ ³
                    ³      DENTHOR of ASPHYXIA      ³ ³ ³
                    ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                      ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                        ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

                            --==[ PART 14 ]==--

 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 þ Introduction

 Hello there. Exams are just around the corner (again :( ), so I thought
 I better get round to doing the next trainer. As usual, there seems to
 have been a big delay between this one and the last one... sorry about
 that ;-)

 Well, this trainer is mainly on four things : Glenzing, faster polys,
 fixed point and assembler. The sample program is basically tut 9
 rewritten to include the above.

 I'll go through them in order, and hopefully you won't have any hassles
 grasping the concepts. By the way, do any of you read the text files? I
 find myself answering questions via E-Mail etc. that were discussed in
 the text sections of the trainers ... oh well, I'll just ramble along
 anyway ;-)

 Please dont send any mail to smith9@batis.bis.und.ac.za anymore ... I
 don't know for how much longer the account will be valid (How can a
 non-BIS person get onto the BIS UNIX machine in the BIS2 directory? If
 his name is Denthor I suppose ;-) Oh well, I got about 8 months use out
 of it. The account expires on Christmas day anyway...) So anyway, please
 leave all messages to denthor@beastie.cs.und.ac.za


 If you would like to contact me, or the team, there are many ways you
 can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
                   on the ASPHYXIA BBS.
             2) Write to :  Grant Smith
                            P.O.Box 270 Kloof
                            3640
                            Natal
                            South Africa
             3) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
                   call during varsity). Call +27-31-73-2129 if you call
                   from outside South Africa. (It's YOUR phone bill ;-))
             4) Write to denthor@beastie.cs.und.ac.za in E-Mail.
             5) Write to asphyxia@beastie.cs.und.ac.za to get to all of
                us at once.

 NB : If you are a representative of a company or BBS, and want ASPHYXIA
        to do you a demo, leave mail to me; we can discuss it.
 NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
         quite lonely and want to meet/help out/exchange code with other demo
         groups. What do you have to lose? Leave a message here and we can work
         out how to transfer it. We really want to hear from you!

 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 þ What is glenzing?

 This is an easy one. Imagine, in a 3D object, that all the sides are
 made out of colored glass. That means that every time you look through
 that side, everything behind it is tinged in a certain color.

 In ascii ...
           +---------+
           |      <--|---Light blue
           |         |
      +--------+     |
      |    | <-|-----|---Dark blue
      |    +---|-----+
      |     <--|---------Light blue
      +--------+

 So where the two sides overlap, the color values of the two sides are
 added. Easy huh? It is also easy to code. This is how you do it :

 Set up your pallette to be a nice run of colors.
 Draw your first poly.
 While drawing poly 1, instead of plonking down a set pixel color, grab the
   backgrond pixel, add 1 to it, then put the result down.
 Draw your second poly.
 While drawing poly 2, instead of plonking down a set pixel color, grab the
   backgrond pixel, add 2 to it, then put the result down.
 and so forth.

 So if the color behind poly 1 was 5, you would place pixel 6 down
 instead.

 If you do this for every single pixel of every single side of your 3d
 object, you then have glenzing going. This is obviously slightly slower
 then just drawing an item straight, but in the sample program it goes
 quite quickly ... this is because of the following sections...


 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 þ Faster Polygons

 In Tut 9, you probably noticed that we were using a multiply for every
 single line of the poly that we drew. This is not good. Let's find out
 how to speed it up, shall we...

 With the multiply method, we went through every line, to find out the
 minimum x and maximum x value for that line.

                            +
                    ------/---\------- Find min x and max x, draw a line
                        /       \        between them.
                      +           +
                        \       /
                          \   /
                            +

 How about if we found out all the min and max x's for every line first,
 then just went through an array drawing them. We could do it by
 "scanning" each side in turn. Here is how we do it :

                           + 1
                         /
                       /
                   2 +

 We go from point one to point two. For every single y we go down, we
 move a constant x value. This value is found like this :

            xchange := (x1-x2)/(y1-y2)

 Remember gradients? This is how you calulated the slope of a line waaay
 back in school. You never thought it would be any use, didn't you ;-)

 Anyway, with this value, we can do the following :

     For loop1:=y1 to y2 do BEGIN
       [ Put clever stuff here ]
       x:=x+xchange;
     END;

 and we will go through all the x-values we need for that line. Clever,
 huh?

 Now for the clever bit. You have an array, from 0 to 199 (which is all
 the possible y-values your onscreen poly can have). Inside this is two
 values, which will be your min x and your max x. You start off with the
 min x being a huge number, and the max x being a low number. Then you
 scan a side. For each y, check to see if one of the following has
 happened :    If the x value is smaller then the xmin value in your
                 array, make the xmin value equal to the x value
               If the x value is larger then the xmax value in your
                 array, make the xmax value equal to the x value

 The loop now looks like this :

     For loop1:=y1 to y2 do BEGIN
       if x>poly[loop1,1] then poly[loop1,1]:=x;
       if x0 then sgn:=+1;
        if a<0 then sgn:=-1;
        if a=0 then sgn:=0;
   end;
 var i,s,d1x,d1y,d2x,d2y,u,v,m,n:integer;
 begin
      u:= c - a;
      v:= d - b;
      d1x:= SGN(u);
      d1y:= SGN(v);
      d2x:= SGN(u);
      d2y:= 0;
      m:= ABS(u);
      n := ABS(v);
      IF NOT (M>N) then
      BEGIN
           d2x := 0 ;
           d2y := SGN(v);
           m := ABS(v);
           n := ABS(u);
      END;
      s := m shr 1;
      FOR i := 0 TO m DO
      BEGIN
           putpixel(a,b,col,where);
           s := s + n;
           IF not (smxy then mxy:=y2;
   if y3mxy then mxy:=y3;    { Choose the min y mny and max y mxy }
   if y4mxy then mxy:=y4;

   if mny<0 then mny:=0;
   if mxy>199 then mxy:=199;
   if mny>199 then exit;
   if mxy<0 then exit;        { Verticle range checking }

   mul1:=x1-x4; div1:=y1-y4;
   mul2:=x2-x1; div2:=y2-y1;
   mul3:=x3-x2; div3:=y3-y2;
   mul4:=x4-x3; div4:=y4-y3;  { Constansts needed for intersection calc }

   for yc:=mny to mxy do
     begin
       mnx:=320;
       mxx:=-1;
       if (y4>=yc) or (y1>=yc) then
         if (y4<=yc) or (y1<=yc) then   { Check that yc is between y1 and y4 }
           if not(y4=y1) then
             begin
               x:=(yc-y4)*mul1 div div1+x4; { Point of intersection on x axis }
               if xmxx then
                 mxx:=x;       { Set point as start or end of horiz line }
             end;
       if (y1>=yc) or (y2>=yc) then
         if (y1<=yc) or (y2<=yc) then   { Check that yc is between y1 and y2 }
           if not(y1=y2) then
             begin
               x:=(yc-y1)*mul2 div div2+x1; { Point of intersection on x axis }
               if xmxx then
                 mxx:=x;       { Set point as start or end of horiz line }
             end;
       if (y2>=yc) or (y3>=yc) then
         if (y2<=yc) or (y3<=yc) then   { Check that yc is between y2 and y3 }
           if not(y2=y3) then
             begin
               x:=(yc-y2)*mul3 div div3+x2; { Point of intersection on x axis }
               if xmxx then
                 mxx:=x;       { Set point as start or end of horiz line }
             end;
       if (y3>=yc) or (y4>=yc) then
         if (y3<=yc) or (y4<=yc) then   { Check that yc is between y3 and y4 }
           if not(y3=y4) then
             begin
               x:=(yc-y3)*mul4 div div4+x3; { Point of intersection on x axis }
               if xmxx then
                 mxx:=x;       { Set point as start or end of horiz line }
             end;
       if mnx<0 then
         mnx:=0;
       if mxx>319 then
         mxx:=319;          { Range checking on horizontal line }
       if mnx<=mxx then
         hline (mnx,mxx,yc,color,where);   { Draw the horizontal line }
     end;
   end;

 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 Function rad (theta : real) : real;
   {  This calculates the degrees of an angle }
 BEGIN
   rad := theta * pi / 180
 END;

 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 Procedure Putpixel (X,Y : Integer; Col : Byte; where:word); assembler;
   { This puts a pixel on the screen by writing directly to memory. }
 Asm
   mov     ax,[where]
   mov     es,ax
   mov     bx,[X]
   mov     dx,[Y]
   mov     di,bx
   mov     bx, dx                  {; bx = dx}
   shl     dx, 8
   shl     bx, 6
   add     dx, bx                  {; dx = dx + bx (ie y*320)}
   add     di, dx                  {; finalise location}
   mov     al, [Col]
   stosb
 End;

 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 Function Getpixel (X,Y : Integer; where:word):byte; assembler;
   { This puts a pixel on the screen by writing directly to memory. }
 Asm
   mov     ax,[where]
   mov     es,ax
   mov     bx,[X]
   mov     dx,[Y]
   mov     di,bx
   mov     bx, dx                  {; bx = dx}
   shl     dx, 8
   shl     bx, 6
   add     dx, bx                  {; dx = dx + bx (ie y*320)}
   add     di, dx                  {; finalise location}
   mov     al, es:[di]
 End;

 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 Procedure LoadCEL (FileName :  string; ScrPtr : pointer);
   { This loads the cel 'filename' into the pointer scrptr }
 var
   Fil : file;
   Buf : array [1..1024] of byte;
   BlocksRead, Count : word;
 begin
   assign (Fil, FileName);
   reset (Fil, 1);
   BlockRead (Fil, Buf, 800);    { Read and ignore the 800 byte header }
   Count := 0; BlocksRead := $FFFF;
   while (not eof (Fil)) and (BlocksRead <> 0) do begin
     BlockRead (Fil, mem [seg (ScrPtr^): ofs (ScrPtr^) + Count], 1024, BlocksRead);
     Count := Count + 1024;
   end;
   close (Fil);
 end;

 BEGIN
 END.{$X+}
 USES Crt,GFX2;

 CONST VGA = $A000;
       maxpolys = 6;
       A : Array [1..maxpolys,1..4,1..3] of integer =
         (
          ((-10,-10,10),(-10,10,10),(10,10,10),(10,-10,10)),
          ((-10,-10,-10),(-10,10,-10),(10,10,-10),(10,-10,-10)),
          ((-10,-10,-10),(-10,10,-10),(-10,10,10),(-10,-10,10)),
          ((10,-10,-10),(10,10,-10),(10,10,10),(10,-10,10)),
          ((10,-10,10),(10,-10,-10),(-10,-10,-10),(-10,-10,10)),
          ((10,10,10),(10,10,-10),(-10,10,-10),(-10,10,10))
         );  { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }
             { (X2,Y2,Z2) ... for the 4 points of a poly }

 Type Point = Record
                x,y,z:integer;                { The data on every point we rotate}
              END;

 VAR Lines : Array [1..maxpolys,1..4] of Point; { The base object to be rotated }
     Translated : Array [1..maxpolys,1..4] of Point; { The rotated object }
     lookup : Array [0..360,1..2] of integer; { Our sin and cos lookup table }
     poly : array [0..199,1..2] of integer;
     ytopclip,ybotclip:integer;  {where to clip our polys to}
     xoff,yoff,zoff:integer;

 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 Procedure SetMCGA;  { This procedure gets you into 320x200x256 mode. }
 BEGIN
   asm
      mov        ax,0013h
      int        10h
   end;
 END;

 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 Procedure Hline (x1,x2,y:word;col:byte;where:word); assembler;
   { This draws a horizontal line from x1 to x2 on line y in color col }
 asm
   mov   ax,where
   mov   es,ax
   mov   ax,y
   mov   di,ax
   shl   ax,8
   shl   di,6
   add   di,ax
   add   di,x1

   mov   cx,x2
   sub   cx,x1
   cmp   cx,0
   jle   @End
 @Loop1 :
   mov   al,es:[di]
   add   al,col
 {  inc   al}
   stosb
   loop  @loop1
 @End:
 end;

 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 Procedure DrawPoly(x1,y1,x2,y2,x3,y3,x4,y4:integer;color:byte;where:word);
   { This draw a polygon with 4 points at x1,y1 , x2,y2 , x3,y3 , x4,y4
     in color col }
 var miny,maxy:integer;
     loop1:integer;

 Procedure doside (x1,y1,x2,y2:integer);
   { This scans the side of a polygon and updates the poly variable }
 VAR temp:integer;
     x,xinc:integer;
     loop1:integer;
 BEGIN
   if y1=y2 then exit;
   if y2ytopclip-1) and (loop1poly[loop1,2]) then poly[loop1,2]:=x shr 7;
     END;
     x:=x+xinc;
   END;
 END;

 begin
   asm
     mov   si,offset poly
     mov   cx,200
 @Loop1:
     mov   ax,32766
     mov   ds:[si],ax
     inc   si
     inc   si
     mov   ax,-32767
     mov   ds:[si],ax
     inc   si
     inc   si
     loop  @loop1
   end;     { Setting the minx and maxx values to extremes }
   miny:=y1;
   maxy:=y1;
   if y2maxy then maxy:=y2;
   if y3>maxy then maxy:=y3;
   if y4>maxy then maxy:=y4;
   if minyybotclip then maxy:=ybotclip;
   if (miny>199) or (maxy<0) then exit;

   Doside (x1,y1,x2,y2);
   Doside (x2,y2,x3,y3);
   Doside (x3,y3,x4,y4);
   Doside (x4,y4,x1,y1);

   for loop1:= miny to maxy do
     hline (poly[loop1,1],poly[loop1,2],loop1,color,where);
 end;

 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 Procedure SetUpPoints;
   { This creates the lookup table }
 VAR loop1,loop2:integer;
 BEGIN
   For loop1:=0 to 360 do BEGIN
     lookup [loop1,1]:=round(sin (rad (loop1))*16384);
     lookup [loop1,2]:=round(cos (rad (loop1))*16384);
   END;
 END;

 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 Procedure RotatePoints (x,Y,z:Integer);
   { This rotates the objecct in lines to translated }
 VAR loop1,loop2:integer;
     a,b,c:integer;
 BEGIN
   For loop1:=1 to maxpolys do BEGIN
     for loop2:=1 to 4 do BEGIN
       b:=lookup[y,2];
       c:=lines[loop1,loop2].x;
       asm
         mov   ax,b
         imul  c
         sal   ax,1
         rcl   dx,1
         sal   ax,1
         rcl   dx,1
         mov   a,dx
       end;
       b:=lookup[y,1];
       c:=lines[loop1,loop2].z;
       asm
         mov   ax,b
         imul  c
         sal   ax,1
         rcl   dx,1
         sal   ax,1
         rcl   dx,1
         add   a,dx
       end;
       translated[loop1,loop2].x:=a;
       translated[loop1,loop2].y:=lines[loop1,loop2].y;
       b:=-lookup[y,1];
       c:=lines[loop1,loop2].x;
       asm
         mov   ax,b
         imul  c
         sal   ax,1
         rcl   dx,1
         sal   ax,1
         rcl   dx,1
         mov   a,dx
       end;
       b:=lookup[y,2];
       c:=lines[loop1,loop2].z;
       asm
         mov   ax,b
         imul  c
         sal   ax,1
         rcl   dx,1
         sal   ax,1
         rcl   dx,1
         add   a,dx
       end;
       translated[loop1,loop2].z:=a;

       if x<>0 then BEGIN
         b:=lookup[x,2];
         c:=translated[loop1,loop2].y;
         asm
           mov   ax,b
           imul  c
           sal   ax,1
           rcl   dx,1
           sal   ax,1
           rcl   dx,1
           mov   a,dx
         end;
         b:=lookup[x,1];
         c:=translated[loop1,loop2].z;
         asm
           mov   ax,b
           imul  c
           sal   ax,1
           rcl   dx,1
           sal   ax,1
           rcl   dx,1
           sub   a,dx
         end;
         b:=lookup[x,1];
         c:=translated[loop1,loop2].y;
         translated[loop1,loop2].y:=a;
         asm
           mov   ax,b
           imul  c
           sal   ax,1
           rcl   dx,1
           sal   ax,1
           rcl   dx,1
           mov   a,dx
         end;
         b:=lookup[x,2];
         c:=translated[loop1,loop2].z;
         asm
           mov   ax,b
           imul  c
           sal   ax,1
           rcl   dx,1
           sal   ax,1
           rcl   dx,1
           add   a,dx
         end;
         translated[loop1,loop2].z:=a;
       END;

       if z<>0 then BEGIN
         b:=lookup[z,2];
         c:=translated[loop1,loop2].x;
         asm
           mov   ax,b
           imul  c
           sal   ax,1
           rcl   dx,1
           sal   ax,1
           rcl   dx,1
           mov   a,dx
         end;
         b:=lookup[z,1];
         c:=translated[loop1,loop2].y;
         asm
           mov   ax,b
           imul  c
           sal   ax,1
           rcl   dx,1
           sal   ax,1
           rcl   dx,1
           sub   a,dx
         end;
         b:=lookup[z,1];
         c:=translated[loop1,loop2].x;
         translated[loop1,loop2].x:=a;
         asm
           mov   ax,b
           imul  c
           sal   ax,1
           rcl   dx,1
           sal   ax,1
           rcl   dx,1
           mov   a,dx
         end;
         b:=lookup[z,2];
         c:=translated[loop1,loop2].y;
         asm
           mov   ax,b
           imul  c
           sal   ax,1
           rcl   dx,1
           sal   ax,1
           rcl   dx,1
           add   a,dx
         end;
         translated[loop1,loop2].y:=a;
       END;
     END;
   END;
 END;

 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 Procedure DrawPoints;
   { This draws the translated object to the virtual screen }
 VAR loop1:Integer;
     temp:integer;
     nx:integer;
     tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4:integer;
 BEGIN
   For loop1:=1 to maxpolys do BEGIN
     If (translated[loop1,1].z+zoff<0) and (translated[loop1,2].z+zoff<0)
        and (translated[loop1,3].z+zoff<0) and (translated[loop1,4].z+zoff<0)
        then BEGIN
       temp:=round (translated[loop1,1].z)+zoff;
       nx:=translated[loop1,1].X;
       asm
         mov   ax,nx
         mov   dx,ax
         sal   ax,8
         sar   dx,8
         idiv  temp
         add   ax,160
         mov   nx,ax
       end;
       tx1:=nx;
       nx:=translated[loop1,1].Y;
       asm
         mov   ax,nx
         mov   dx,ax
         sal   ax,8
         sar   dx,8
         idiv  temp
         add   ax,100
         mov   nx,ax
       end;
       ty1:=nx;

       temp:=round (translated[loop1,2].z)+zoff;
       nx:=translated[loop1,2].X;
       asm
         mov   ax,nx
         mov   dx,ax
         sal   ax,8
         sar   dx,8
         idiv  temp
         add   ax,160
         mov   nx,ax
       end;
       tx2:=nx;
       nx:=translated[loop1,2].Y;
       asm
         mov   ax,nx
         mov   dx,ax
         sal   ax,8
         sar   dx,8
         idiv  temp
         add   ax,100
         mov   nx,ax
       end;
       ty2:=nx;

       temp:=round (translated[loop1,3].z)+zoff;
       nx:=translated[loop1,3].X;
       asm
         mov   ax,nx
         mov   dx,ax
         sal   ax,8
         sar   dx,8
         idiv  temp
         add   ax,160
         mov   nx,ax
       end;
       tx3:=nx;
       nx:=translated[loop1,3].Y;
       asm
         mov   ax,nx
         mov   dx,ax
         sal   ax,8
         sar   dx,8
         idiv  temp
         add   ax,100
         mov   nx,ax
       end;
       ty3:=nx;

       temp:=round (translated[loop1,4].z)+zoff;
       nx:=translated[loop1,4].X;
       asm
         mov   ax,nx
         mov   dx,ax
         sal   ax,8
         sar   dx,8
         idiv  temp
         add   ax,160
         mov   nx,ax
       end;
       tx4:=nx;
       nx:=translated[loop1,4].Y;
       asm
         mov   ax,nx
         mov   dx,ax
         sal   ax,8
         sar   dx,8
         idiv  temp
         add   ax,100
         mov   nx,ax
       end;
       ty4:=nx;

       drawpoly (tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4,loop1,vaddr);
     END;
   END;
 END;

 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 Procedure MoveAround;
   { This is the main display procedure. }
 VAR deg,loop1,loop2:integer;
     ch:char;

 BEGIN
   for loop1:=1 to 15 do
     pal (loop1,0,loop1*4+3,63-(loop1*4+3));
   pal (100,50,50,50);

   deg:=0;
   ch:=#0;
   Cls (vaddr,0);
   For loop1:=1 to maxpolys do
     For loop2:=1 to 4 do BEGIN
       Lines [loop1,loop2].x:=a [loop1,loop2,1]*8;
       Lines [loop1,loop2].y:=a [loop1,loop2,2]*8;
       Lines [loop1,loop2].z:=a [loop1,loop2,3]*8;
     END;

   cls (vaddr,0);
   cls (vga,0);
   Xoff := 160;
   Yoff:=100;
   zoff:=-500;

   ytopclip:=101;
   ybotclip:=100;
   line (0,100,319,100,100,vga);
   delay (2000);
   for loop1:=1 to 25 do BEGIN
     RotatePoints (deg,deg,deg);
     DrawPoints;
     line (0,ytopclip,319,ytopclip,100,vaddr);
     line (0,ybotclip,319,ybotclip,100,vaddr);
     flip (vaddr,vga);
     cls (vaddr,0);
     deg:=(deg+5) mod 360;
     ytopclip:=ytopclip-4;
     ybotclip:=ybotclip+4;
   END;
   Repeat
     if keypressed then ch:=upcase (Readkey);
     RotatePoints (deg,deg,deg);
     DrawPoints;
     line (0,0,319,0,100,vaddr);
     line (0,199,319,199,100,vaddr);
     flip (vaddr,vga);
     cls (vaddr,0);
     deg:=(deg+5) mod 360;
   Until ch=#27;
   for loop1:=1 to 25 do BEGIN
     ytopclip:=ytopclip+4;
     ybotclip:=ybotclip-4;
     RotatePoints (deg,deg,deg);
     DrawPoints;
     line (0,ytopclip,319,ytopclip,100,vaddr);
     line (0,ybotclip,319,ybotclip,100,vaddr);
     flip (vaddr,vga);
     cls (vaddr,0);
     deg:=(deg+5) mod 360;
   END;
 END;

 BEGIN
   clrscr;
   writeln ('Welcome to the fourteenth trainer! This one is on glenzing, and also');
   writeln ('throws in a faster poly, fixed point math and a lot more assembler.');
   writeln;
   Writeln ('This isn''t very interactive ... hit any key to start, and then');
   writeln ('hit the [ESC] key to exit. It is a glenzed cube spinning in the');
   writeln ('middle of the screen. Read the text file for more information on');
   writeln ('how the fixed point etc. works ... it will also help a lot if you');
   writeln ('compare it with TUTPROG9.PAS, as this is the same 3D system, just');
   writeln ('speeded up.');
   writeln;
   writeln;
   writeln;
   write ('Hit any key to continue ...');
   readkey;
   SetUpVirtual;
   SetMCGA;
   SetUpPoints;
   MoveAround;
   SetText;
   ShutDown;
   Writeln ('All done. This concludes the fourteenth sample program in the ASPHYXIA');
   Writeln ('Training series. You may reach DENTHOR under the names of GRANT');
   Writeln ('SMITH/DENTHOR/ASPHYXIA on the ASPHYXIA BBS.I also occasinally');
   Writeln ('RSAProg, comp.lang.pascal and comp.sys.ibm.pc.demos. E-mail me at :');
   Writeln ('    smith9@batis.bis.und.ac.za');
   Writeln ('The numbers are available in the main text. You may also write to me at:');
   Writeln ('             Grant Smith');
   Writeln ('             P.O. Box 270');
   Writeln ('             Kloof');
   Writeln ('             3640');
   Writeln ('             Natal');
   Writeln ('             South Africa');
   Writeln ('I hope to hear from you soon!');
   Writeln; Writeln;
   Write   ('Hit any key to exit ...');
   readkey;
 END.

 [BACK] Back

Discuss this article in the forums


Date this article was posted to GameDev.net: 7/16/1999
(Note that this date does not necessarily correspond to the date the article was written)

See Also:
Denthor's Asphyxia Tutorials

© 1999-2011 Gamedev.net. All rights reserved. Terms of Use Privacy Policy
Comments? Questions? Feedback? Click here!