
Program TrnsVect; { Transparent Vectors }
{$G+} { 286 Instructions Enabled }

{  Transparent 3D Vectors Example  }
{     Programmed by David Dahl     }
{  This program is PUBLIC DOMAIN   }

Uses CRT;
Const ViewerDist = 200;
Type VGAArray = Array [0..199, 0..319] of Byte;
     VGAPtr   = ^VGAArray;
     PaletteRec  = Record
                         Red   : Byte;
                         Green : Byte;
                         Blue  : Byte;
                   End;
     PaletteType = Array [0..255] of PaletteRec;
     PalettePtr  = ^PaletteType;
     PolyRaster  = Record
                         X1 : Word;
                         X2 : Word;
                   End;
     PolyFill    = Array [0..199] of PolyRaster;
     PolyFillPtr = ^PolyFill;
     FacetPtr     = ^PolyFacet;
     PolyFacet    = Record
                          Color       : Byte;
                          X1, Y1, Z1,
                          X2, Y2, Z2,
                          X3, Y3, Z3,
                          X4, Y4, Z4  : Integer;
                          NextFacet   : FacetPtr;
                    End;
     PolyHPtr     = ^PolygonHead;
     PolygonHead  = Record
                          X, Y, Z    : Integer;
                          AX, AY, AZ : Integer;
                          FirstFacet : FacetPtr;
                    End;
Var  VGAMEM   : VGAPtr;
     WorkPage : VGAPtr;
     BkgPage  : VGAPtr;
     Palette  : PalettePtr;
     PolyList : PolyFillPtr;
{-[ Initialize 320 X 200 X 256 VGA ]---------------------------------------}
Procedure GoMode13h; Assembler;
ASM
   MOV AX, $0013
   INT $10
End;
{=[ Convex Polygon Drawing Routines ]======================================}
{-[ Clear Polygon Raster List ]--------------------------------------------}
Procedure ClearPolyList (Var ListIn : PolyFill);
Begin
     FillChar (ListIn, SizeOf(ListIn), $FF);
End;
{-[ OR VariableIn with Value -- Modeled after FillChar ]-------------------}
Procedure ORChar (Var VariableIn;
                      Size       : Word;
                      Value      : Byte); Assembler;
ASM
   PUSH DS
   MOV CX, Size
   OR  CX, CX
   JZ  @Done
   LDS SI, VariableIn
   MOV AL, Value
   @ORLoop:
      OR DS:[SI], AL
      INC SI
   LOOP @ORLoop
   @Done:
   POP DS
End;
{-[ Draw Polygon From Raster List To Work Buffer ]-------------------------}
Procedure DrawPolyFromList (Var ListIn      : PolyFill;
                            Var FrameBuffer : VGAArray;
                                Color       : Byte);
Var YCount : Word;
    TempX1 : Word;
    TempX2 : Word;
Begin
     For YCount := 0 to 199 do
     Begin
          TempX1 := ListIn[YCount].X1;
          TempX2 := ListIn[YCount].X2;
          If (TempX1 <= 319) AND (TempX2 <= 319)
          Then
              ORChar (FrameBuffer[YCount, TempX1],
                      TempX2 - TempX1 + 1, Color);
     End;
End;
{-[ Add An Element To The Raster List ]------------------------------------}
Procedure AddRasterToPoly (Var ListIn : PolyFill;
                               X, Y   : Integer);
Begin
     { Clip X }
     If X < 0
     Then
         X := 0
     Else
         If X > 319
         Then
             X := 319;
    { If Y in bounds, add to list }
    If ((Y >= 0) AND (Y <= 199))
    Then
    Begin
         If (ListIn[Y].X1 > 319)
         Then
         Begin
             ListIn[Y].X1 := X;
             ListIn[Y].X2 := X;
         End
         Else
             If (X < ListIn[Y].X1)
             Then
                 ListIn[Y].X1 := X
             Else
                 If (X > ListIn[Y].X2)
                 Then
                     ListIn[Y].X2 := X;
    End;
End;
{=[ Polygon ]==============================================================}
{-[ Add A Facet To Current Polygon ]---------------------------------------}
Procedure AddFacet (Polygon          : PolyHPtr;
                    Color            : Byte;
                    X1In, Y1In, Z1In : Integer;
                    X2In, Y2In, Z2In : Integer;
                    X3In, Y3In, Z3In : Integer;
                    X4In, Y4In, Z4In : Integer);
