home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / games / egagraph.zip / BOXDEMO.PAS < prev    next >
Pascal/Delphi Source File  |  1987-07-23  |  20KB  |  669 lines

  1. program BoxDemo;
  2.  
  3. (* ================================================= *)
  4. (* =  This program demonstraits the fast EGA line  = *)
  5. (* =  drawing routine. The program has other GOOD  = *)
  6. (* =  stuff in it..so use  what you can..any  way  = *)
  7. (* =  you  can..at  you  own  expense..good  luck  = *)
  8. (* =  graphicsing.                                 = *)
  9. (* =                                               = *)
  10. (* =  James Billmeyer                              = *)
  11. (* =  Soft-Touch Computer Systems                  = *)
  12. (* =  7716 Balboa Blvd., Unit D                    = *)
  13. (* =  Van Nuys, Ca. 91406                          = *)
  14. (* =  (818) 781-4400                               = *)
  15. (* ================================================= *)
  16.  
  17.  
  18. const
  19.    middle_horizontal  = 320;
  20.    middle_vertical    = 175;
  21.  
  22.    horizontal_scale   = 1.53241;
  23.    vertical_scale     = 1.0000;
  24.    longitudinal_scale =  0.5005657;
  25.  
  26. (*   ===================================== *)
  27.  
  28. type
  29.    cgtype = string[3];
  30.    str10  = string[10];
  31.  
  32.    border_type     = (DB,NB);
  33.    projection_type = (PARALLEL,PERSPECTIVE);
  34.    model_type      = (LARGE,SMALL);
  35.  
  36.    line_info = record
  37.                   x1,
  38.                   y1,
  39.                   x2,
  40.                   y2,
  41.                   color :  integer;
  42.                end;
  43.  
  44.  
  45.    object_lines = array[1..9] of line_info;
  46.  
  47.  
  48.    coord_type = record
  49.                    x,
  50.                    y,
  51.                    z :  real;
  52.                 end;
  53.  
  54.    object_info = record
  55.                     name                :  string[10];
  56.                     number_of_surface   :  integer;
  57.                     number_of_lines     :  integer;
  58.                     old_number_of_lines :  integer;
  59.                     surface_to_view     :  string[48];
  60.                     lines_to_view       :  string[24];
  61.                     vertex              :  array[1..4] of coord_type;
  62.                     lines               :  object_lines;
  63.                     old_lines           :  object_lines;
  64.                     coord_reset         :  integer;
  65.                     coordinates,
  66.                     end_coordinates     :  coord_type;
  67.                     otheta,
  68.                     ophi,
  69.                     obeta               :  real;
  70.                  end;
  71.  
  72.    trig_type = record
  73.                   sin0,
  74.                   cos0,
  75.                   sin1,
  76.                   cos1,
  77.                   sin2,
  78.                   cos2 : real;
  79.                end;
  80.  
  81.  
  82. var
  83.    projection  : projection_type;
  84.    line        : line_info;
  85.    test,
  86.    oldtest     : object_info;
  87.    trig_set    : trig_type;
  88.    model       : model_type;
  89.  
  90.    xdir,ydir,i,j,
  91.    tx,ty,tz,
  92.    color,
  93.    loop,
  94.    xscrn,yscrn,
  95.    xscrn0,yscrn0,
  96.    total_surfaces,
  97.    wxmin,wymin,wxmax,wymax : integer;
  98.  
  99.    ok,
  100.    dir,firstime  :  boolean;
  101.  
  102.    dist,
  103.    xwrld,ywrld,zwrld,
  104.    theta,beta,phi,
  105.    x_scale,y_scale,z_scale : real;
  106.  
  107.  
  108. procedure drawline(x1,y1,x2,y2,color : integer); External 'LINE.BIN';
  109.  
  110. procedure get_object_from_file(var object: object_info; object_name: str10);
  111.  
  112. (* ================================================ *)
  113. (* =  The get_object_from_file  procedure  loads  = *)
  114. (* =  object information into the arrays.         = *)
  115. (* ================================================ *)
  116.  
  117. begin
  118.    with  object  do
  119.       begin
  120.          name := 'Test';
  121.          number_of_surface := 3;
  122.          lines_to_view   := '123847561328457614352786';
  123.          surface_to_view := '011103090510070901060205021204100612081103080407';
  124.          coordinates.x := 0.00;
  125.          coordinates.y := 0.00;
  126.          coordinates.z := 0.00;
  127.          end_coordinates.x := 0.00;
  128.          end_coordinates.y := 0.00;
  129.          end_coordinates.z := 0.00;
  130.          ophi   := 0.00;
  131.          obeta  := 0.00;
  132.          otheta := 0.00;
  133.          vertex[1].x := -12.00;
  134.          vertex[1].y := -12.00;
  135.          vertex[2].x :=  12.00;
  136.          vertex[2].y := -12.00;
  137.          vertex[3].x := -12.00;
  138.          vertex[3].y := -12.00;
  139.          vertex[4].x := -12.00;
  140.          vertex[4].y :=  12.00;
  141.          vertex[4].z :=  12.00;
  142.          vertex[1].z :=  12.00;
  143.          vertex[2].z :=  12.00;
  144.          vertex[3].z := -12.00;
  145.       end;
  146. end; (* proc Array_load *)
  147.  
  148.  
  149. Procedure Phi_change(var trig_set: trig_type; dir: boolean);
  150.  
  151. (* ================================================ *)
  152. (* =  The procedure Phi_change adds or subtracts  = *)
  153. (* =  from the angle phi depending  on  the  dir  = *)
  154. (* ================================================ *)
  155.  
  156. begin  (* proc Phi_change *)
  157.    if  dir  then
  158.       phi := phi + 0.04
  159.    else
  160.       phi := phi - 0.04;
  161.    trig_set.sin0 := sin(phi);
  162.    trig_set.cos0 := cos(phi);
  163. end;  (* proc Phi_change *)
  164.  
  165.  
  166. Procedure Beta_change(var trig_set: trig_type; dir: boolean);
  167.  
  168. (* ================================================ *)
  169. (* =  The procedure Phi_change adds or subtracts  = *)
  170. (* =  from the angle phi depending  on  the  dir  = *)
  171. (* ================================================ *)
  172.  
  173. begin  (* proc beta_change *)
  174.    if  dir  then
  175.       beta := beta + 0.04
  176.    else
  177.       beta := beta - 0.04;
  178.    trig_set.sin1 := sin(beta);
  179.    trig_set.cos1 := cos(beta);
  180. end;  (* proc beta_change *)
  181.  
  182.  
  183. Procedure theta_change(var trig_set: trig_type; dir: boolean);
  184.  
  185. (* ================================================ *)
  186. (* =  The procedure theta_change add or subtract  = *)
  187. (* =  from the angle phi depending  on  the  dir  = *)
  188. (* ================================================ *)
  189.  
  190. begin  (* proc theta_change *)
  191.    if  dir  then
  192.       theta := theta + 0.05
  193.    else
  194.       theta := theta - 0.05;
  195.    trig_set.sin2 := sin(theta);
  196.    trig_set.cos2 := cos(theta);
  197. end;  (* proc theta_change *)
  198.  
  199.  
  200. procedure Rotate(x,y,z: real; trig_set: trig_type; var xwrld,ywrld,zwrld: real);
  201.  
  202. (* ==================================== *)
  203. (* =  This routine calculates the 3D  = *)
  204. (* =  transformation matrix.          = *)
  205. (* ==================================== *)
  206.  
  207. var
  208.    group1,group2,group3 :  real;
  209.  
  210. begin
  211.    with  trig_set  do
  212.       begin
  213.          group1 := -y * sin0 + z * cos0;
  214.          group2 :=  y * cos0 + z * sin0;
  215.          group3 :=  x * cos1 - group1 * sin1;
  216.          xwrld :=  group3 * cos2 + group2 * sin2;
  217.          ywrld :=  group2 * cos2 - group3 * sin2;
  218.          zwrld :=  x * sin1 - group1 * cos1;
  219.       end;
  220. end;
  221.  
  222.  
  223. Procedure Parallel_projection(var xscrn,yscrn: integer; xwrld,ywrld,zwrld: real);
  224.  
  225. (* ================================================ *)
  226. (* =  Parallel_projection procedure converts      = *)
  227. (* =  world coordinates to screen coordinates in  = *)
  228. (* =  parallel projection.                        = *)
  229. (* ================================================ *)
  230.  
  231. var
  232.    ratio :  real;
  233.  
  234. begin  (* proc Parallel_projection *)
  235.    xscrn := round(middle_horizontal + x_scale * xwrld);
  236.    yscrn := round(middle_vertical   + y_scale * ywrld);
  237. end;   (* proc Parallel_projection *)
  238.  
  239.  
  240. procedure gwindow(xmin,ymin,xmax,ymax: integer; border: border_type);
  241.  
  242. (**************************************************)
  243. (*  This procedure sets the  graphics window and  *)
  244. (*  will draw the window border if directed.      *)
  245. (*        DB => draw border                       *)
  246. (*        NB => no border                         *)
  247. (**************************************************)
  248.  
  249. begin
  250.    wxmin := xmin + 1;
  251.    wymin := ymin + 1;
  252.    wxmax := xmax - 1;
  253.    wymax := ymax - 1;
  254.    if  border = DB  then
  255.       begin
  256.          drawline(xmin,ymin,xmax,ymin,1);
  257.          drawline(xmin,ymax,xmax,ymax,1);
  258.          drawline(xmax,ymin,xmax,ymax,1);
  259.          drawline(xmin,ymin,xmin,ymax,1);
  260.       end;
  261. end;
  262.  
  263.  
  264. procedure clipper(var x1,y1,x2,y2: integer);
  265.  
  266. (**************************************************)
  267. (*  This  procedure  uses  the  Cohen-Sutherland  *)
  268. (*  algorithm for line clipping.                  *)
  269. (**************************************************)
  270.  
  271. type
  272.    outcode = array[1..4] of boolean;
  273.  
  274. var
  275.    accept,reject,done : boolean;
  276.    outcode1,outcode2  : outcode;
  277.  
  278.  
  279.    procedure outcodes(x,y: integer; var outcodeset: outcode);
  280.  
  281.    (**************************************************)
  282.    (*  This procedure returns the  outcodes for the  *)
  283.    (*  point (x,y)                                   *)
  284.    (**************************************************)
  285.  
  286.    var
  287.       i :  integer;
  288.  
  289.    begin
  290.       for  i := 1  to  4  do
  291.          outcodeset[i] := false;
  292.       if  x < wxmin  then
  293.          outcodeset[4] := true
  294.       else if  x > wxmax  then
  295.          outcodeset[3] := true;
  296.       if  y > wymax  then
  297.          outcodeset[2] := true
  298.       else if  y < wymin  then
  299.          outcodeset[1] := true;
  300.    end;
  301.  
  302.  
  303.    function reject_check(outcode1,outcode2: outcode): boolean;
  304.  
  305.    (**************************************************)
  306.    (*  This function checks to see if the line lies  *)
  307.    (*  outside the window.                           *)
  308.    (**************************************************)
  309.  
  310.    var
  311.       i      : integer;
  312.  
  313.    begin
  314.       reject_check := false;
  315.       for  i := 1  to  4  do
  316.          if  (outcode1[i] and outcode2[i])  then
  317.             begin
  318.                reject_check := true;
  319.                i := 4;
  320.             end;
  321.    end;
  322.  
  323.  
  324.    function accept_check(outcode1,outcode2: outcode): boolean;
  325.  
  326.    (**************************************************)
  327.    (*  This function checks to see if the line lies  *)
  328.    (*  inside the window.                            *)
  329.    (**************************************************)
  330.  
  331.    var
  332.       i      : integer;
  333.  
  334.    begin
  335.       accept_check := true;
  336.       for  i := 1  to  4  do
  337.          if  (outcode1[i] or outcode2[i])  then
  338.             accept_check := false;
  339.    end;
  340.  
  341.  
  342.    procedure swap;
  343.  
  344.    (**************************************************)
  345.    (*  This procedure swaps the point1  and  point2  *)
  346.    (*  values.                                       *)
  347.    (**************************************************)
  348.  
  349.    var
  350.       pointemp    : integer;
  351.       outcodetemp : outcode;
  352.  
  353.    begin
  354.       pointemp := x1;
  355.       x1 := x2;
  356.       x2 := pointemp;
  357.       pointemp := y1;
  358.       y1 := y2;
  359.       y2 := pointemp;
  360.       outcodetemp := outcode1;
  361.       outcode1 := outcode2;
  362.       outcode2 := outcodetemp;
  363.    end;
  364.  
  365.  
  366. begin
  367.    accept := false;
  368.    reject := false;
  369.    done   := false;
  370.    outcodes(x1,y1,outcode1);
  371.    outcodes(x2,y2,outcode2);
  372.    repeat
  373.       reject := reject_check(outcode1,outcode2);
  374.       if  reject  then
  375.          done := true
  376.       else
  377.          begin
  378.             accept := accept_check(outcode1,outcode2);
  379.             if  accept  then
  380.                done := true
  381.             else
  382.                begin
  383.                   if  not (outcode1[1] or outcode1[2] or outcode1[3] or outcode1[4])  then
  384.                      swap;
  385.                   if  outcode1[1]  then
  386.                      begin
  387.                         x1 := x1 + (x2 - x1) * (wymin - y1) div (y2 - y1);
  388.                         y1 := wymin;
  389.                      end
  390.                   else if  outcode1[2]  then
  391.                      begin
  392.                         x1 := x1 + (x2 - x1) * (wymax - y1) div (y2 - y1);
  393.                         y1 := wymax;
  394.                      end
  395.                   else if  outcode1[3]  then
  396.                      begin
  397.                         y1 := y1 + (y2 - y1) * (wxmax - x1) div (x2 - x1);
  398.                         x1 := wxmax;
  399.                      end
  400.                   else if  outcode1[4]  then
  401.                      begin
  402.                         y1 := y1 + (y2 - y1) * (wxmin - x1) div (x2 - x1);
  403.                         x1 := wxmin;
  404.                      end
  405.                end;
  406.          end;
  407.          if  not done  then
  408.             outcodes(x1,y1,outcode1);
  409.    until  done;
  410.    if  reject  then
  411.       begin
  412.          x1 := wxmin;
  413.          y1 := wymin;
  414.          x2 := wxmin;
  415.          y2 := wymin;
  416.       end;
  417. end;
  418.  
  419.  
  420. Procedure calc_object_lines(var object: object_info);
  421.  
  422. (* ================================================ *)
  423. (* =  The Draw_Scrn procedure draw an  object on  = *)
  424. (* =  the screen.                                 = *)
  425. (* ================================================ *)
  426.  
  427. const
  428.    surface0  = $A0A;
  429.    surface1  = $AC;
  430.    surface2  = $CC0;
  431.    surface3  = $505;
  432.    surface4  = $53;
  433.    surface5  = $330;
  434.    line_loc : array[1..12] of integer = ($800,$400,$200,$100,$80,$40,$20,$10,$8,$4,$2,$1);
  435. var
  436.    x_wrld,
  437.    y_wrld,
  438.    z_wrld      :  array[1..8] of real;
  439.    i,j,
  440.    sindex,index,
  441.    first,second,
  442.    dummy,
  443.    view_surface,
  444.    line_count,
  445.    lines_drawn,
  446.    line_mask   :  integer;
  447.    x,y,z,
  448.    x_temp,
  449.    y_temp,
  450.    z_temp      :  real;
  451.  
  452. begin  (* proc calculate_lines *)
  453.    for  i := 1  to  4  do
  454.       with  object.vertex[i]  do
  455.          begin
  456.             if  model = SMALL  then
  457.                z := 0;
  458.             Rotate((x + object.coordinates.x),
  459.                    (y + object.coordinates.y),
  460.                    (z + object.coordinates.z),trig_set,xwrld,ywrld,zwrld);
  461.             x_wrld[i] := xwrld;
  462.             y_wrld[i] := ywrld;
  463.             z_wrld[i] := zwrld;
  464.          end;
  465.    x_temp := x_wrld[2] - x_wrld[1];
  466.    y_temp := y_wrld[2] - y_wrld[1];
  467.    z_temp := z_wrld[2] - z_wrld[1];
  468.    x_wrld[8] := x_temp + x_wrld[3];                  x_wrld[7] := x_temp + x_wrld[4];
  469.    x_wrld[5] := x_wrld[3] - x_wrld[1] + x_wrld[4];   x_wrld[6] := x_temp + x_wrld[5];
  470.    y_wrld[8] := y_temp + y_wrld[3];                  y_wrld[7] := y_temp + y_wrld[4];
  471.    y_wrld[5] := y_wrld[3] - y_wrld[1] + y_wrld[4];   y_wrld[6] := y_temp + y_wrld[5];
  472.    z_wrld[8] := z_temp + z_wrld[3];                  z_wrld[7] := z_temp + z_wrld[4];
  473.    z_wrld[5] := z_wrld[3] - z_wrld[1] + z_wrld[4];   z_wrld[6] := z_temp + z_wrld[5];
  474.    with  object  do
  475.       begin
  476.          lines_drawn := 0;
  477.          line_count := 0;
  478.          old_lines := lines;
  479.          old_number_of_lines := number_of_lines;
  480.          if  model = LARGE  then
  481.             begin
  482.                if  int(z_wrld[5] - z_wrld[4]) > 0  then
  483.                   lines_drawn := lines_drawn or surface0
  484.                else if  int(z_wrld[5] - z_wrld[4]) < 0  then
  485.                   lines_drawn := lines_drawn or surface3;
  486.                if  int(z_wrld[7] - z_wrld[4]) < 0  then
  487.                   lines_drawn := lines_drawn or surface1
  488.                else if  int(z_wrld[7] - z_wrld[4]) > 0  then
  489.                   lines_drawn := lines_drawn or surface4;
  490.                if  int(z_wrld[1] - z_wrld[4]) > 0  then
  491.                   lines_drawn := lines_drawn or surface5
  492.                else if  int(z_wrld[1] - z_wrld[4]) < 0  then
  493.                   lines_drawn := lines_drawn or surface2;
  494.             end
  495.          else
  496.             lines_drawn := lines_drawn or $2;
  497.          for  j := 1 to 12  do
  498.             begin
  499.                line_mask := lines_drawn;
  500.                if  (line_mask and line_loc[j]) > 0 then
  501.                   begin
  502.                      line_count := line_count + 1;
  503.                      index := j * 2 - 1;
  504.                      val(copy(lines_to_view,(index),1),first,dummy);
  505.                      val(copy(lines_to_view,(index + 1),1),second,dummy);
  506.                      Parallel_projection(line.x1,line.y1,x_wrld[first],y_wrld[first],z_wrld[first]);
  507.                      Parallel_projection(line.x2,line.y2,x_wrld[second],y_wrld[second],z_wrld[second]);
  508.                      lines[line_count] := line;
  509.                      clipper(lines[line_count].x1,lines[line_count].y1,lines[line_count].x2,lines[line_count].y2);
  510.                   end;
  511.             end;
  512.          number_of_lines := line_count;
  513.       end;
  514. end;  (* proc calculate_lines *)
  515.  
  516.  
  517. Procedure draw_object(var object: object_info);
  518.  
  519. (* ================================================ *)
  520. (* =  The Draw_Scrn procedure draw an  object on  = *)
  521. (* =  the screen.                                 = *)
  522. (* ================================================ *)
  523.  
  524. var
  525.    i :  integer;
  526.  
  527. begin  (* proc Draw_Scrn *)
  528.    with  object  do
  529.       for  i := 1  to  number_of_lines  do
  530.         with  lines[i]  do
  531.           begin
  532.             drawline(x1,y1,x2,y2,i);
  533.           end;
  534. end;  (* proc Draw_Scrn *)
  535.  
  536.  
  537. Procedure erase_object(var object: object_info);
  538.  
  539. (* ================================================ *)
  540. (* =  The Draw_Scrn procedure draw an  object on  = *)
  541. (* =  the screen.                                 = *)
  542. (* ================================================ *)
  543.  
  544. var
  545.    i :  integer;
  546.  
  547. begin  (* proc Draw_Scrn *)
  548.    with  object  do
  549.       for  i := 1  to  old_number_of_lines  do
  550.         with  old_lines[i]  do
  551.           begin
  552.             drawline(x1,y1,x2,y2,0);
  553.           end;
  554. end;  (* proc Draw_Scrn *)
  555.  
  556.  
  557.  
  558. procedure color_display(selection:cgtype);
  559.  
  560. (* ================================================ *)
  561. (* =  The  selectmonitor  procedure  changes the  = *)
  562. (* =  current monitor selection from  monochrome  = *)
  563. (* =  to color graphics or vice-aversa.           = *)
  564. (* ================================================ *)
  565.  
  566. var
  567.    displayvar :  integer absolute $0000:$0410;
  568.  
  569. begin  (* proc colordsply *)
  570.    if  selection = 'on'  then
  571.       begin
  572.          displayvar := (displayvar and 207) or 16;
  573.          hires;
  574.       end
  575.    else if selection = 'off' then
  576.       begin
  577.          displayvar := displayvar or 48;
  578.          textmode;
  579.       end;
  580. end;  (* proc colordsply *)
  581.  
  582.  
  583. procedure SetEGAMode(mode : integer);
  584.  
  585.   type
  586.     regset = record
  587.                ax,bx,cx,dx,bp,si,di,ds,es,flags : integer;
  588.              end;
  589.   var
  590.     registers : regset;
  591.  
  592. begin
  593.   with registers do
  594.     begin
  595.       ax := mode;
  596.       intr($10,registers);
  597.     end;
  598. END;
  599.  
  600.  
  601. procedure EGA43;
  602.  
  603. begin
  604.   inline($b8/$12/$11/         (* mov  ax,1112    *)
  605.          $b3/$00/             (* mov  bl,00      *)
  606.          $cd/$10/             (* int  10         *)
  607.          $2b/$c0/             (* sub  ax,ax      *)
  608.          $1e/                 (* push ds         *)
  609.          $8e/$d8/             (* mov  ds,ax      *)
  610.          $ff/$36/$87/$04/     (* push [0487]     *)
  611.          $80/$0e/$87/$04/$01/ (* or   byte ptr [0487],01 *)
  612.          $b9/$00/$06/         (* mov  cx,06      *)
  613.          $b4/$01/             (* mov  ah,01      *)
  614.          $cd/$10/             (* int  10         *)
  615.          $8f/$06/$87/$04/     (* pop  [0487]     *)
  616.          $1f);                 (* pop  ds         *)
  617.        (*  $ba/$b4/$03/  *)       (* mov  dx,03b4    *)
  618.        (*  $b8/$14/$07/  *)       (* mov  ax,0714    *)
  619.        (*  $ef);         *)       (* out  dx,ax      *)
  620. end;
  621.  
  622. begin (* main program *)
  623.    dir := true;
  624.    tx := 0;
  625.    ty := 0;
  626.    tz := 0;
  627.    dist := 15.0;
  628.    z_scale := longitudinal_scale;
  629.    x_scale := horizontal_scale * (dist / 10);
  630.    y_scale := vertical_scale * (dist / 10);
  631. (*   hires; *)
  632. (*   ega43; *)
  633.    SetEGAMode(18);
  634.    color := 32;
  635.  
  636.    theta := 1.0;
  637.    phi   := 1.0;
  638.    beta  := 1.0;
  639.    Phi_change(trig_set,dir);
  640.    Theta_change(trig_set,dir);
  641.    beta_change(trig_set,dir);
  642.    model := LARGE;
  643.    get_object_from_file(test,'TEST');
  644.    projection := PARALLEL;
  645.    gwindow(250,20,380,199,DB);
  646.    Phi_change(trig_set,dir);
  647.    Theta_change(trig_set,dir);
  648.    beta_change(trig_set,dir);
  649.    calc_object_lines(test);
  650.    draw_object(test);
  651.    Writeln('┌───────┐');
  652.    writeln('│ Start │');
  653.    writeln('└───────┘');
  654.    for  loop := 1  to  500  do
  655.       begin
  656.          Phi_change(trig_set,dir);
  657.          Theta_change(trig_set,dir);
  658.          beta_change(trig_set,dir);
  659.          calc_object_lines(test);
  660.          erase_object(test);
  661.          draw_object(test);
  662.       end;
  663.    Writeln('┌──────┐');
  664.    writeln('│ Done │');
  665.    writeln('└──────┘');
  666.    delay(3000);
  667.    SetEGAMode(03);
  668. end.  (* main program *)
  669.