Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Portions of this file are copyright Rebirth contributors and licensed as
  3.  * described in COPYING.txt.
  4.  * Portions of this file are copyright Parallax Software and licensed
  5.  * according to the Parallax license below.
  6.  * See COPYING.txt for license details.
  7.  
  8. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  9. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  10. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  11. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  12. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  13. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  14. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  15. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  16. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  17. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  18. */
  19.  
  20. /*
  21.  *
  22.  * Graphical routines for drawing lines.
  23.  *
  24.  */
  25.  
  26. #include <stdlib.h>
  27. #include "u_mem.h"
  28. #include "gr.h"
  29. #include "grdef.h"
  30. #include "maths.h"
  31. #include "clip.h"
  32. #if DXX_USE_OGL
  33. #include "ogl_init.h"
  34. #endif
  35.  
  36. namespace dcx {
  37.  
  38. /*
  39. Symmetric Double Step Line Algorithm
  40. by Brian Wyvill
  41. from "Graphics Gems", Academic Press, 1990
  42. */
  43.  
  44. /* non-zero flag indicates the pixels needing EXCHG back. */
  45. static void plot(grs_canvas &canvas, int x, int y, int flag, const color_palette_index color)
  46. #define plot(x,y,f)     plot(canvas,x,y,f,color)
  47. {
  48.         if (flag)
  49.                 std::swap(x, y);
  50.         gr_upixel(canvas.cv_bitmap, x, y, color);
  51. }
  52.  
  53. static void gr_hline(grs_canvas &canvas, int x1, int x2, const int y, const color_palette_index color)
  54. {
  55.         using std::swap;
  56.         if (x1 > x2)
  57.                 swap(x1,x2);
  58.         for (int i=x1; i<=x2; i++ )
  59.                 gr_upixel(canvas.cv_bitmap, i, y, color);
  60. }
  61.  
  62. static void gr_vline(grs_canvas &canvas, int y1, int y2, const int x, const color_palette_index color)
  63. {
  64.         using std::swap;
  65.         if (y1 > y2) swap(y1,y2);
  66.         for (int i=y1; i<=y2; i++ )
  67.                 gr_upixel(canvas.cv_bitmap, x, i, color);
  68. }
  69.  
  70. static void gr_universal_uline(grs_canvas &canvas, int a1, int b1, int a2, int b2, const color_palette_index color)
  71. {
  72.         int dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left;
  73.         int x1, y1;
  74.         int sign_x = 1, sign_y = 1, step, reverse;
  75.  
  76.         if (a1==a2) {
  77.                 gr_vline(canvas, b1, b2, a1, color);
  78.                 return;
  79.         }
  80.  
  81.         if (b1==b2) {
  82.                 gr_hline(canvas, a1, a2, b1, color);
  83.                 return;
  84.         }
  85.  
  86.         dx = a2 - a1;
  87.         dy = b2 - b1;
  88.  
  89.         if (dx < 0) {
  90.                 sign_x = -1;
  91.                 dx *= -1;
  92.         }
  93.         if (dy < 0) {
  94.                 sign_y = -1;
  95.                 dy *= -1;
  96.         }
  97.  
  98.         /* decide increment sign by the slope sign */
  99.         if (sign_x == sign_y)
  100.                 step = 1;
  101.         else
  102.                 step = -1;
  103.  
  104.         if (dy > dx) {          /* chooses axis of greatest movement (make * dx) */
  105.                 using std::swap;
  106.                 swap(a1, b1);
  107.                 swap(a2, b2);
  108.                 swap(dx, dy);
  109.                 reverse = 1;
  110.         } else
  111.                 reverse = 0;
  112.         /* note error check for dx==0 should be included here */
  113.         if (a1 > a2) {          /* start from the smaller coordinate */
  114.                 x = a2;
  115.                 y = b2;
  116.                 x1 = a1;
  117.                 y1 = b1;
  118.         } else {
  119.                 x = a1;
  120.                 y = b1;
  121.                 x1 = a2;
  122.                 y1 = b2;
  123.         }
  124.  
  125.  
  126.         /* Note dx=n implies 0 - n or (dx+1) pixels to be set */
  127.         /* Go round loop dx/4 times then plot last 0,1,2 or 3 pixels */
  128.         /* In fact (dx-1)/4 as 2 pixels are already plottted */
  129.         xend = (dx - 1) / 4;
  130.         pixels_left = (dx - 1) % 4;     /* number of pixels left over at the
  131.                                          * end */
  132.         plot(x, y, reverse);
  133.         plot(x1, y1, reverse);  /* plot first two points */
  134.         incr2 = 4 * dy - 2 * dx;
  135.         if (incr2 < 0) {        /* slope less than 1/2 */
  136.                 c = 2 * dy;
  137.                 incr1 = 2 * c;
  138.                 D = incr1 - dx;
  139.  
  140.                 for (uint_fast32_t i = xend; i--;)
  141.                 {    /* plotting loop */
  142.                         ++x;
  143.                         --x1;
  144.                         if (D < 0) {
  145.                                         /* pattern 1 forwards */
  146.                                 plot(x, y, reverse);
  147.                                 plot(++x, y, reverse);
  148.                                 /* pattern 1 backwards */
  149.                                 plot(x1, y1, reverse);
  150.                                 plot(--x1, y1, reverse);
  151.                                 D += incr1;
  152.                         } else {
  153.                                 if (D < c) {
  154.                                         /* pattern 2 forwards */
  155.                                         plot(x, y, reverse);
  156.                                         plot(++x, y += step, reverse);
  157.                                         /* pattern 2 backwards */
  158.                                         plot(x1, y1, reverse);
  159.                                         plot(--x1, y1 -= step, reverse);
  160.                                 } else {
  161.                                         /* pattern 3 forwards */
  162.                                         plot(x, y += step, reverse);
  163.                                         plot(++x, y, reverse);
  164.                                         /* pattern 3 backwards */
  165.                                         plot(x1, y1 -= step, reverse);
  166.                                         plot(--x1, y1, reverse);
  167.                                 }
  168.                                 D += incr2;
  169.                         }
  170.                 }               /* end for */
  171.  
  172.                 /* plot last pattern */
  173.                 if (pixels_left) {
  174.                         if (D < 0) {
  175.                                 plot(++x, y, reverse);  /* pattern 1 */
  176.                                 if (pixels_left > 1)
  177.                                         plot(++x, y, reverse);
  178.                                 if (pixels_left > 2)
  179.                                         plot(--x1, y1, reverse);
  180.                         } else {
  181.                                 if (D < c) {
  182.                                         plot(++x, y, reverse);  /* pattern 2  */
  183.                                         if (pixels_left > 1)
  184.                                                 plot(++x, y += step, reverse);
  185.                                         if (pixels_left > 2)
  186.                                                 plot(--x1, y1, reverse);
  187.                                 } else {
  188.                                   /* pattern 3 */
  189.                                         plot(++x, y += step, reverse);
  190.                                         if (pixels_left > 1)
  191.                                                 plot(++x, y, reverse);
  192.                                         if (pixels_left > 2)
  193.                                                 plot(--x1, y1 -= step, reverse);
  194.                                 }
  195.                         }
  196.                 }               /* end if pixels_left */
  197.         }
  198.         /* end slope < 1/2 */
  199.         else {                  /* slope greater than 1/2 */
  200.                 c = 2 * (dy - dx);
  201.                 incr1 = 2 * c;
  202.                 D = incr1 + dx;
  203.                 for (uint_fast32_t i = xend; i--;)
  204.                 {
  205.                         ++x;
  206.                         --x1;
  207.                         if (D > 0) {
  208.                           /* pattern 4 forwards */
  209.                                 plot(x, y += step, reverse);
  210.                                 plot(++x, y += step, reverse);
  211.                           /* pattern 4 backwards */
  212.                                 plot(x1, y1 -= step, reverse);
  213.                                 plot(--x1, y1 -= step, reverse);
  214.                                 D += incr1;
  215.                         } else {
  216.                                 if (D < c) {
  217.                                   /* pattern 2 forwards */
  218.                                         plot(x, y, reverse);
  219.                                         plot(++x, y += step, reverse);
  220.  
  221.                                   /* pattern 2 backwards */
  222.                                         plot(x1, y1, reverse);
  223.                                         plot(--x1, y1 -= step, reverse);
  224.                                 } else {
  225.                                   /* pattern 3 forwards */
  226.                                         plot(x, y += step, reverse);
  227.                                         plot(++x, y, reverse);
  228.                                   /* pattern 3 backwards */
  229.                                         plot(x1, y1 -= step, reverse);
  230.                                         plot(--x1, y1, reverse);
  231.                                 }
  232.                                 D += incr2;
  233.                         }
  234.                 }               /* end for */
  235.                 /* plot last pattern */
  236.                 if (pixels_left) {
  237.                         if (D > 0) {
  238.                                 plot(++x, y += step, reverse);  /* pattern 4 */
  239.                                 if (pixels_left > 1)
  240.                                         plot(++x, y += step, reverse);
  241.                                 if (pixels_left > 2)
  242.                                         plot(--x1, y1 -= step, reverse);
  243.                         } else {
  244.                                 if (D < c) {
  245.                                         plot(++x, y, reverse);  /* pattern 2  */
  246.                                         if (pixels_left > 1)
  247.                                                 plot(++x, y += step, reverse);
  248.                                         if (pixels_left > 2)
  249.                                                 plot(--x1, y1, reverse);
  250.                                 } else {
  251.                                   /* pattern 3 */
  252.                                         plot(++x, y += step, reverse);
  253.                                         if (pixels_left > 1)
  254.                                                 plot(++x, y, reverse);
  255.                                         if (pixels_left > 2) {
  256.                                                 if (D > c) /* step 3 */
  257.                                                    plot(--x1, y1 -= step, reverse);
  258.                                                 else /* step 2 */
  259.                                                         plot(--x1, y1, reverse);
  260.                                         }
  261.                                 }
  262.                         }
  263.                 }
  264.         }
  265. }
  266.  
  267.  
  268. //unclipped version just calls clipping version for now
  269. void gr_uline(grs_canvas &canvas, const fix _a1, const fix _b1, const fix _a2, const fix _b2, const color_palette_index color)
  270. {
  271.         int a1,b1,a2,b2;
  272.         a1 = f2i(_a1); b1 = f2i(_b1); a2 = f2i(_a2); b2 = f2i(_b2);
  273.         switch(canvas.cv_bitmap.get_type())
  274.         {
  275. #if DXX_USE_OGL
  276.         case bm_mode::ogl:
  277.                 ogl_ulinec(canvas, a1, b1, a2, b2, color);
  278.                 return;
  279. #endif
  280.         case bm_mode::linear:
  281.                 gr_universal_uline(canvas, a1, b1, a2, b2, color);
  282.                 return;
  283.         }
  284.         return;
  285. }
  286.  
  287. // Returns 0 if drawn with no clipping, 1 if drawn but clipped, and
  288. // 2 if not drawn at all.
  289.  
  290. void gr_line(grs_canvas &canvas, fix a1, fix b1, fix a2, fix b2, const color_palette_index color)
  291. {
  292.         int x1, y1, x2, y2;
  293.         x1 = i2f(MINX);
  294.         y1 = i2f(MINY);
  295.         x2 = i2f(canvas.cv_bitmap.bm_w - 1);
  296.         y2 = i2f(canvas.cv_bitmap.bm_h - 1);
  297.  
  298.         CLIPLINE(a1,b1,a2,b2,x1,y1,x2,y2,return,, FIXSCALE );
  299.         gr_uline(canvas, a1, b1, a2, b2, color);
  300. }
  301.  
  302. }
  303.