Var CurrentFacet : FacetPtr;
Begin
     If Polygon^.FirstFacet = Nil
     Then
     Begin
          New(Polygon^.FirstFacet);
          CurrentFacet := Polygon^.FirstFacet;
     End
     Else
     Begin
          CurrentFacet := Polygon^.FirstFacet;
          While CurrentFacet^.NextFacet <> Nil do
                CurrentFacet := CurrentFacet^.NextFacet;
          New(CurrentFacet^.NextFacet);
          CurrentFacet := CurrentFacet^.NextFacet;
     End;
     CurrentFacet^.Color := Color;
     CurrentFacet^.X1 := X1In;
     CurrentFacet^.X2 := X2In;
     CurrentFacet^.X3 := X3In;
     CurrentFacet^.X4 := X4In;
     CurrentFacet^.Y1 := Y1In;
     CurrentFacet^.Y2 := Y2In;
     CurrentFacet^.Y3 := Y3In;
     CurrentFacet^.Y4 := Y4In;
     CurrentFacet^.Z1 := Z1In;
     CurrentFacet^.Z2 := Z2In;
     CurrentFacet^.Z3 := Z3In;
     CurrentFacet^.Z4 := Z4In;
     CurrentFacet^.NextFacet := Nil;
End;
{-[ Initialize a New Polygon ]---------------------------------------------}
Procedure InitializePolygon (Var PolyHead               : PolyHPtr;
                                 XIn, YIn, ZIn          : Integer;
                                 RollIn, PitchIn, YawIn : Integer);
Begin
     If PolyHead = Nil
     Then
     Begin
          New(PolyHead);
          PolyHead^.X := XIn;
          PolyHead^.Y := YIn;
          PolyHead^.Z := ZIn;
          PolyHead^.AX := RollIn;
          PolyHead^.AY := PitchIn;
          PolyHead^.AZ := YawIn;
          PolyHead^.FirstFacet := Nil;
     End;
End;
{-[ Dispose Polygon ]------------------------------------------------------}
Procedure DisposePolygon (Var PolyHead : PolyHPtr);
Var TempPtr : FacetPtr;
    TP2     : FacetPtr;
Begin
     TempPtr := PolyHead^.FirstFacet;
     While TempPtr <> Nil do
     Begin
          TP2 := TempPtr^.NextFacet;
          Dispose (TempPtr);
          TempPtr := TP2;
     End;
     Dispose (PolyHead);
     PolyHead := Nil;
End;
{-[ Rotate Polygon About Axies ]-------------------------------------------}
Procedure RotatePolygon (Var PolyHead   : PolyHPtr;
                             DX, DY, DZ : Integer);
Begin
     INC (PolyHead^.AX, DX);
     INC (PolyHead^.AY, DY);
     INC (PolyHead^.AZ, DZ);
     While (PolyHead^.AX > 360) do
           DEC(PolyHead^.AX, 360);
     While (PolyHead^.AY > 360) do
           DEC(PolyHead^.AY, 360);
     While (PolyHead^.AZ > 360) do
           DEC(PolyHead^.AZ, 360);
     While (PolyHead^.AX < -360) do
           INC(PolyHead^.AX, 360);
     While (PolyHead^.AY < -360) do
           INC(PolyHead^.AY, 360);
     While (PolyHead^.AZ < -360) do
           INC(PolyHead^.AZ, 360);
End;
{=[ Graphics Related Routines ]============================================}
{-[ Build Facet Edge ]-----------------------------------------------------}
Procedure DrawLine (X1In, Y1In,
                    X2In, Y2In  : Integer;
                    Color       : Byte);
Var dx, dy : Integer;
    ix, iy : Integer;
    X,  Y  : Integer;
    PX, PY : Integer;
    i      : Integer;
    incc   : Integer;
    plot   : Boolean;
Begin
     dx := X1In - X2In;
     dy := Y1In - Y2In;
     ix := abs(dx);
     iy := abs(dy);
     X  := 0;
     Y  := 0;
     PX := X1In;
     PY := Y1In;
     AddRasterToPoly (PolyList^, PX, PY);
     If ix > iy
     Then
         incc := ix
     Else
         incc := iy;
     i := 0;
     While (i <= incc) do
     Begin
          Inc (X, ix);
          Inc (Y, iy);
          Plot := False;
          If X > incc
          Then
          Begin
               Plot := True;
               Dec (X, incc);
               If dx < 0
               Then
                   Inc(PX)
               Else
                   Dec(PX);
          End;
          If Y > incc
          Then
          Begin
               Plot := True;
               Dec (Y, incc);
               If dy < 0
               Then
                   Inc(PY)
               Else
                   Dec(PY);
          End;
          If Plot
          Then
              AddRasterToPoly (PolyList^, PX, PY);
          Inc(i);
     End;
