{   Polygon Fills Source file                  }
{   PHRO!                                      }
{   Phred/OTM                                  }
{   achalfin@uceng.uc.edu                      }
{   DO NOT DISTRIBUTE THIS SOURCE FILE         }
Unit Polygons;
{$G+}

Interface

Const
  MinX = 0;
  MinY = 0;
  MaxX = 319;
  MaxY = 199;

Procedure GouraudClipPolygon(x1, y1, x2, y2, x3, y3, C1, C2, C3, PgSeg : Integer);
Procedure PhongClipPolygon(x1, y1, x2, y2, x3, y3, t1, p1, t2, p2, t3, p3, PgSeg : Integer; EMap : Pointer);

Implementation

Var
  EnvMap : Pointer;


Procedure GouraudPoly(X1, Y1, X2, Y2, X3, Y3, C1, C2, C3, PgSeg : Integer);

Var
  xTop, yTop : Integer;
  xBot, yBot : Integer;
  xMid, yMid : Integer;
  cTop, cBot, cMid : Integer;
  Count : Integer;
  xVal1, xStep1 : Integer;
  xVal2, xStep2 : Integer;
  cVal1, cStep1 : Integer;
  DColor : Integer;
  crMid : Integer;
  xrMid : Integer;
  hCount, cVal : Integer;

Begin
  Asm
    Mov  ax,Y1
    Mov  bx,X1
    Mov  cx,Y2
    Mov  dx,X2
    Mov  si,C1
    Mov  di,C2

    Mov  xTop,bx
    Mov  yTop,ax
    Mov  xBot,dx
    Mov  yBot,cx
    Mov  cTop,si
    Mov  cBot,di
    Cmp  ax,cx
    Jle @Skip2Top
      Mov  xTop,dx
      Mov  yTop,cx
      Mov  xBot,bx
      Mov  yBot,ax
      Mov  cTop,di
      Mov  cBot,si
   @Skip2Top:
    Mov  ax,Y3
    Mov  bx,X3
    Mov  cx,C3
    Cmp  ax,yTop
    Jge @CheckY3Bottom
      Mov  dx,yTop
      Mov  yMid,dx
      Mov  dx,xTop
      Mov  xMid,dx
      Mov  dx,cTop
      Mov  cMid,dx
      Mov  yTop,ax
      Mov  xTop,bx
      Mov  cTop,cx
      Jmp @Fini
   @CheckY3Bottom:
      Cmp ax,yBot
      Jle @Y3Mid
        Mov  dx,yBot
        Mov  yMid,dx
        Mov  dx,xBot
        Mov  xMid,dx
        Mov  dx,cBot
        Mov  cMid,dx
        Mov  yBot,ax
        Mov  xBot,bx
        Mov  cBot,cx
        Jmp @Fini
     @Y3Mid:
        Mov  yMid,ax
        Mov  xMid,bx
        Mov  cMid,cx
   @Fini:
  End;

  If (yBot-yTop) = 0
    Then Begin
      xrMid := xMid;
      crMid := cMid;
    End
    Else Begin
      xrMid := (yMid-yTop)*(xBot-xTop) Div (yBot-yTop) + xTop;
      crMid := (yMid-yTop)*(cBot-cTop) Div (yBot-yTop) + cTop;
    End;

  Asm
    Mov  es,PgSeg
  End;

  If xMid < XrMid
    Then Begin
      DColor := (crMid-cMid) Shl 8 Div (xrMid-xMid+1);

      cVal1 := cTop Shl 8;
      xVal1 := xTop Shl 6;
      xVal2 := xVal1;
      xStep1 := (xMid-xTop) Shl 6 Div (yMid-yTop+1);
      cStep1 := (cMid-cTop) Shl 8 Div (yMid-yTop+1);
      xStep2 := (xBot-xTop) Shl 6 Div (yBot-yTop+1);
      For Count := yTop to yMid do
        Begin
          Asm
            Mov  bx,Count
            Mov  dx,bx
            Shl  bx,6
            Add  bh,dl
            Mov  di,bx

            Mov  ax,Word Ptr [xVal1]
            Shr  ax,6
            Mov  cx,Word Ptr [xVal2]
            Shr  cx,6

            Add  di,ax

            Sub  cx,ax
            Inc  cx
            Js   @Exit
            Mov  bx,dColor
            Mov  ax,cVal1
            Shr  cx,1
            Jnc @SkipSingle
            Mov  es:[di],ah
            Add  ax,bx
            Inc  di
           @SkipSingle:
            Jcxz @Exit
           @Looper:
            Mov  dl,ah
            Add  ax,bx
            Mov  dh,ah
            Add  ax,bx
            Mov  es:[di],dx
            Add  di,2
            Dec  cx
            Jnz  @Looper
           @Exit:
          End;
          Inc(cVal1, cStep1);
          Inc(xVal1, xStep1);
          Inc(xVal2, xStep2);
        End;

      xVal2 := xVal2 - xStep2;

      cVal1 := cMid Shl 8;
      xVal1 := xMid Shl 6;
      xStep1 := (xBot-xMid) Shl 6 Div (yBot-yMid+1);
      cStep1 := (cBot-cMid) Shl 8 Div (yBot-yMid+1);
      For Count := yMid to yBot do
        Begin
          Asm
            Mov  bx,Count
            Mov  dx,bx
            Shl  bx,6
            Add  bh,dl
            Mov  di,bx

            Mov  ax,Word Ptr [xVal1]
            Shr  ax,6
            Mov  cx,Word Ptr [xVal2]
            Shr  cx,6
            Add  di,ax

            Sub  cx,ax
            Inc  cx
            Js   @Exit
            Jcxz @Exit
            Mov  bx,dColor
            Mov  ax,cVal1
            Shr  cx,1
            Jnc @SkipSingle
            Mov  es:[di],ah
            Add  ax,bx
            Inc  di
           @SkipSingle:
            Jcxz @Exit
           @Looper:
            Mov  dl,ah
            Add  ax,bx
            Mov  dh,ah
            Add  ax,bx
            Mov  es:[di],dx
            Add  di,2
            Dec  cx
            Jnz  @Looper
           @Exit:
          End;
          Inc(cVal1, cStep1);
          Inc(xVal1, xStep1);
          Inc(xVal2, xStep2);
        End;
    End
    Else Begin
      DColor := (cMid-crMid) Shl 8 Div (xMid-xrMid+1);

      cVal1 := cTop Shl 8;
      xVal1 := (xTop) Shl 6;
      xVal2 := xVal1;
      xStep1 := (xBot-xTop) Shl 6 Div (yBot-yTop+1);
      cStep1 := (cBot-cTop) Shl 8 Div (yBot-yTop+1);
      xStep2 := (xMid-xTop) Shl 6 Div (yMid-yTop+1);

      For Count := yTop to yMid do
        Begin
          Asm
            Mov  bx,Count
            Mov  dx,bx
            Shl  bx,6
            Add  bh,dl
            Mov  di,bx

            Mov  ax,Word Ptr [xVal1]
            Shr  ax,6
            Mov  cx,Word Ptr [xVal2]
            Shr  cx,6
            Add  di,ax

            Sub  cx,ax
            Inc  cx
            Js   @Exit
            Jcxz @Exit
            Mov  bx,dColor
            Mov  ax,cVal1
            Shr  cx,1
            Jnc @SkipSingle
            Mov  es:[di],ah
            Add  ax,bx
            Inc  di
           @SkipSingle:
            Jcxz @Exit
           @Looper:
            Mov  dl,ah
            Add  ax,bx
            Mov  dh,ah
            Add  ax,bx
            Mov  es:[di],dx
            Add  di,2
            Dec  cx
            Jnz  @Looper
           @Exit:
          End;
          Inc(cVal1, cStep1);
          Inc(xVal1, xStep1);
          Inc(xVal2, xStep2);
        End;

      xVal1 := xVal1 - xStep1;
      cVal1 := cVal1 - cStep1;
      xVal2 := (xMid) Shl 6;
      xStep2 := (xBot-xMid) Shl 6 Div (yBot-yMid+1);
      For Count := yMid to yBot do
        Begin
          Asm
            Mov  bx,Count
            Mov  dx,bx
            Shl  bx,6
            Add  bh,dl
            Mov  di,bx

            Mov  ax,Word Ptr [xVal1]
            Shr  ax,6
            Mov  cx,Word Ptr [xVal2]
            Shr  cx,6

            Add  di,ax

            Sub  cx,ax
            Inc  cx
            Js   @Exit
            Jcxz @Exit
            Mov  bx,dColor
            Mov  ax,cVal1
            Shr  cx,1
            Jnc @SkipSingle
            Mov  es:[di],ah
            Add  ax,bx
            Inc  di
           @SkipSingle:
            Jcxz @Exit
           @Looper:
            Mov  dl,ah
            Add  ax,bx
            Mov  dh,ah
            Add  ax,bx
            Mov  es:[di],dx
            Add  di,2
            Dec  cx
            Jnz  @Looper
           @Exit:
          End;
          Inc(cVal1, cStep1);
          Inc(xVal1, xStep1);
          Inc(xVal2, xStep2);
        End;
    End;

