/*
==============================================================================
		      WordUp Graphics Toolkit Version 5.0                     
			     Demonstration Program 51                         
									      
 Demonstrates the scan converted polygon routines, and shadebob techniques.  
									      
 *** PROJECT ***                                                             
 This program requires the WGT5_WC.LIB file to be linked.                    
									      
 *** DATA FILES ***                                                          
 SQUARE.PLY,  STAR.PLY (Autodesk Animator Polygon files)                     
							   WATCOM C++ VERSION 
==============================================================================
*/

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <math.h>
#include <time.h>
#include <wgt5.h>

/* "Polybob" example:

   A common part in a lot of computer demos involves a technique called
   shadebobs.   They simply mean that each pixel drawn is based on the
   one that previously existed at that spot.  Usually the color of each
   pixel is increased or decreased by 1.  Using a palette with many
   shades of colors, this can produces a colorful display on your monitor.

   Polybobs are an extension of this idea.  Most shadebobs are simple shapes
   like squares or circles.  Using WGT's polygon routines, we can write
   our own horizontal line routine which will do the shadebobs for us.
   Using this, we can do shadebobs with complex polygons.

   By using rendered polygons, once the shape is rendered, all it needs to
   do is draw a list of horizontal lines, which is very fast.  Of course, 
   this means our shape will not be able to change, or rotate.  The second
   part of this demo will show you another technique using the wsolidpoly
   routines to draw a see-through polygon with another shadebob method.

   */


color pal[256];
short oldmode;

tpolypoint pts[150];      /* Stores points of polygon. */
short nump;               /* Number of points in this polygon. */

unsigned char shadebob_increment;  /* number of colors to add to each */
	      /* pixel when drawing an object with the shadebob technique. */
block virt;   /* A virtual screen */


void setup_palette (void)
/* Sets up a nice looking palette for shadebobs */
{
  short i;

  for (i = 0; i < 256; i++)
    wsetrgb (i, 64 * sin(i * 0.017), 64 * sin(i * 0.102), 64 * sin(i * 0.008), pal);
  wsetpalette (0, 255, pal);
}


void setup_transparent_palette (void)
/* Sets up a palette used for transparent images. */
{
  short i;

  for (i = 0; i < 128; i++)
    wsetrgb (i, 64 * sin(i * 0.017), 64 * sin(i * 0.02), 64 * sin(i * 0.01), pal);
  for (i = 128; i < 256; i++)
  {
    pal[i].b = pal[i - 128].r;   /* Here we will access the palette */
    pal[i].g = 0;
    pal[i].r = 0;
  }                               
				  
  wsetpalette (0, 255, pal);
}


void load_poly (char *polyfilename)
/* Loads an Autodesk Animator Polygon definition file. */
{
  FILE *polyfile;
  short magic, i;

  polyfile = fopen (polyfilename, "rb");
  if (polyfile == NULL) 
    return;
  fread (&nump, 2, 1, polyfile);
  fread (&magic, 2, 1, polyfile);  /* unused space  4 bytes */
  fread (&magic, 2, 1, polyfile);
  fread (&magic, 2, 1, polyfile);  /* close shape flag, and magic number (0x99) */
  /* Assume we always want a closed shape for filled polygons. */

  for (i = 0; i < nump; i++)
  {
    fread (&pts[i].x, 2, 1, polyfile);
    fread (&pts[i].y, 2, 1, polyfile);
    fread (&magic, 2, 1, polyfile); /* Z coord is always 0, discard */
  }
  fclose (polyfile);
}


void shadebobline (short x, short x2, short y)
{
  short swap;       /* Used for sorting x coords */
  short length;     /* Horizontal line length (in pixels) */
  block temp;       /* unsigned char far * to the video screen */

  if (x2 < x)
  {
    swap = x2;
    x2 = x;
    x = swap;
  }

  if (x < tx) 
    x = tx;    /* Clip the left edge */
  if (x2 > bx) 
    x2 = bx;  /* Clip the right edge */

  length = x2 - x + 1;  /* Find the length of the line */

  if (length > 0)
  {
    temp = abuf + y * 320 + x;  /* Makes a pointer to the first point on */
				/* the line.  Abuf is the current working */
				/* video page, and we add the number of */
				/* pixels up to the point. */

    while (length > 0)          /* Draw each pixel in the line */
    {
      *temp = *temp + shadebob_increment; /* add to the color */
      temp++;                             /* go to the next pixel */
      length--;                           /* decrease loop counter */
    }
  }
}