End;
{-[ Draw Polygon ]---------------------------------------------------------}
Procedure DrawPolygon3D (PolyHead : PolyHPtr;
                         Buffer   : VGAPtr);
Var CurrentFacet               : FacetPtr;
    CalcX1, CalcY1, CalcZ1,
    CalcX2, CalcY2, CalcZ2,
    CalcX3, CalcY3, CalcZ3,
    CalcX4, CalcY4, CalcZ4     : Integer;
    XPrime1, YPrime1, ZPrime1,
    XPrime2, YPrime2, ZPrime2,
    XPrime3, YPrime3, ZPrime3,
    XPrime4, YPrime4, ZPrime4  : Integer;
    Temp                       : Integer;
    CTX, STX,
    CTY, STY,
    CTZ, STZ  : Real;
Begin
     CurrentFacet := PolyHead^.FirstFacet;
     While CurrentFacet <> Nil do
       With CurrentFacet^ do
       Begin
            ClearPolyList (PolyList^);
            XPrime1 := X1; YPrime1 := Y1; ZPrime1 := Z1;
            XPrime2 := X2; YPrime2 := Y2; ZPrime2 := Z2;
            XPrime3 := X3; YPrime3 := Y3; ZPrime3 := Z3;
            XPrime4 := X4; YPrime4 := Y4; ZPrime4 := Z4;
            { Rotate Coords }
            CTX := COS(PolyHead^.AX * PI / 180);
            STX := SIN(PolyHead^.AX * PI / 180);
            CTY := COS(PolyHead^.AY * PI / 180);
            STY := SIN(PolyHead^.AY * PI / 180);
            CTZ := COS(PolyHead^.AZ * PI / 180);
            STZ := SIN(PolyHead^.AZ * PI / 180);
            Temp    := Round((YPrime1 * CTX) - (ZPrime1 * STX));
            ZPrime1 := Round((YPrime1 * STX) + (ZPrime1 * CTX));
            YPrime1 := Temp;
            Temp    := Round((XPrime1 * CTY) - (ZPrime1 * STY));
            ZPrime1 := Round((XPrime1 * STY) + (ZPrime1 * CTY));
            XPrime1 := Temp;
            Temp    := Round((XPrime1 * CTZ) - (YPrime1 * STZ));
            YPrime1 := Round((XPrime1 * STZ) + (YPrime1 * CTZ));
            XPrime1 := Temp;
            Temp    := Round((YPrime2 * CTX) - (ZPrime2 * STX));
            ZPrime2 := Round((YPrime2 * STX) + (ZPrime2 * CTX));
            YPrime2 := Temp;
            Temp    := Round((XPrime2 * CTY) - (ZPrime2 * STY));
            ZPrime2 := Round((XPrime2 * STY) + (ZPrime2 * CTY));
            XPrime2 := Temp;
            Temp    := Round((XPrime2 * CTZ) - (YPrime2 * STZ));
            YPrime2 := Round((XPrime2 * STZ) + (YPrime2 * CTZ));
            XPrime2 := Temp;
            Temp    := Round((YPrime3 * CTX) - (ZPrime3 * STX));
            ZPrime3 := Round((YPrime3 * STX) + (ZPrime3 * CTX));
            YPrime3 := Temp;
            Temp    := Round((XPrime3 * CTY) - (ZPrime3 * STY));
            ZPrime3 := Round((XPrime3 * STY) + (ZPrime3 * CTY));
            XPrime3 := Temp;
            Temp    := Round((XPrime3 * CTZ) - (YPrime3 * STZ));
            YPrime3 := Round((XPrime3 * STZ) + (YPrime3 * CTZ));
            XPrime3 := Temp;
            Temp    := Round((YPrime4 * CTX) - (ZPrime4 * STX));
            ZPrime4 := Round((YPrime4 * STX) + (ZPrime4 * CTX));
            YPrime4 := Temp;
            Temp    := Round((XPrime4 * CTY) - (ZPrime4 * STY));
            ZPrime4 := Round((XPrime4 * STY) + (ZPrime4 * CTY));
            XPrime4 := Temp;
            Temp    := Round((XPrime4 * CTZ) - (YPrime4 * STZ));
            YPrime4 := Round((XPrime4 * STZ) + (YPrime4 * CTZ));
            XPrime4 := Temp;
            { Translate Coords }
            XPrime1 := PolyHead^.X + XPrime1;
            YPrime1 := PolyHead^.Y + YPrime1;
            ZPrime1 := PolyHead^.Z + ZPrime1;
            XPrime2 := PolyHead^.X + XPrime2;
            YPrime2 := PolyHead^.Y + YPrime2;
            ZPrime2 := PolyHead^.Z + ZPrime2;
            XPrime3 := PolyHead^.X + XPrime3;
            YPrime3 := PolyHead^.Y + YPrime3;
            ZPrime3 := PolyHead^.Z + ZPrime3;
            XPrime4 := PolyHead^.X + XPrime4;
            YPrime4 := PolyHead^.Y + YPrime4;
            ZPrime4 := PolyHead^.Z + ZPrime4;
            { Translate 3D Vectorspace to 2D Framespace }
            CalcX1 := 160 + ((LongInt(XPrime1)*ViewerDist) DIV
                             (ZPrime1+ViewerDist));
            CalcY1 := 100 + ((LongInt(YPrime1)*ViewerDist) DIV
                             (ZPrime1+ViewerDist));
            CalcX2 := 160 + ((LongInt(XPrime2)*ViewerDist) DIV
                             (ZPrime2+ViewerDist));
            CalcY2 := 100 + ((LongInt(YPrime2)*ViewerDist) DIV
                             (ZPrime2+ViewerDist));
            CalcX3 := 160 + ((LongInt(XPrime3)*ViewerDist) DIV
                             (ZPrime3+ViewerDist));
            CalcY3 := 100 + ((LongInt(YPrime3)*ViewerDist) DIV
                             (ZPrime3+ViewerDist));
            CalcX4 := 160 + ((LongInt(XPrime4)*ViewerDist) DIV
                             (ZPrime4+ViewerDist));
            CalcY4 := 100 + ((LongInt(YPrime4)*ViewerDist) DIV
                             (ZPrime4+ViewerDist));
            { Draw Shape }
            DrawLine (CalcX1, CalcY1, CalcX2, CalcY2, Color);
            DrawLine (CalcX2, CalcY2, CalcX3, CalcY3, Color);
            DrawLine (CalcX3, CalcY3, CalcX4, CalcY4, Color);
            DrawLine (CalcX4, CalcY4, CalcX1, CalcY1, Color);
            DrawPolyFromList (PolyList^, WorkPage^, Color);
            CurrentFacet := CurrentFacet^.NextFacet;
       End;