End;

Procedure GouraudClipPolygon(x1, y1, x2, y2, x3, y3, C1, C2, C3, PgSeg : Integer);

Type
  tFlatClip = Record
    x, y, x1, y1 : Integer;
    c, c1 : Integer;
  End;

Var
  FlatList : Array[0..7] of tFlatClip;
  NumVert : Integer;
  Count : Integer;
  ClipVert : Integer;
  V1, V2 : Integer;

Begin
  If (((X1 >= MinX) and (X1 <= MaxX)) and ((Y1 >= MinY) and (Y1 <= MaxY)) and
      ((X2 >= MinX) and (X2 <= MaxX)) and ((Y2 >= MinY) and (Y2 <= MaxY))) and
      ((X3 >= MinX) and (X3 <= MaxX)) and ((Y3 >= MinY) and (Y3 <= MaxY))
      Then Begin
        GouraudPoly(X1, Y1, X2, Y2, X3, Y3, C1, C2, C3, PgSeg);
        Exit;
      End;
  FlatList[0].x := X1;
  FlatList[0].y := Y1;
  FlatList[0].c := C1;
  FlatList[1].x := X2;
  FlatList[1].y := Y2;
  FlatList[1].c := C2;
  FlatList[2].x := X3;
  FlatList[2].y := Y3;
  FlatList[2].c := C3;
  NumVert := 3;
  ClipVert := 0;
  { Clip against left side }
  V1 := NumVert - 1;
  For Count := 0 to (NumVert-1) do
    Begin
      If (FlatList[V1].x >= MinX) and (FlatList[Count].x >= MinX)
        Then Begin
          FlatList[ClipVert].x1 := FlatList[Count].x;
          FlatList[ClipVert].y1 := FlatList[Count].y;
          FlatList[ClipVert].c1 := FlatList[Count].c;
          ClipVert := ClipVert + 1;
        End;
      If (FlatList[V1].x >= MinX) and (FlatList[Count].x < MinX)
        Then Begin
          FlatList[ClipVert].x1 := MinX;
          FlatList[ClipVert].y1 := (FlatList[Count].y-FlatList[V1].y)*(MinX-FlatList[v1].x)
                                    Div (FlatList[Count].x-FlatList[V1].x) + FlatList[V1].y;
          FlatList[ClipVert].c1 := (FlatList[Count].c-FlatList[V1].c)*(MinX-FlatList[v1].x)
                                    Div (FlatList[Count].x-FlatList[V1].x) + FlatList[V1].c;
          ClipVert := ClipVert + 1;
        End;
      If (FlatList[V1].x < MinX) and (FlatList[Count].x >= MinX)
        Then Begin
          FlatList[ClipVert].x1 := MinX;
          FlatList[ClipVert].y1 := (FlatList[Count].y-FlatList[V1].y)*(MinX-FlatList[V1].x)
                                    Div (FlatList[Count].x-FlatList[V1].x) + FlatList[v1].y;
          FlatList[ClipVert].c1 := (FlatList[Count].c-FlatList[V1].c)*(MinX-FlatList[V1].x)
                                    Div (FlatList[Count].x-FlatList[V1].x) + FlatList[v1].c;
          ClipVert := ClipVert + 1;
          FlatList[ClipVert].x1 := FlatList[Count].x;
          FlatList[ClipVert].y1 := FlatList[Count].y;
          FlatList[ClipVert].c1 := FlatList[Count].c;
          ClipVert := ClipVert + 1;
        End;
      V1 := Count;
    End;
  NumVert := ClipVert;
  ClipVert := 0;
  { Clip against Right side }
  V1 := NumVert - 1;
  For Count := 0 to (NumVert-1) do
    Begin
      If (FlatList[v1].x1 <= MaxX) and (FlatList[Count].x1 <= MaxX)
        Then Begin
          FlatList[ClipVert].x := FlatList[Count].x1;
          FlatList[ClipVert].y := FlatList[Count].y1;
          FlatList[ClipVert].c := FlatList[Count].c1;
          ClipVert := ClipVert + 1;
        End;
      If (FlatList[V1].x1 <= MaxX) and (FlatList[Count].x1 > MaxX)
        Then Begin
          FlatList[ClipVert].x := MaxX;
          FlatList[ClipVert].y := (FlatList[Count].y1-FlatList[V1].y1)*(MaxX-FlatList[v1].x1)
                                   Div (FlatList[Count].x1-FlatList[v1].x1) + FlatList[v1].y1;
          FlatList[ClipVert].c := (FlatList[Count].c1-FlatList[V1].c1)*(MaxX-FlatList[v1].x1)
                                   Div (FlatList[Count].x1-FlatList[v1].x1) + FlatList[v1].c1;
          ClipVert := ClipVert + 1;
        End;
      If (FlatList[v1].x1 > MaxX) and (FlatList[Count].x1 <= MaxX)
        Then Begin
          FlatList[ClipVert].x := MaxX;
          FlatList[ClipVert].y := (FlatList[Count].y1-FlatList[V1].y1)*(MaxX-FlatList[v1].x1)
                                   Div (FlatList[Count].x1-FlatList[v1].x1) + FlatList[v1].y1;
          FlatList[ClipVert].c := (FlatList[Count].c1-FlatList[V1].c1)*(MaxX-FlatList[v1].x1)
                                   Div (FlatList[Count].x1-FlatList[v1].x1) + FlatList[v1].c1;
          ClipVert := ClipVert + 1;
          FlatList[ClipVert].x := FlatList[Count].x1;
          FlatList[ClipVert].y := FlatList[Count].y1;
          FlatList[ClipVert].c := FlatList[Count].c1;
          ClipVert := ClipVert + 1;
        End;
      v1 := Count;
    End;
  NumVert := ClipVert;
  ClipVert := 0;
  { Clip against top edge }
  V1 := NumVert - 1;
  For Count := 0 to (NumVert-1) do
    Begin
      If (FlatList[V1].y >= MinY) and (FlatList[Count].y >= MinY)
        Then Begin
          FlatList[ClipVert].x1 := FlatList[Count].x;
          FlatList[ClipVert].y1 := FlatList[Count].y;
          FlatList[ClipVert].c1 := FlatList[Count].c;
          ClipVert := ClipVert + 1;
        End;
      If (FlatList[V1].y >= MinY) and (FlatList[Count].y < MinY)
        Then Begin
          FlatList[ClipVert].x1 := (MinY-FlatList[V1].y)*(FlatList[Count].x-FlatList[V1].x)
                                           Div (FlatList[Count].y-FlatList[V1].y) + FlatList[V1].x;
          FlatList[ClipVert].c1 := (MinY-FlatList[V1].y)*(FlatList[Count].c-FlatList[V1].c)
                                           Div (FlatList[Count].y-FlatList[V1].y) + FlatList[V1].c;
          FlatList[ClipVert].y1 := MinY;
          ClipVert := ClipVert + 1;
        End;
      If (FlatList[V1].y < MinY) and (FlatList[Count].y >= MinY)
        Then Begin
          FlatList[ClipVert].x1 := (MinY-FlatList[V1].y)*(FlatList[Count].x-FlatList[V1].x)
                                    Div (FlatList[Count].y-FlatList[V1].y) + FlatList[V1].x;
          FlatList[ClipVert].c1 := (MinY-FlatList[V1].y)*(FlatList[Count].c-FlatList[V1].c)
                                    Div (FlatList[Count].y-FlatList[V1].y) + FlatList[V1].c;
          FlatList[ClipVert].y1 := MinY;
          ClipVert := ClipVert + 1;
          FlatList[ClipVert].x1 := FlatList[Count].x;
          FlatList[ClipVert].y1 := FlatList[Count].y;
          FlatList[ClipVert].c1 := FlatList[Count].c;
          ClipVert := ClipVert + 1;
        End;
      V1 := Count;
    End;
  NumVert := ClipVert;
  ClipVert := 0;
  V1 := NumVert - 1;
  For Count := 0 to (NumVert-1) do
    Begin
      If (FlatList[V1].y1 <= MaxY) and (FlatList[Count].y1 <= MaxY)
        Then Begin
          FlatList[ClipVert].x := FlatList[Count].x1;
          FlatList[ClipVert].y := FlatList[Count].y1;
          FlatList[ClipVert].c := FlatList[Count].c1;
          ClipVert := ClipVert + 1;
        End;
      If (FlatList[V1].y1 <= MaxY) and (FlatList[Count].y1 > MaxY)
        Then Begin
          FlatList[ClipVert].x := (MaxY-FlatList[V1].y1)*(FlatList[Count].x1-FlatList[V1].x1)
                                    Div (FlatList[Count].y1-FlatList[v1].y1) + FlatList[V1].x1;
          FlatList[ClipVert].c := (MaxY-FlatList[V1].y1)*(FlatList[Count].c1-FlatList[V1].c1)
                                    Div (FlatList[Count].y1-FlatList[v1].y1) + FlatList[V1].c1;
          FlatList[ClipVert].y := MaxY;
          ClipVert := ClipVert + 1;
        End;
      If (FlatList[V1].y1 > MaxY) and (FlatList[Count].y1 <= MaxY)
        Then Begin
          FlatList[ClipVert].x := (MaxY-FlatList[V1].y1)*(FlatList[Count].x1-FlatList[V1].x1)
                                    Div (FlatList[Count].y1-FlatList[v1].y1) + FlatList[V1].x1;
          FlatList[ClipVert].c := (MaxY-FlatList[V1].y1)*(FlatList[Count].c1-FlatList[V1].c1)
                                    Div (FlatList[Count].y1-FlatList[v1].y1) + FlatList[V1].c1;
          FlatList[ClipVert].y := MaxY;
          ClipVert := ClipVert + 1;
          FlatList[ClipVert].x := FlatList[Count].x1;
          FlatList[ClipVert].y := FlatList[Count].y1;
          FlatList[ClipVert].c := FlatList[Count].c1;
          ClipVert := ClipVert + 1;
        End;
      V1 := Count;
    End;
  NumVert := ClipVert;

  V1 := 1;
  V2 := 2;

  { Now draw the polygons }
  For Count := 0 to (NumVert - 3) do
    Begin
      GouraudPoly(FlatList[0].x, FlatList[0].y,
                  FlatList[V1].x, FlatList[V1].y,
                  FlatList[V2].x, FlatList[V2].y,
                  FlatList[0].c, FlatList[V1].c,
                  FlatList[V2].c, PgSeg);
      V1 := V2;
      V2 := V2 + 1;
    End;