void do_polybob (void)
/* Displays the moving polybob on the screen until you hit a key. */
{
  wscanpoly polybob; /* The rendered polygon */
  short xdir = 1;
  short ydir = 1;
  short xcoord, ycoord;

  xcoord = rand () % 280;
  ycoord = rand () % 160;

  wscan_convertpoly (pts, nump, &polybob);
  wcls (0);
  
  do {
    xcoord += xdir;  /* Move the polybob */
    ycoord += ydir;

    if (xcoord < 0)               /* Make the polybob switch directions */
      xdir = rand() % 4;          /* when it hits the side of the screen. */
    else if (xcoord > 280) 
      xdir = -rand() % 4;
    if (ycoord < 0) 
      ydir = rand() % 4;
    else if (ycoord > 160) 
      ydir = -rand() % 4;

    wdraw_scanpoly (xcoord, ycoord, &polybob, shadebobline);
  } while (!kbhit ());

 wfree_scanpoly (&polybob);

 while (kbhit ()) 
   getch ();  /* Clear out keyboard buffer */
} 


void do_transparentbob (void)
/* Displays the moving polybob on the screen until you hit a key. */
{
  wscanpoly polybob; /* The rendered polygon */
  short xdir = 1, ydir = 1;
  short xcoord, ycoord;

  xcoord = rand () % 280;
  ycoord = rand () % 160;

  wscan_convertpoly (pts, nump, &polybob);

  do {
   xcoord += xdir;  /* Move the polybob */
   ycoord += ydir;

   if (xcoord < 0)              /* Make the polybob switch directions */
     xdir = rand() % 4;         /* when it hits the side of the screen. */
   else if (xcoord > 280) 
     xdir = -rand() % 4;
   if (ycoord < 0) 
     ydir = rand() % 4;
   else if (ycoord > 160) 
     ydir = -rand() % 4;

   wdraw_scanpoly (xcoord, ycoord, &polybob, shadebobline);
   wretrace ();
   wdraw_scanpoly (xcoord, ycoord, &polybob, shadebobline);
  } while (!kbhit ());

  wfree_scanpoly (&polybob);

  while (kbhit ()) 
    getch ();  /* Clear out keyboard buffer */
} 


void draw_transparent_background (void)
{
  short x, y;

  wcls (0);
  for (y = 0; y < 200; y++)
    for (x = 0; x < 320; x++)
    {
      wsetcolor (y % 128);
      wfastputpixel (x, y);
    }

  wtexttransparent (TEXTFG);
  wtextcolor (13);
  wgtprintf (10, 50, NULL, "This is a see-through polygon");
  wgtprintf (10, 90, NULL, "This is a see-through polygon");
  wgtprintf (10, 130, NULL, "This is a see-through polygon");
  wgtprintf (10, 170, NULL, "This is a see-through polygon");
}


void main(void)
{
  oldmode = wgetmode ();
  printf ("WGT Example #51\n\n");
  printf ("Polygon routines are used in conjunction with a custom WHLINE so that\n");
  printf ("see-through images can be created. Press a key to advance each section.\n");
  printf ("\n\nPress any key to continue.\n");
  getch();

  vga256 ();
  winitpoly (WGT_SYS.yres);

  setup_palette ();
  shadebob_increment = 1;
  load_poly ("square.ply");
  do_polybob ();
  load_poly ("star.ply");
  do_polybob ();

  setup_transparent_palette ();
  shadebob_increment = 128;
  draw_transparent_background ();
  virt = wnewblock (0, 0, 319, 199);
  do_transparentbob ();

  wfreeblock (virt); 
  wdeinitpoly ();
  wsetmode (oldmode);
}