End;
{-[ Build Background ]-----------------------------------------------------}
Procedure BuildBackground (Var BufferIn : VGAArray);
Var CounterX,
    CounterY  : Integer;
Begin
     For CounterY := 0 to 199 do
      For CounterX := 0 to 319 do
          BufferIn[CounterY, CounterX] := 1 + ((CounterY MOD 5) * 5) +
                                               (CounterX MOD 5);
End;
{-[ Build Palette ]--------------------------------------------------------}
Procedure BuildPalette (Var PaletteOut : PaletteType);
Const BC = 16;
Var Counter1,
    Counter2  : Integer;
Begin
     FillChar (PaletteOut, SizeOf(PaletteOut), 0);
     For Counter1 := 0 to 4 do
     For Counter2 := 1 to 2 do
     Begin
          PaletteOut[1+(Counter1 * 5)+Counter2].Red   := BC+(Counter2 * 5);
          PaletteOut[1+(Counter1 * 5)+Counter2].Green := BC+(Counter2 * 5);
          PaletteOut[1+(Counter1 * 5)+Counter2].Blue  := BC+(Counter2 * 5);
          PaletteOut[1+(Counter1 * 5)+4-Counter2].Red   := BC+(Counter2 * 5);
          PaletteOut[1+(Counter1 * 5)+4-Counter2].Green := BC+(Counter2 * 5);
          PaletteOut[1+(Counter1 * 5)+4-Counter2].Blue  := BC+(Counter2 * 5);
     End;
     For Counter1 := 0 to 4 do
     Begin
          If PaletteOut[1+(5 * 1)+Counter1].Red < BC + 5
          Then
          Begin
              PaletteOut[1+(5 * 1)+Counter1].Red   := BC + 5;
              PaletteOut[1+(5 * 1)+Counter1].Green := BC + 5;
              PaletteOut[1+(5 * 1)+Counter1].Blue  := BC + 5;
              PaletteOut[1+(5 * 3)+Counter1].Red   := BC + 5;
              PaletteOut[1+(5 * 3)+Counter1].Green := BC + 5;
              PaletteOut[1+(5 * 3)+Counter1].Blue  := BC + 5;
          End;
          PaletteOut[1+(5 * 2)+Counter1].Red   := BC + 10;
          PaletteOut[1+(5 * 2)+Counter1].Green := BC + 10;
          PaletteOut[1+(5 * 2)+Counter1].Blue  := BC + 10;
     End;
     For Counter1 := 0 to 24 do
     Begin
      PaletteOut[32+Counter1].Red   := ((PaletteOut[Counter1].Red* 8)+
                                        (26 * 24)) DIV 32;
      PaletteOut[32+Counter1].Green := ((PaletteOut[Counter1].Green* 8)+
                                        (0  * 24)) DIV 32;
      PaletteOut[32+Counter1].Blue  := ((PaletteOut[Counter1].Blue* 8)+
                                        (0  * 24)) DIV 32;
      PaletteOut[64+Counter1].Red   := ((PaletteOut[Counter1].Red* 8)+
                                        (0  * 24)) DIV 32;
      PaletteOut[64+Counter1].Green := ((PaletteOut[Counter1].Green* 8)+
                                        (26 * 24)) DIV 32;
      PaletteOut[64+Counter1].Blue  := ((PaletteOut[Counter1].Blue* 8)+
                                        (0  * 24)) DIV 32;
      PaletteOut[128+Counter1].Red   := ((PaletteOut[Counter1].Red* 8)+
                                        (0  * 24)) DIV 32;
      PaletteOut[128+Counter1].Green := ((PaletteOut[Counter1].Green* 8)+
                                        (0  * 24)) DIV 32;
      PaletteOut[128+Counter1].Blue  := ((PaletteOut[Counter1].Blue* 8)+
                                        (26 * 24)) DIV 32;
      PaletteOut[32+64+Counter1].Red   := ((PaletteOut[Counter1].Red* 6)+
                                        (23 * 26)) DIV 32;
      PaletteOut[32+64+Counter1].Green := ((PaletteOut[Counter1].Green* 6)+
                                        (23 * 26)) DIV 32;
      PaletteOut[32+64+Counter1].Blue  := ((PaletteOut[Counter1].Blue* 6)+
                                        (0  * 26)) DIV 32;
      PaletteOut[32+128+Counter1].Red   := ((PaletteOut[Counter1].Red* 6)+
                                        (23 * 26)) DIV 32;
      PaletteOut[32+128+Counter1].Green := ((PaletteOut[Counter1].Green* 6)+
                                        (0  * 26)) DIV 32;
      PaletteOut[32+128+Counter1].Blue  := ((PaletteOut[Counter1].Blue* 6)+
                                        (23 * 26)) DIV 32;
      PaletteOut[64+128+Counter1].Red   := ((PaletteOut[Counter1].Red* 6)+
                                        (0  * 26)) DIV 32;
      PaletteOut[64+128+Counter1].Green := ((PaletteOut[Counter1].Green* 6)+
                                        (23 * 26)) DIV 32;
      PaletteOut[64+128+Counter1].Blue  := ((PaletteOut[Counter1].Blue* 6)+
                                        (23 * 26)) DIV 32;
     End;