End;


Procedure PhongPoly(X1, Y1, X2, Y2, X3, Y3, p1, t1, p2, t2, p3, t3, PgSeg : Integer);

Var
  xTop, yTop, pTop, tTop : Integer;
  xMid, yMid, pMid, tMid : Integer;
  xBot, yBot, pBot, tBot : Integer;
  xVal1, xStep1, xVal2, xStep2 : Integer;
  tVal1, tStep1 : Integer;
  pVal1, pStep1 : Integer;
  Count : Integer;
  xrMid, prMid, trMid : Integer;
  pVal, tVal : Integer;
  HCount : Integer;
  DPhi, DTheta : Integer;
  Segment : Word;
  yDiver : Integer;

Begin
  If Y1 < Y2
    Then Begin
      yTop := Y1;
      xTop := X1;
      pTop := p1;
      tTop := t1;
      yBot := Y2;
      xBot := X2;
      pBot := p2;
      tBot := t2;
    End
    Else Begin
      yTop := Y2;
      xTop := X2;
      pTop := p2;
      tTop := t2;
      yBot := Y1;
      xBot := X1;
      pBot := p1;
      tBot := t1;
    End;
  If Y3 < yTop
    Then Begin
      yMid := yTop;
      xMid := xTop;
      tMid := tTop;
      pMid := pTop;
      xTop := X3;
      yTop := Y3;
      pTop := p3;
      tTop := t3;
    End
    Else Begin
      If Y3 > yBot
        Then Begin
          yMid := yBot;
          xMid := xBot;
          pMid := pBot;
          tMid := tBot;
          xBot := X3;
          yBot := Y3;
          pBot := p3;
          tBot := t3;
        End
        Else Begin
          yMid := Y3;
          xMid := X3;
          pMid := p3;
          tMid := t3;
        End;
    End;

  If yBot-yTop = 0 Then Exit;

  Segment := PgSeg;

  yDiver := (yMid-yTop) Shl 8 Div (yBot-yTop);
  Asm
    Mov  ax,xBot
    Sub  ax,xTop
    Mov  bx,yDiver
    IMul bx
    Sar  ax,8
    Add  ax,xTop
    Mov  xrMid,ax

    Mov  ax,pBot
    Sub  ax,pTop
    IMul bx
    Sar  ax,8
    Add  ax,pTop
    Mov  prMid,ax

    Mov  ax,tBot
    Sub  ax,tTop
    IMul bx
    Sar  ax,8
    Add  ax,tTop
    Mov  trMid,ax
  End;

