home *** CD-ROM | disk | FTP | other *** search
/ Graphics Programming Black Book (Special Edition) / BlackBook.bin / disk1 / source / chapter32 / l32-2.c < prev    next >
C/C++ Source or Header  |  1997-06-18  |  7KB  |  205 lines

  1. /*
  2.  * *** Listing 10.2 ***
  3.  *
  4.  * Sample program to illustrate VGA line drawing in 360x480
  5.  * 256-color mode.
  6.  *
  7.  * Compiled with Borland C++ 4.02.
  8.  * Checked by Jim Mischel 11/21/94
  9.  *
  10.  * Must be linked with Listing 10.1 with a command line like:
  11.  *
  12.  *    bcc l10-2.c l10-1.asm
  13.  *
  14.  * By Michael Abrash.  6/2/89.
  15.  */
  16. #include <dos.h>                 /* contains geninterrupt */
  17.  
  18. #define TEXT_MODE       0x03
  19. #define BIOS_VIDEO_INT  0x10
  20. #define X_MAX           360      /* working screen width */
  21. #define Y_MAX           480      /* working screen height */
  22.  
  23. extern void Draw360x480Dot();
  24. extern void Set360x480Mode();
  25.  
  26. /*
  27.  * Draws a line in octant 0 or 3 ( |DeltaX| >= DeltaY ).
  28.  * |DeltaX|+1 points are drawn.
  29.  */
  30. void Octant0(X0, Y0, DeltaX, DeltaY, XDirection, Color)
  31. unsigned int X0, Y0;          /* coordinates of start of the line */
  32. unsigned int DeltaX, DeltaY;  /* length of the line */
  33. int XDirection;               /* 1 if line is drawn left to right,
  34.                                  -1 if drawn right to left */
  35. int Color;                    /* color in which to draw line */
  36. {
  37.    int DeltaYx2;
  38.    int DeltaYx2MinusDeltaXx2;
  39.    int ErrorTerm;
  40.  
  41.    /* Set up initial error term and values used inside drawing loop */
  42.    DeltaYx2 = DeltaY * 2;
  43.    DeltaYx2MinusDeltaXx2 = DeltaYx2 - (int) ( DeltaX * 2 );
  44.    ErrorTerm = DeltaYx2 - (int) DeltaX;
  45.  
  46.    /* Draw the line */
  47.    Draw360x480Dot(X0, Y0, Color);   /* draw the first pixel */
  48.    while ( DeltaX-- ) {
  49.       /* See if it's time to advance the Y coordinate */
  50.       if ( ErrorTerm >= 0 ) {
  51.          /* Advance the Y coordinate & adjust the error term
  52.             back down */
  53.          Y0++;
  54.          ErrorTerm += DeltaYx2MinusDeltaXx2;
  55.       } else {
  56.          /* Add to the error term */
  57.          ErrorTerm += DeltaYx2;
  58.       }
  59.       X0 += XDirection;          /* advance the X coordinate */
  60.       Draw360x480Dot(X0, Y0, Color);    /* draw a pixel */
  61.    }
  62. }
  63.  
  64. /*
  65.  * Draws a line in octant 1 or 2 ( |DeltaX| < DeltaY ).
  66.  * |DeltaY|+1 points are drawn.
  67.  */
  68. void Octant1(X0, Y0, DeltaX, DeltaY, XDirection, Color)
  69. unsigned int X0, Y0;          /* coordinates of start of the line */
  70. unsigned int DeltaX, DeltaY;  /* length of the line */
  71. int XDirection;               /* 1 if line is drawn left to right,
  72.                                  -1 if drawn right to left */
  73. int Color;                    /* color in which to draw line */
  74. {
  75.    int DeltaXx2;
  76.    int DeltaXx2MinusDeltaYx2;
  77.    int ErrorTerm;
  78.  
  79.    /* Set up initial error term and values used inside drawing loop */
  80.    DeltaXx2 = DeltaX * 2;
  81.    DeltaXx2MinusDeltaYx2 = DeltaXx2 - (int) ( DeltaY * 2 );
  82.    ErrorTerm = DeltaXx2 - (int) DeltaY;
  83.  
  84.    Draw360x480Dot(X0, Y0, Color);        /* draw the first pixel */
  85.    while ( DeltaY-- ) {
  86.       /* See if it's time to advance the X coordinate */
  87.       if ( ErrorTerm >= 0 ) {
  88.          /* Advance the X coordinate & adjust the error term
  89.             back down */
  90.          X0 += XDirection;
  91.          ErrorTerm += DeltaXx2MinusDeltaYx2;
  92.       } else {
  93.          /* Add to the error term */
  94.          ErrorTerm += DeltaXx2;
  95.       }
  96.       Y0++;                           /* advance the Y coordinate */
  97.       Draw360x480Dot(X0, Y0,Color);      /* draw a pixel */
  98.    }
  99. }
  100.  
  101. /*
  102.  * Draws a line on the EGA or VGA.
  103.  */
  104. void EVGALine(X0, Y0, X1, Y1, Color)
  105. int X0, Y0;            /* coordinates of one end of the line */
  106. int X1, Y1;            /* coordinates of the other end of the line */
  107. unsigned char Color;        /* color in which to draw line */
  108. {
  109.    int DeltaX, DeltaY;
  110.    int Temp;
  111.  
  112.    /* Save half the line-drawing cases by swapping Y0 with Y1
  113.       and X0 with X1 if Y0 is greater than Y1. As a result, DeltaY
  114.       is always > 0, and only the octant 0-3 cases need to be
  115.       handled. */
  116.    if ( Y0 > Y1 ) {
  117.       Temp = Y0;
  118.       Y0 = Y1;
  119.       Y1 = Temp;
  120.       Temp = X0;
  121.       X0 = X1;
  122.       X1 = Temp;
  123.    }
  124.  
  125.    /* Handle as four separate cases, for the four octants in which
  126.       Y1 is greater than Y0 */
  127.    DeltaX = X1 - X0;    /* calculate the length of the line
  128.                            in each coordinate */
  129.    DeltaY = Y1 - Y0;
  130.    if ( DeltaX > 0 ) {
  131.       if ( DeltaX > DeltaY ) {
  132.          Octant0(X0, Y0, DeltaX, DeltaY, 1, Color);
  133.       } else {
  134.          Octant1(X0, Y0, DeltaX, DeltaY, 1, Color);
  135.       }
  136.    } else {
  137.       DeltaX = -DeltaX;             /* absolute value of DeltaX */
  138.       if ( DeltaX > DeltaY ) {
  139.          Octant0(X0, Y0, DeltaX, DeltaY, -1, Color);
  140.       } else {
  141.          Octant1(X0, Y0, DeltaX, DeltaY, -1, Color);
  142.       }
  143.    }
  144. }
  145.  
  146. /*
  147.  * Subroutine to draw a rectangle full of vectors, of the
  148.  * specified length and in varying colors, around the
  149.  * specified rectangle center.
  150.  */
  151. void VectorsUp(XCenter, YCenter, XLength, YLength)
  152. int XCenter, YCenter;   /* center of rectangle to fill */
  153. int XLength, YLength;   /* distance from center to edge
  154.                            of rectangle */
  155. {
  156.    int WorkingX, WorkingY, Color = 1;
  157.  
  158.    /* Lines from center to top of rectangle */
  159.    WorkingX = XCenter - XLength;
  160.    WorkingY = YCenter - YLength;
  161.    for ( ; WorkingX < ( XCenter + XLength ); WorkingX++ )
  162.       EVGALine(XCenter, YCenter, WorkingX, WorkingY, Color++);
  163.  
  164.    /* Lines from center to right of rectangle */
  165.    WorkingX = XCenter + XLength - 1;
  166.    WorkingY = YCenter - YLength;
  167.    for ( ; WorkingY < ( YCenter + YLength ); WorkingY++ )
  168.       EVGALine(XCenter, YCenter, WorkingX, WorkingY, Color++);
  169.  
  170.    /* Lines from center to bottom of rectangle */
  171.    WorkingX = XCenter + XLength - 1;
  172.    WorkingY = YCenter + YLength - 1;
  173.    for ( ; WorkingX >= ( XCenter - XLength ); WorkingX-- )
  174.       EVGALine(XCenter, YCenter, WorkingX, WorkingY, Color++);
  175.  
  176.    /* Lines from center to left of rectangle */
  177.    WorkingX = XCenter - XLength;
  178.    WorkingY = YCenter + YLength - 1;
  179.    for ( ; WorkingY >= ( YCenter - YLength ); WorkingY-- )
  180.       EVGALine(XCenter, YCenter, WorkingX, WorkingY, Color++);
  181. }
  182.  
  183. /*
  184.  * Sample program to draw four rectangles full of lines.
  185.  */
  186. void main()
  187. {
  188.    char temp;
  189.  
  190.    Set360x480Mode();
  191.  
  192.    /* Draw each of four rectangles full of vectors */
  193.    VectorsUp(X_MAX / 4, Y_MAX / 4, X_MAX / 4, Y_MAX / 4, 1);
  194.    VectorsUp(X_MAX * 3 / 4, Y_MAX / 4, X_MAX / 4, Y_MAX / 4, 2);
  195.    VectorsUp(X_MAX / 4, Y_MAX * 3 / 4, X_MAX / 4, Y_MAX / 4, 3);
  196.    VectorsUp(X_MAX * 3 / 4, Y_MAX * 3 / 4, X_MAX / 4, Y_MAX / 4, 4);
  197.  
  198.    /* Wait for the enter key to be pressed */
  199.    scanf("%c", &temp);
  200.  
  201.    /* Back to text mode */
  202.    _AX = TEXT_MODE;
  203.    geninterrupt(BIOS_VIDEO_INT);
  204. }
  205.