/*----------------------------------------------------------------------
 *			 TMS340 Graphics Library
 *          Copyright (c) 1990 Texas Instruments Incorporated.
 *                         All Rights Reserved
 *----------------------------------------------------------------------
 * Demonstration Program
 *
 *   Test the draw_polyline function.  Several animated wireframe
 *   "daisies" are bounced off the sides of the screen.  Each "daisy" is
 *   defined by an enclosing parallelogram, which is in turn defined by 3
 *   vertices xy[3] (from which the 4th vertex is easily determined).
 *   The 3 vertices have velocities vxy[3].
 *----------------------------------------------------------------------
 * Revision History:
 *   03/27/90...Original version written...................J.R. Van Aken
 *----------------------------------------------------------------------
 */
#include <gsptypes.h>

/* If MODE not defined at preprocessor command line, set to default. */
#ifndef  MODE
#define  MODE	  0	  /* default graphics mode */
#endif

#define NDAISIES  5		   /* number of "daisies" */
#define N	  2		   /* angular increment = 1>>N radians */
#define TWOPI	  411775	   /* fixed point 2*PI */
#define NPOINTS   ((TWOPI<<N)>>16-1)  /* number of vertices in "daisy" */

typedef long FIX16;		   /* fixed-point with 16-bit fraction */
typedef struct { FIX16 x, y; } XYFIX;  /* fixed-point xy pair */
typedef struct { short x, y; } XYINT;  /* short int xy pair */
typedef struct { XYFIX xy[3], vxy[3]; } DAISY;	/* 3 points/velocities */

static CONFIG cfg;
static XYINT xy[NPOINTS];
static DAISY daisy[NDAISIES];


main()
{
    int hres, vres, x, y, i, j, k, disppage, drawpage;
    int x0, y0, x1, y1, x2, y2, xc, yc, ux, vx, uy, vy;

    /* Initialize graphics environment. */
    if (!set_config(MODE, 1))
	exit(1);		 /* invalid graphics mode number */
    clear_screen(0);
    get_config(&cfg);
    hres = cfg.mode.disp_hres;	 /* horizontal resolution */
    vres = cfg.mode.disp_vres;	 /* vertical resolution */

    /* Adjust shape and movement parameters to screen dimensions. */
    x = hres << 16;
    y = 0;
    for (i = 0; i < NDAISIES; i++) {
	for (j = 0; j < 3; j++) {
	    /* Initially all points are at xy origin. */
	    daisy[i].xy[j].x = daisy[i].xy[j].y = 0;

	    /* Give each point a different velocity. */
	    x -= y/8;
	    y += x/16;
	    daisy[i].vxy[j].x = x >> 7;
	    daisy[i].vxy[j].y = y >> 7;
	    if (j & 1) {
		daisy[i].vxy[j].x += x >> 10;
		daisy[i].vxy[j].y += y >> 10;
	    }
	}
    }

    /* Each loop draws the next frame of wireframe "daisies". */
    disppage = 0;
    drawpage = 1;
    for (;;) {
	page_flip(disppage ^= 1, drawpage ^= 1);

	/* Each loop below updates the 3 vertices defining a daisy. */
	for (i = 0; i < NDAISIES; i++)
	    /* Each loop below updates one vertex. */
	    for (j = 0; j < 3; j++) {
		/* Update position of vertex. */
		daisy[i].xy[j].x += daisy[i].vxy[j].x;
		daisy[i].xy[j].y += daisy[i].vxy[j].y;

		/* Bounce off left or right window edge. */
		x = daisy[i].xy[j].x >> 16;
		if (cpw(x, 0))
		    daisy[i].vxy[j].x *= -1;

		/* Bounce off top or bottom window edge. */
		y = daisy[i].xy[j].y >> 16;
		if (cpw(0, y))
		    daisy[i].vxy[j].y *= -1;
	    }
	while (page_busy())
	    ;
	clear_screen(0);
	/* Each loop below calculates and draws the rim of a daisy. */
	for (i = k = 0; i < NDAISIES; i++) {
	    /* Get 3 points defining parallelogram enclosing daisy. */
	    x1 = daisy[i].xy[0].x;
	    y1 = daisy[i].xy[0].y;
	    xc = daisy[i].xy[1].x;
	    yc = daisy[i].xy[1].y;
	    x2 = daisy[i].xy[2].x;
	    y2 = daisy[i].xy[2].y;

	    /* Calculate displacements from center of parallelologram. */
	    vx = (xc - x2)/2;
	    ux = (xc - x1)/2;
	    vy = (yc - y2)/2;
	    uy = (yc - y1)/2;
	    ux += vx >> N+1;	  /* add fudge factor */
	    uy += vy >> N+1;

	    /* Calculate center of parallelogram. */
	    x0 = (x1 + x2)/2;
	    y0 = (y1 + y2)/2;

	    /* Calculate points around rim of daisy. */
	    for (j = 0; j < NPOINTS; j++) {
		if (j & 1) {	       /* rotate on odd j */
		    ux -= vx >> N;
		    vx += ux >> N;
		    uy -= vy >> N;
		    vy += uy >> N;
		}
		if (j & 2) {	       /* inner point on rim */
		    xy[j].x = (x0 + vx/2) >> 16;
		    xy[j].y = (y0 + vy/2) >> 16;
		} else {	       /* outer point on rim */
		    xy[j].x = (x0 + vx) >> 16;
		    xy[j].y = (y0 + vy) >> 16;
		}
	    }

	    /* Draw the next daisy. */
	    if (++k == cfg.mode.palet_size)
		k = 1;
	    set_fcolor(k);
	    draw_polyline(NPOINTS, xy);
	}
    }
}