{  xrMid := (yMid-yTop)*(xBot-xTop) Div (yBot-yTop) + xTop;
  prMid := (yMid-yTop)*(pBot-pTop) Div (yBot-yTop) + pTop;
  trMid := (yMid-yTop)*(tBot-tTop) Div (yBot-yTop) + tTop;
}

  If xMid < xrMid
    Then Begin    { 2 edges are on the left side }
      DPhi := (prMid-pMid) Shl 8 Div (xrMid-xMid+1);
      DTheta := (trMid-tMid) Shl 8 Div (xrMid-xMid+1);

      xVal1 := xTop Shl 6;
      xVal2 := xVal1;
      tVal1 := tTop Shl 8;
      pVal1 := pTop Shl 8;

      xStep1 := (xMid-xTop) Shl 6 Div (yMid-yTop+1);
      tStep1 := (tMid-tTop) Shl 8 Div (yMid-yTop+1);
      pStep1 := (pMid-pTop) Shl 8 Div (yMid-yTop+1);
      xStep2 := (xBot-xTop) Shl 6 Div (yBot-yTop+1);

      For Count := yTop to yMid do
        Begin
          { ***** HLine *****}
          Asm
            Mov  ax,Segment
            Mov  es,ax

            Mov  ax,xVal1
            Shr  ax,6
            Mov  cx,xVal2
            Shr  cx,6
            Sub  cx,ax
            Inc  cx
            Js   @Exit
            Jcxz @Exit
            

            Mov  bx,Count
            Mov  dx,bx
            Shl  bx,6
            Add  bh,dl
            Add  bx,ax
            Mov  di,bx

            Mov  ax,pVal1
            Mov  si,dPhi
            Mov  dx,tVal1
            
            Push bp
            Mov  bp,dTheta
            Push ds
            Lds  bx,EnvMap

            Shr  cx,1
            Jnc @SkipSingle
             Mov  bh,ah
             Mov  bl,dh
             Mov  ch,ds:[bx]
             Mov  es:[di],ch
             Add  ax,si
             Add  dx,bp
             Inc  di
           @SkipSingle:

            Xor  ch,ch
            Jcxz @SkipLoop
           @Looper:
            Mov  bh,ah
            Mov  bl,dh
            Mov  ch,ds:[bx]
            Mov  es:[di],ch
            Add  ax,si
            Add  dx,bp
            Inc  di
            Mov  bh,ah
            Mov  bl,dh
            Mov  ch,ds:[bx]
            Mov  es:[di],ch
            Add  ax,si
            Add  dx,bp
            Inc  di
            Dec  cl
            Jnz  @Looper
           @SkipLoop:

            Pop  ds
            Pop  bp
           @Exit:
           
          End;
          { ***** End HLine ***** }
          xVal1 := xVal1 + xStep1;
          xVal2 := xVal2 + xStep2;
          pVal1 := pVal1 + pStep1;
          tVal1 := tVal1 + tStep1;
        End;


      xVal2 := xVal2 - xStep2;
      tVal1 := tMid Shl 8;
      pVal1 := pMid Shl 8;
      xVal1 := xMid Shl 6;
      tStep1 := (tBot-tMid) Shl 8 Div (yBot-yMid+1);
      pStep1 := (pBot-pMid) Shl 8 Div (yBot-yMid+1);
      xStep1 := (xBot-xMid) Shl 6 Div (yBot-yMid+1);

      For Count := yMid to yBot do
        Begin
          { ***** HLine *****}
          Asm
            Mov  ax,Segment
            Mov  es,ax

            Mov  ax,xVal1
            Shr  ax,6
            Mov  cx,xVal2
            Shr  cx,6
            Sub  cx,ax
            Inc  cx
            Js   @Exit
            Jcxz @Exit
            

            Mov  bx,Count
            Mov  dx,bx
            Shl  bx,6
            Add  bh,dl
            Add  bx,ax
            Mov  di,bx

            Mov  ax,pVal1
            Mov  si,dPhi
            Mov  dx,tVal1
            
            Push bp
            Mov  bp,dTheta
            Push ds
            Lds  bx,EnvMap

            Shr  cx,1
            Jnc @SkipSingle
             Mov  bh,ah
             Mov  bl,dh
             Mov  ch,ds:[bx]
             Mov  es:[di],ch
             Add  ax,si
             Add  dx,bp
             Inc  di
           @SkipSingle:

            Xor  ch,ch
            Jcxz @SkipLoop
           @Looper:
            Mov  bh,ah
            Mov  bl,dh
            Mov  ch,ds:[bx]
            Mov  es:[di],ch
            Add  ax,si
            Add  dx,bp
            Inc  di
            Mov  bh,ah
            Mov  bl,dh
            Mov  ch,ds:[bx]
            Mov  es:[di],ch
            Add  ax,si
            Add  dx,bp
            Inc  di
            Dec  cl
            Jnz  @Looper
           @SkipLoop:

            Pop  ds
            Pop  bp
           @Exit:
           
          End;
          { ***** End HLine ***** }
          xVal1 := xVal1 + xStep1;
          xVal2 := xVal2 + xStep2;
          pVal1 := pVal1 + pStep1;
          tVal1 := tVal1 + tStep1;
        End;


    End
    Else Begin  { Long Edge on the left side }
      DPhi := (pMid-prMid) Shl 8 Div (xMid-xrMid+1);
      DTheta := (tMid-trMid) Shl 8 Div (xMid-xrMid+1);

      xVal1 := xTop Shl 6;
      tVal1 := tTop Shl 8;
      pVal1 := pTop Shl 8;
      xVal2 := xVal1;
      xStep1 := (xBot-xTop) Shl 6 Div (yBot-yTop+1);
      tStep1 := (tBot-tTop) Shl 8 Div (yBot-yTop+1);
      pStep1 := (pBot-pTop) Shl 8 Div (yBot-yTop+1);
      xStep2 := (xMid-xTop) Shl 6 Div (yMid-yTop+1);
      For Count := yTop to yMid do
        Begin
          { ***** HLine *****}
          Asm
            Mov  ax,Segment
            Mov  es,ax

            Mov  ax,xVal1
            Shr  ax,6
            Mov  cx,xVal2
            Shr  cx,6
            Sub  cx,ax
            Inc  cx
            Js   @Exit
            Jcxz @Exit
            

            Mov  bx,Count
            Mov  dx,bx
            Shl  bx,6
            Add  bh,dl
            Add  bx,ax
            Mov  di,bx

            Mov  ax,pVal1
            Mov  si,dPhi
            Mov  dx,tVal1
            
            Push bp
            Mov  bp,dTheta
            Push ds
            Lds  bx,EnvMap

            Shr  cx,1
            Jnc @SkipSingle
             Mov  bh,ah
             Mov  bl,dh
             Mov  ch,ds:[bx]
             Mov  es:[di],ch
             Add  ax,si
             Add  dx,bp
             Inc  di
           @SkipSingle:

            Xor  ch,ch
            Jcxz @SkipLoop
           @Looper:
            Mov  bh,ah
            Mov  bl,dh
            Mov  ch,ds:[bx]
            Mov  es:[di],ch
            Add  ax,si
            Add  dx,bp
            Inc  di
            Mov  bh,ah
            Mov  bl,dh
            Mov  ch,ds:[bx]
            Mov  es:[di],ch
            Add  ax,si
            Add  dx,bp
            Inc  di
            Dec  cl
            Jnz  @Looper
           @SkipLoop:

            Pop  ds
            Pop  bp
           @Exit:
           
          End;
          { ***** End HLine ***** }
          xVal1 := xVal1 + xStep1;
          xVal2 := xVal2 + xStep2;
          pVal1 := pVal1 + pStep1;
          tVal1 := tVal1 + tStep1;
        End;

      tVal1 := tVal1 - tStep1;
      pVal1 := pVal1 - pStep1;
      xVal1 := xVal1 - xStep1;
      xStep2 := (xBot-xMid) Shl 6 Div (yBot-yMid+1);
      For Count := yMid to yBot do
        Begin
          { ***** HLine *****}
          Asm
            Mov  ax,Segment
            Mov  es,ax

            Mov  ax,xVal1
            Shr  ax,6
            Mov  cx,xVal2
            Shr  cx,6
            Sub  cx,ax
            Inc  cx
            Js   @Exit
            Jcxz @Exit
            

            Mov  bx,Count
            Mov  dx,bx
            Shl  bx,6
            Add  bh,dl
            Add  bx,ax
            Mov  di,bx

            Mov  ax,pVal1
            Mov  si,dPhi
            Mov  dx,tVal1
            
            Push bp
            Mov  bp,dTheta
            Push ds
            Lds  bx,EnvMap

            Shr  cx,1
            Jnc @SkipSingle
             Mov  bh,ah
             Mov  bl,dh
             Mov  ch,ds:[bx]
             Mov  es:[di],ch
             Add  ax,si
             Add  dx,bp
             Inc  di
           @SkipSingle:

            Xor  ch,ch
            Jcxz @SkipLoop
           @Looper:
            Mov  bh,ah
            Mov  bl,dh
            Mov  ch,ds:[bx]
            Mov  es:[di],ch
            Add  ax,si
            Add  dx,bp
            Inc  di
            Mov  bh,ah
            Mov  bl,dh
            Mov  ch,ds:[bx]
            Mov  es:[di],ch
            Add  ax,si
            Add  dx,bp
            Inc  di
            Dec  cl
            Jnz  @Looper
           @SkipLoop:

            Pop  ds
            Pop  bp
           @Exit:
           
          End;
          { ***** End HLine ***** }
          xVal1 := xVal1 + xStep1;
          xVal2 := xVal2 + xStep2;
          pVal1 := pVal1 + pStep1;
          tVal1 := tVal1 + tStep1;
        End;
    End;