End;
{-[ Move Background by Moving Palette ]------------------------------------}
Procedure MoveBackground (Var PaletteIn : PaletteType);
Var TempPal : Array[0..5] of PaletteRec;
Begin
     {-- Move Background Colors --}
     Move (PaletteIn[1], TempPal[0], 5 * 3);
     Move (PaletteIn[1+5], PaletteIn[1], ((5 * 4) * 3));
     Move (TempPal[0], PaletteIn[1 + (5 * 4)], 5 * 3);
     {-- Move See-Through Colors --}
     { Red }
     Move (PaletteIn[32], TempPal[0], 6 * 3);
     Move (PaletteIn[32+5], PaletteIn[32], ((5 * 4) * 3));
     Move (TempPal[0], PaletteIn[32 + (5 * 4)], 6 * 3);
     { Green }
     Move (PaletteIn[64], TempPal[0], 6 * 3);
     Move (PaletteIn[64+5], PaletteIn[64], ((5 * 4) * 3));
     Move (TempPal[0], PaletteIn[64 + (5 * 4)], 6 * 3);
     { Blue }
     Move (PaletteIn[128], TempPal[0], 6 * 3);
     Move (PaletteIn[128+5], PaletteIn[128], ((5 * 4) * 3));
     Move (TempPal[0], PaletteIn[128 + (5 * 4)], 6 * 3);
     { Red + Green }
     Move (PaletteIn[(32 OR 64)], TempPal[0], 6 * 3);
     Move (PaletteIn[(32 OR 64)+5], PaletteIn[(32 OR 64)], ((5 * 4) * 3));
     Move (TempPal[0], PaletteIn[(32 OR 64) + (5 * 4)], 6 * 3);
     { Red + Blue }
     Move (PaletteIn[(32 OR 128)], TempPal[0], 6 * 3);
     Move (PaletteIn[(32 OR 128)+5], PaletteIn[(32 OR 128)], ((5 * 4) * 3));
     Move (TempPal[0], PaletteIn[(32 OR 128) + (5 * 4)], 6 * 3);
     { Green + Blue }
     Move (PaletteIn[(64 OR 128)], TempPal[0], 6 * 3);
     Move (PaletteIn[(64 OR 128)+5], PaletteIn[(64 OR 128)], ((5 * 4) * 3));
     Move (TempPal[0], PaletteIn[(64 OR 128) + (5 * 4)], 6 * 3);
