home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / diverace.zip / SOURCE.ZIP / source / work / gfxfunc.pas < prev    next >
Pascal/Delphi Source File  |  1995-08-27  |  11KB  |  380 lines

  1. (***************************************************************************
  2.   Some Graphics Primitives which access the video-buffer.
  3. ****************************************************************************)
  4.  
  5. Unit GfxFunc;
  6.  
  7. interface
  8.  
  9. uses Use32;
  10.  
  11. type
  12.   pixel = record
  13.             x,y:SmallInt;
  14.           end;
  15.  
  16.  
  17.  
  18.  
  19. Procedure Span(y,x1,x2,c:integer);
  20. Procedure SetPixel(x,y,c:integer);
  21. procedure line(x1,y1,x2,y2,c:integer);
  22. procedure FillTria(p1,p2,p3:pixel;c:integer);
  23. procedure FillQuad(p1,p2,p3,p4:pixel;c:integer);
  24. Procedure OutStr(x,y,fore:integer;s:string);
  25.  
  26. implementation
  27.  
  28. Uses DreiD;
  29.  
  30.  
  31. type
  32.  fix = record case boolean of            (* 32Bit Fixed-Point number *)
  33.           true:(fix:longint);
  34.           false:(f:SmallWord;i:SmallInt);
  35.         end;
  36.  
  37.  
  38. {$I FONT8x8.INC}
  39.  
  40.  
  41. Procedure OutStr(x,y,fore:integer;s:string);
  42. type
  43.   Fontbuff = array[0..32000] of byte;
  44. var
  45.   line,spos,bit,bpos:integer;
  46.   LineBuffer : array[0..640] of byte;
  47.   ScrAddr:integer;
  48. begin
  49.   if length(s)>80 then
  50.     s:=copy(s,1,80);
  51.  
  52.   scraddr:=y*xpels+x;
  53.   for line:=0 to 7 do
  54.   begin
  55.     bpos:=scraddr;
  56.     for spos:=1 to length(s) do
  57.       for bit:=7 downto 0 do
  58.       begin
  59.         if (Font8x8[ord(s[spos]) shl 3+line] shr bit) and 1=1 then
  60.           DispBuffer^[bpos]:=fore;
  61.        (* else
  62.           LineBuffer[bpos]:=back;*)
  63.         inc(bpos);
  64.       end;
  65.     Inc(ScrAddr,xpels);
  66.   end;
  67. end;
  68.  
  69.  
  70.  
  71.  
  72. Procedure Span(y,x1,x2,c:integer);
  73. var h:integer;
  74. begin
  75.   if x1>x2 then begin h:=x1;x1:=x2;x2:=h;end;
  76.   if (y>=0) and (y<=ymax) then (*y in range ?*)
  77.     if (x1>=0) and (x1<=xmax) then
  78.       if (x2>=0) and (x2<=xmax) then
  79.         Fillchar(DispBuffer^[y*xpels+x1],x2-x1+1,c)
  80.       else (*x2 has to be > xmax*)
  81.         Fillchar(DispBuffer^[y*xpels+x1],xmax-x1+1,c)
  82.     else
  83.       if (x2>=0) and (x2<=xmax) then (*x2 ok ?->x1<0*)
  84.         Fillchar(DispBuffer^[y*xpels],x2,c)
  85.       else (*none ok*)
  86.         if (x1<0) and (x2>xmax) then (*x1 left out and x2 on right*)
  87.           Fillchar(DispBuffer^[y*xpels],xmax+1,c);
  88. end;
  89.  
  90.  
  91. Procedure SetPixel(x,y,c:integer);
  92. begin
  93.   if (x>=0) and (x<=xmax) and (y>=0) and (y<=ymax) then
  94.     DispBuffer^[y*xpels+x]:=c;
  95. end;
  96.  
  97.  
  98.  
  99. procedure line(x1,y1,x2,y2,c:integer);
  100. var
  101.   dyDdx,dxDdy,sy,sx:fix;
  102.   dy,dx,h: integer;
  103.  
  104. begin
  105.   dy:=abs(y2-y1);
  106.   dx:=abs(x2-x1);
  107.   if (dx>dy) then
  108.   begin
  109.     if x2<x1 then  {swap x1,x2}
  110.     begin
  111.       h:=x1;
  112.       x1:=x2;
  113.       x2:=h;
  114.       h:=y1;
  115.       y1:=y2;
  116.       y2:=h;
  117.     end;
  118.     SetPixel(x1,y1,c);
  119.     if dx<>0 then
  120.     begin
  121.       sy.i:=y1;
  122.       sy.f:=$8000;
  123.       dyDdx.i:=y2-y1;
  124.       dyDdx.f:=0;
  125.       dyDdx.fix:=dyDdx.fix div dx;
  126.       while x1<x2-1 do
  127.       begin
  128.         INC(x1);
  129.         INC(sy.fix,dyDdx.fix);
  130.         SetPixel(x1,sy.i,c);
  131.       end;
  132.       SetPixel(x2,y2,c);
  133.     end; { Ende mehr als ein Punkt }
  134.   end { Ende dx>dy }
  135.   else
  136.   begin
  137.     if y2<y1 then
  138.     begin
  139.       h:=x1;
  140.       x1:=x2;
  141.       x2:=h;
  142.       h:=y1;
  143.       y1:=y2;
  144.       y2:=h;
  145.     end;
  146.     SetPixel(x1,y1,c);
  147.     if dy<>0 then
  148.     begin
  149.       sx.i:=x1;
  150.       sx.f:=$8000;
  151.       dxDdy.i:=x2-x1;
  152.       dxDdy.f:=0;
  153.       dxDdy.fix:=dxDdy.fix div dy;
  154.       while y1<y2-1 do
  155.       begin
  156.         INC(y1);
  157.         INC(sx.fix,dxDdy.fix);
  158.         setpixel(sx.i,y1,c);
  159.       end;
  160.       SetPixel(x2,y2,c);
  161.     end; { Ende mehr als ein Punkt }
  162.   end; { Ende dy>dx }
  163. end;
  164.  
  165.  
  166. procedure FillTria(p1,p2,p3:pixel;c:integer);
  167.  
  168. var x21,x31,x32,                       (* x-Differenzen der drei Kanten    *)
  169.     y21,y31,y32:integer;               (* y-Differenzen der drei Kanten    *)
  170.     ex,                   (* aktuelle Werte lange Kante (Festkomma 32 Bit) *)
  171.     e1x,                  (* aktuelle Werte kurze Kante (Festkomma 32 Bit) *)
  172.     edx,                  (* Steigungen lange Kante     (Festkomma 32 Bit) *)
  173.     e1dx:fix;             (* Steigungen kurze Kante     (Festkomma 32 Bit) *)
  174.     N: longint;                    (* Nenner Steigung Span (siehe Kasten)  *)
  175.     ph: pixel;                     (* Hilfsvariable zum Sortieren der Pkt. *)
  176. begin
  177.   if LineMode then
  178.   begin
  179.     Line(p1.x,p1.y,p2.x,p2.y,c); (* Nur die Kanten zeichnen   *)
  180.     Line(p2.x,p2.y,p3.x,p3.y,c);
  181.     Line(p3.x,p3.y,p1.x,p1.y,c);
  182.   end else begin
  183.  
  184.     if p1.y>p2.y then begin ph:=p1; p1:=p2; p2:=ph; end; (* p1,p2,p3 sor-  *)
  185.     if p1.y>p3.y then begin ph:=p1; p1:=p3; p3:=ph; end; (* tieren. Es gilt*)
  186.     if p2.y>p3.y then begin ph:=p2; p2:=p3; p3:=ph; end; (* p1y<=p2y<=p3y  *)
  187.  
  188.     y31:=p3.y - p1.y;                         (* Länge der 'langen' Kante  *)
  189.     if y31<>0 then begin                      (* Dreieck keine hor. Linie? *)
  190.       y21:=p2.y-p1.y; x21:=p2.x-p1.x;         (* Differenzen 'kurze' Kante *)
  191.       x31:=p3.x-p1.x;                         (* Breite der langen Kante   *)
  192.       N:=longint(y21)*x31-longint(y31)*x21;   (* Siehe Kasten              *)
  193.       (*if N<>0 then*) begin                      (* kein entartetes Dreieck:  *)
  194.         SetPixel(p1.x,p1.y,c);                (* obersten Punkt ausgeben   *)
  195.         INC(p1.y);                            (* p1.y = treibender Wert    *)
  196.         ex.i:=p1.x; ex.f:=$8000;              (* Anfangswert x lange Kante *)
  197.         edx.i:=x31; edx.f:=0;                 (* dx lange Kante            *)
  198.         edx.fix:=edx.fix div y31;             (* dx/dy lange Kante         *)
  199.         if y21<>0 then begin                  (* Kante (P1,P2) nicht horiz.*)
  200.           e1x.fix:=ex.fix;                    (* Anfangswerte obere kurze  *)
  201.           e1dx.i:=x21; e1dx.f:=0;             (* dx kurze Kante            *)
  202.           e1dx.fix:=e1dx.fix div y21;         (* dx/dy kurze Kante         *)
  203.           while p1.y<p2.y do begin (* für alle Zeilen zwischen p1y u. p2y: *)
  204.             INC(ex.fix,edx.fix);              (* inkrementieren. Als y-Ko- *)
  205.             INC(e1x.fix,e1dx.fix);            (* alle Komponenten von e1   *)
  206.             Span(p1.y,ex.i,e1x.i,c);          (* Span ]e,e1[  *)
  207.             INC(p1.y);                        (* y für e,e1 u. Span weiter *)
  208.           end;                                (* Ende alle Spans über P2   *)
  209.           INC(ex.fix,edx.fix);                (* e inkrementieren. e liegt *)
  210.         end;                        (* Ende Kante (P1,P2) nicht waagerecht *)
  211.         p1.y:=p2.y;                 (* y-Koordinate für e,e1 u. Spans      *)
  212.  
  213.         SetPixel(ex.i,p1.y,c);
  214.         SetPixel(p2.x,p2.y,c);
  215.  
  216.         Span(p1.y,ex.i,p2.x,c);                     (* Span in Höhe P2     *)
  217.         INC(p1.y);                                  (* y einen tiefer      *)
  218.         (* Ab hier folgt nun das gleiche Spiel für die untere kurze Kante.
  219.            Das Prinzip ist identisch, so daß auf Kommentar verzichtet
  220.            wird. (.. wenn Turbo doch Spaltenblöcke kopieren könnte!)       *)
  221.         y32:=p3.y-p2.y;
  222.         if y32<>0 then begin             (* Kante (P2,P3) nicht waagerecht *)
  223.           x32:=p3.x-p2.x;
  224.           e1x.i:=p2.x; e1x.f:=$8000;
  225.           e1dx.i:=x32; e1dx.f:=0; e1dx.fix:=e1dx.fix div y32;
  226.           while p1.y<p3.y do begin
  227.             INC(ex.fix,edx.fix);
  228.             INC(e1x.fix,e1dx.fix);
  229.             Span(p1.y,ex.i,e1x.i,c);
  230.             INC(p1.y);
  231.           end; (* Ende alle Spans  unter P2 *)
  232.         end; (* Ende untere kurze Kante nicht senkrecht *)
  233.         SetPixel(p3.x,p3.y,c);
  234.       end (* Ende kein entartetes Dreieck *)
  235. (*      else
  236.         write(#7);Line(p1.x,p1.y,p3.x,p3.y,c);*)
  237.     end (* Ende keine vertikale Linie *)
  238.     else Line(p1.x,p1.y,p3.x,p3.y,c);
  239.   end; (* Ende trifillenabled *)
  240. end; (* Ende FillTria() *)
  241.  
  242.  
  243. procedure FillQuad(p1,p2,p3,p4:pixel;c:integer);
  244. var l1,l2,l1dx,l2dx:fix;
  245.     ph:pixel;
  246.     under1,under2:boolean;
  247.  
  248.   Procedure AssignLine(var p1,p2:pixel;var l,ldx:fix);(*p2 muß unter p1 sein*)
  249.   var dx,dy:integer;
  250.   begin
  251.     dx:=p2.x-p1.x;
  252.     dy:=p2.y-p1.y;
  253.     l.i:=p1.x;
  254.     l.f:=$8000;
  255.     ldx.i:=dx;
  256.     ldx.f:=0;
  257.     ldx.fix:=ldx.fix div dy;
  258.   end;
  259.  
  260.    (*Füllt zwischen l1 und l2 bis y=ymax*)
  261.  
  262.   Procedure FillBetweenLines(y,ymax:integer);
  263.   begin
  264.     while y<=ymax do
  265.     begin
  266.       inc(l1.fix,l1dx.fix);
  267.       inc(l2.fix,l2dx.fix);
  268.       Span(y,l1.i,l2.i,c);
  269.       inc(y);
  270.     end;
  271.   end;
  272.  
  273. begin
  274.   if p1.y>p2.y then begin ph:=p1; p1:=p2; p2:=ph; end; (* p1,p2,p3,p4 sor*)
  275.   if p1.y>p3.y then begin ph:=p1; p1:=p3; p3:=ph; end; (* tieren. Es gilt*)
  276.   if p1.y>p4.y then begin ph:=p1; p1:=p4; p4:=ph; end;
  277.   if p2.y>p3.y then begin ph:=p2; p2:=p3; p3:=ph; end; (*p1y<=p2y<=p3y<=p4y*)
  278.   if p2.y>p4.y then begin ph:=p2; p2:=p4; p4:=ph; end;
  279.   if p3.y>p4.y then begin ph:=p3; p3:=p4; p4:=ph; end;
  280.  
  281.   if p4.y<>p1.y then
  282.   begin  (*nicht Horizontale Linie ?*)
  283.     if p3.y<>p1.y then
  284.     begin (*Keine Linie+Dreieck ?*)
  285.       if p1.x=p3.x then
  286.       begin
  287.         under1:=p2.x<p1.x;
  288.         under2:=p4.x<p1.x;
  289.       end
  290.       else
  291.       begin
  292.         under1:=p3.y-p2.y<(longint(p3.x-p2.x)*(p3.y-p1.y)) div (p3.x-p1.x);
  293.         under2:=p3.y-p4.y<(longint(p3.x-p4.x)*(p3.y-p1.y)) div (p3.x-p1.x);
  294.       end;
  295.  
  296.       SetPixel(p1.x,p1.y,c);
  297.       if under1 xor under2  then
  298.       begin (*p3 liegt unter der Geraden durch p2-p4*)
  299.         if linemode then
  300.         begin
  301.           Line(p1.x,p1.y,p2.x,p2.y,c); (* Nur die Kanten zeichnen   *)
  302.           Line(p2.x,p2.y,p3.x,p3.y,c);
  303.           Line(p3.x,p3.y,p4.x,p4.y,c);
  304.           Line(p4.x,p4.y,p1.x,p1.y,c);
  305.         end
  306.         else
  307.         begin
  308.           AssignLine(p1,p4,l1,l1dx);
  309.           if p1.y=p2.y then
  310.             Span(p1.y,p1.x,p2.x,c)
  311.           else
  312.           begin
  313.             AssignLine(p1,p2,l2,l2dx);
  314.             FillBetweenLines(p1.y+1,p2.y);
  315.           end;
  316.           if p2.y<>p3.y then
  317.           begin
  318.             AssignLine(p2,p3,l2,l2dx);
  319.             FillBetweenLines(p2.y+1,p3.y);
  320.           end;
  321.           if p3.y<>p4.y then
  322.           begin
  323.             AssignLine(p3,p4,l2,l2dx);
  324.             FillBetweenLines(p3.y+1,p4.y);
  325.           end;
  326.         end;
  327.       end
  328.       else
  329.       begin
  330.         if linemode then
  331.         begin
  332.           Line(p1.x,p1.y,p2.x,p2.y,c); (* Nur die Kanten zeichnen   *)
  333.           Line(p2.x,p2.y,p4.x,p4.y,c);
  334.           Line(p4.x,p4.y,p3.x,p3.y,c);
  335.           Line(p3.x,p3.y,p1.x,p1.y,c);
  336.         end
  337.         else
  338.         begin
  339.           AssignLine(p1,p3,l1,l1dx);
  340.           if p1.y=p2.y then
  341.             Span(p1.y,p1.x,p2.x,c)
  342.           else
  343.           begin
  344.             AssignLine(p1,p2,l2,l2dx);
  345.             FillBetweenLines(p1.y+1,p2.y);
  346.           end;
  347.           if p2.y<>p4.y then
  348.           begin
  349.             AssignLine(p2,p4,l2,l2dx);
  350.             if p2.y<>p3.y then
  351.               FillBetweenLines(p2.y+1,p3.y);
  352.             if p3.y<>p4.y then
  353.             begin
  354.               AssignLine(p3,p4,l1,l1dx);
  355.               FillBetweenLines(p3.y+1,p4.y);
  356.             end;
  357.           end;
  358.         end;
  359.       end;
  360.     end
  361.     else
  362.     begin  (*p1.y=p2.y=p3.y*)
  363.       Span(p1.y,p1.x,p2.x,c);
  364.       Span(p1.y,p1.x,p3.x,c);
  365.       AssignLine(p2,p4,l1,l1dx);
  366.       AssignLine(p3,p4,l2,l2dx);
  367.       FillBetweenLines(p3.y+1,p4.y);
  368.     end;
  369.   end
  370.   else
  371.   begin (*p1=p2=p3=p4*)
  372.     Span(p1.y,p1.x,p2.x,c);
  373.     Span(p1.y,p1.x,p3.x,c);
  374.     Span(p1.y,p1.x,p4.x,c);
  375.   end;
  376. end;
  377.  
  378.  
  379. end.
  380.