End;





Procedure PhongClipPolygon(x1, y1, x2, y2, x3, y3, t1, p1, t2, p2, t3, p3, PgSeg : Integer; EMap : Pointer);

Type
  tFlatClip = Record
    x, y, x1, y1 : Integer;
    t, p, t1, p1 : Integer;
  End;

Var
  FlatList : Array[0..7] of tFlatClip;
  NumVert : Integer;
  Count : Integer;
  ClipVert : Integer;
  V1, V2 : Integer;

Begin
  EnvMap := EMap;
  If (((X1 >= MinX) and (X1 <= MaxX)) and ((Y1 >= MinY) and (Y1 <= MaxY)) and
      ((X2 >= MinX) and (X2 <= MaxX)) and ((Y2 >= MinY) and (Y2 <= MaxY))) and
      ((X3 >= MinX) and (X3 <= MaxX)) and ((Y3 >= MinY) and (Y3 <= MaxY))
      Then Begin
        PhongPoly(X1, Y1, X2, Y2, X3, Y3, p1, t1, p2, t2, p3, t3, PgSeg);
        Exit;
      End;
  FlatList[0].x := X1;
  FlatList[0].y := Y1;
  FlatList[0].t := t1;
  FlatList[0].p := p1;
  FlatList[1].x := X2;
  FlatList[1].y := Y2;
  FlatList[1].t := t2;
  FlatList[1].p := p2;
  FlatList[2].x := X3;
  FlatList[2].y := Y3;
  FlatList[2].t := t3;
  FlatList[2].p := p3;
  NumVert := 3;
  ClipVert := 0;
  { Clip against left side }
  V1 := NumVert - 1;
  For Count := 0 to (NumVert-1) do
    Begin
      If (FlatList[V1].x >= MinX) and (FlatList[Count].x >= MinX)
        Then Begin
          FlatList[ClipVert].x1 := FlatList[Count].x;
          FlatList[ClipVert].y1 := FlatList[Count].y;
          FlatList[ClipVert].t1 := FlatList[Count].t;
          FlatList[ClipVert].p1 := FlatList[Count].p;
          ClipVert := ClipVert + 1;
        End;
      If (FlatList[V1].x >= MinX) and (FlatList[Count].x < MinX)
        Then Begin
          FlatList[ClipVert].x1 := MinX;
          FlatList[ClipVert].y1 := (FlatList[Count].y-FlatList[V1].y)*(MinX-FlatList[v1].x)
                                    Div (FlatList[Count].x-FlatList[V1].x) + FlatList[V1].y;
          FlatList[ClipVert].t1 := (FlatList[Count].t-FlatList[V1].t)*(MinX-FlatList[v1].x)
                                    Div (FlatList[Count].x-FlatList[V1].x) + FlatList[V1].t;
          FlatList[ClipVert].p1 := (FlatList[Count].p-FlatList[V1].p)*(MinX-FlatList[v1].x)
                                    Div (FlatList[Count].x-FlatList[V1].x) + FlatList[V1].p;
          ClipVert := ClipVert + 1;
        End;
      If (FlatList[V1].x < MinX) and (FlatList[Count].x >= MinX)
        Then Begin
          FlatList[ClipVert].x1 := MinX;
          FlatList[ClipVert].y1 := (FlatList[Count].y-FlatList[V1].y)*(MinX-FlatList[V1].x)
                                    Div (FlatList[Count].x-FlatList[V1].x) + FlatList[v1].y;
          FlatList[ClipVert].t1 := (FlatList[Count].t-FlatList[V1].t)*(MinX-FlatList[V1].x)
                                    Div (FlatList[Count].x-FlatList[V1].x) + FlatList[v1].t;
          FlatList[ClipVert].p1 := (FlatList[Count].p-FlatList[V1].p)*(MinX-FlatList[V1].x)
                                    Div (FlatList[Count].x-FlatList[V1].x) + FlatList[v1].p;
          ClipVert := ClipVert + 1;
          FlatList[ClipVert].x1 := FlatList[Count].x;
          FlatList[ClipVert].y1 := FlatList[Count].y;
          FlatList[ClipVert].t1 := FlatList[Count].t;
          FlatList[ClipVert].p1 := FlatList[Count].p;
          ClipVert := ClipVert + 1;
        End;
      V1 := Count;
    End;
  NumVert := ClipVert;
  ClipVert := 0;
  { Clip against Right side }
  V1 := NumVert - 1;
  For Count := 0 to (NumVert-1) do
    Begin
      If (FlatList[v1].x1 <= MaxX) and (FlatList[Count].x1 <= MaxX)
        Then Begin
          FlatList[ClipVert].x := FlatList[Count].x1;
          FlatList[ClipVert].y := FlatList[Count].y1;
          FlatList[ClipVert].t := FlatList[Count].t1;
          FlatList[ClipVert].p := FlatList[Count].p1;
          ClipVert := ClipVert + 1;
        End;
      If (FlatList[V1].x1 <= MaxX) and (FlatList[Count].x1 > MaxX)
        Then Begin
          FlatList[ClipVert].x := MaxX;
          FlatList[ClipVert].y := (FlatList[Count].y1-FlatList[V1].y1)*(MaxX-FlatList[v1].x1)
                                   Div (FlatList[Count].x1-FlatList[v1].x1) + FlatList[v1].y1;
          FlatList[ClipVert].t := (FlatList[Count].t1-FlatList[V1].t1)*(MaxX-FlatList[v1].x1)
                                   Div (FlatList[Count].x1-FlatList[v1].x1) + FlatList[v1].t1;
          FlatList[ClipVert].p := (FlatList[Count].p1-FlatList[V1].p1)*(MaxX-FlatList[v1].x1)
                                   Div (FlatList[Count].x1-FlatList[v1].x1) + FlatList[v1].p1;
          ClipVert := ClipVert + 1;
        End;
      If (FlatList[v1].x1 > MaxX) and (FlatList[Count].x1 <= MaxX)
        Then Begin
          FlatList[ClipVert].x := MaxX;
          FlatList[ClipVert].y := (FlatList[Count].y1-FlatList[V1].y1)*(MaxX-FlatList[v1].x1)
                                   Div (FlatList[Count].x1-FlatList[v1].x1) + FlatList[v1].y1;
          FlatList[ClipVert].t := (FlatList[Count].t1-FlatList[V1].t1)*(MaxX-FlatList[v1].x1)
                                   Div (FlatList[Count].x1-FlatList[v1].x1) + FlatList[v1].t1;
          FlatList[ClipVert].p := (FlatList[Count].p1-FlatList[V1].p1)*(MaxX-FlatList[v1].x1)
                                   Div (FlatList[Count].x1-FlatList[v1].x1) + FlatList[v1].p1;
          ClipVert := ClipVert + 1;
          FlatList[ClipVert].x := FlatList[Count].x1;
          FlatList[ClipVert].y := FlatList[Count].y1;
          FlatList[ClipVert].t := FlatList[Count].t1;
          FlatList[ClipVert].p := FlatList[Count].p1;
          ClipVert := ClipVert + 1;
        End;
      v1 := Count;
    End;
  NumVert := ClipVert;
  ClipVert := 0;
  { Clip against top edge }
  V1 := NumVert - 1;
  For Count := 0 to (NumVert-1) do
    Begin
      If (FlatList[V1].y >= MinY) and (FlatList[Count].y >= MinY)
        Then Begin
          FlatList[ClipVert].x1 := FlatList[Count].x;
          FlatList[ClipVert].y1 := FlatList[Count].y;
          FlatList[ClipVert].t1 := FlatList[Count].t;
          FlatList[ClipVert].p1 := FlatList[Count].p;
          ClipVert := ClipVert + 1;
        End;
      If (FlatList[V1].y >= MinY) and (FlatList[Count].y < MinY)
        Then Begin
          FlatList[ClipVert].x1 := (MinY-FlatList[V1].y)*(FlatList[Count].x-FlatList[V1].x)
                                           Div (FlatList[Count].y-FlatList[V1].y) + FlatList[V1].x;
          FlatList[ClipVert].t1 := (MinY-FlatList[V1].y)*(FlatList[Count].t-FlatList[V1].t)
                                           Div (FlatList[Count].y-FlatList[V1].y) + FlatList[V1].t;
          FlatList[ClipVert].p1 := (MinY-FlatList[V1].y)*(FlatList[Count].p-FlatList[V1].p)
                                           Div (FlatList[Count].y-FlatList[V1].y) + FlatList[V1].p;
          FlatList[ClipVert].y1 := MinY;
          ClipVert := ClipVert + 1;
        End;
      If (FlatList[V1].y < MinY) and (FlatList[Count].y >= MinY)
        Then Begin
          FlatList[ClipVert].x1 := (MinY-FlatList[V1].y)*(FlatList[Count].x-FlatList[V1].x)
                                    Div (FlatList[Count].y-FlatList[V1].y) + FlatList[V1].x;
          FlatList[ClipVert].t1 := (MinY-FlatList[V1].y)*(FlatList[Count].t-FlatList[V1].t)
                                    Div (FlatList[Count].y-FlatList[V1].y) + FlatList[V1].t;
          FlatList[ClipVert].p1 := (MinY-FlatList[V1].y)*(FlatList[Count].p-FlatList[V1].p)
                                    Div (FlatList[Count].y-FlatList[V1].y) + FlatList[V1].p;
          FlatList[ClipVert].y1 := MinY;
          ClipVert := ClipVert + 1;
          FlatList[ClipVert].x1 := FlatList[Count].x;
          FlatList[ClipVert].y1 := FlatList[Count].y;
          FlatList[ClipVert].t1 := FlatList[Count].t;
          FlatList[ClipVert].p1 := FlatList[Count].p;
          ClipVert := ClipVert + 1;
        End;
      V1 := Count;
    End;
  NumVert := ClipVert;
  ClipVert := 0;
  V1 := NumVert - 1;
  For Count := 0 to (NumVert-1) do
    Begin
      If (FlatList[V1].y1 <= MaxY) and (FlatList[Count].y1 <= MaxY)
        Then Begin
          FlatList[ClipVert].x := FlatList[Count].x1;
          FlatList[ClipVert].y := FlatList[Count].y1;
          FlatList[ClipVert].t := FlatList[Count].t1;
          FlatList[ClipVert].p := FlatList[Count].p1;
          ClipVert := ClipVert + 1;
        End;
      If (FlatList[V1].y1 <= MaxY) and (FlatList[Count].y1 > MaxY)
        Then Begin
          FlatList[ClipVert].x := (MaxY-FlatList[V1].y1)*(FlatList[Count].x1-FlatList[V1].x1)
                                    Div (FlatList[Count].y1-FlatList[v1].y1) + FlatList[V1].x1;
          FlatList[ClipVert].t := (MaxY-FlatList[V1].y1)*(FlatList[Count].t1-FlatList[V1].t1)
                                    Div (FlatList[Count].y1-FlatList[v1].y1) + FlatList[V1].t1;
          FlatList[ClipVert].p := (MaxY-FlatList[V1].y1)*(FlatList[Count].p1-FlatList[V1].p1)
                                    Div (FlatList[Count].y1-FlatList[v1].y1) + FlatList[V1].p1;
          FlatList[ClipVert].y := MaxY;
          ClipVert := ClipVert + 1;
        End;
      If (FlatList[V1].y1 > MaxY) and (FlatList[Count].y1 <= MaxY)
        Then Begin
          FlatList[ClipVert].x := (MaxY-FlatList[V1].y1)*(FlatList[Count].x1-FlatList[V1].x1)
                                    Div (FlatList[Count].y1-FlatList[v1].y1) + FlatList[V1].x1;
          FlatList[ClipVert].t := (MaxY-FlatList[V1].y1)*(FlatList[Count].t1-FlatList[V1].t1)
                                    Div (FlatList[Count].y1-FlatList[v1].y1) + FlatList[V1].t1;
          FlatList[ClipVert].p := (MaxY-FlatList[V1].y1)*(FlatList[Count].p1-FlatList[V1].p1)
                                    Div (FlatList[Count].y1-FlatList[v1].y1) + FlatList[V1].p1;
          FlatList[ClipVert].y := MaxY;
          ClipVert := ClipVert + 1;
          FlatList[ClipVert].x := FlatList[Count].x1;
          FlatList[ClipVert].y := FlatList[Count].y1;
          FlatList[ClipVert].t := FlatList[Count].t1;
          FlatList[ClipVert].p := FlatList[Count].p1;
          ClipVert := ClipVert + 1;
        End;
      V1 := Count;
    End;
  NumVert := ClipVert;

  V1 := 1;
  V2 := 2;

  { Now draw the polygons }
  For Count := 0 to (NumVert - 3) do
    Begin
      PhongPoly(FlatList[0].x, FlatList[0].y,
                FlatList[V1].x, FlatList[V1].y,
                FlatList[V2].x, FlatList[V2].y,
                FlatList[0].p, FlatList[0].t,
                FlatList[V1].p, FlatList[V1].t,
                FlatList[V2].p, FlatList[V2].t, PgSeg);
      V1 := V2;
      V2 := V2 + 1;
    End;
End;

End.