End;
{-[ Set Palette ]----------------------------------------------------------}
Procedure SetPalette (Var PaletteIn : PaletteType); Assembler;
ASM
   PUSH DS
   LDS SI, PaletteIn { Sets whole palette at once...       }
   MOV CX, 256 * 3   {  *NOT* good practice since many VGA }
   MOV DX, 03DAh     {  cards will show snow at the top of }
   @WaitNotVSync:    {  of the screen.  It's done here     }
     IN  AL, DX      {  'cause the background animation    }
     AND AL, 8       {  requires large ammounts of the     }
   JNZ @WaitNotVSync {  palette to be updated every new    }
   @WaitVSync:       {  frame.                             }
     IN  AL, DX
     AND AL, 8
   JZ @WaitVSync
   XOR AX, AX
   MOV DX, 03C8h
   OUT DX, AL
   INC DX
   @PaletteLoop:
     LODSB
     OUT DX, AL
   LOOP @PaletteLoop
   POP DS
End;
{=[ Main Program ]=========================================================}
Var Polygon1 : PolyHPtr;
Begin
     VGAMEM := Ptr($A000, $0000);
     New (WorkPage);
     New (BkgPage);
     New (Palette);
     New (PolyList);
     ClearPolyList (PolyList^);
     GoMode13h;
     BuildBackground (BkgPage^);
     BuildPalette    (Palette^);
     SetPalette (Palette^);
     Polygon1 := Nil;
     InitializePolygon (Polygon1,  { Polygon List Head         }
                        0, 0, 60,  { X, Y, Z of polygon        }
                        0, 0, 0);  { Iniitial Roll, Pitch, Yaw }
     AddFacet (Polygon1,       { Polygon List Head        }
                32,            { Color                    }
               -40, -40,  50,  { One Corner of Polygon    }
                40, -40,  50,  { Second Corner of Polygon }
                40,  40,  50,  { Third Corner of Polygon  }
               -40,  40,  50); { Last Corner of Polygon   }
     AddFacet (Polygon1,
                64,
               -50, -40, -40,
               -50, -40,  40,
               -50,  40,  40,
               -50,  40, -40);
     AddFacet (Polygon1,
               128,
                40, -50, -40,
                40, -50,  40,
               -40, -50,  40,
               -40, -50, -40);
     Repeat
           { Clear Workpage }
           WorkPage^ := BkgPage^;
           ClearPolyList (PolyList^);
           DrawPolygon3D (Polygon1,    { Polygon Definition }
                          WorkPage);   { Work buffer        }
           MoveBackground (Palette^);
           SetPalette     (Palette^);
           { Display Work Buffer }
           VGAMEM^ := WorkPage^;
           RotatePolygon (Polygon1,
                          5, 10, 1);
     Until Keypressed;
     DisposePolygon (Polygon1);
     Dispose (PolyList);
     Dispose (Palette);
     Dispose (BkgPage);
     Dispose (WorkPage);
     TextMode (C80);
End.
