/************************************************************************
 *		basic ray tracing package tracer2.1			*
 *									*
 *		version 0.0 done 6/1/86-6/10/86				*
 *		version 1.0 released 6/29/86				*
 *		version 2.0 released 7/5/86				*
 *		version 2.1 released 8/27/86				*
 *		by friedrich knauss (one tired programmer)		*
 *									*
 *		Fast Amiga math	9/86 	Mark Reichert			*
 *		-p, -a options	9/86	Steve Williams & Jim Horn	*
 *		IFF file output	12/86:	Mark Reichert			*
 ************************************************************************/

#include <stdio.h>
#include <math.h>
#include "MyMath.h"
#include "rtd.h"
#include "macros.h"


#define	CHECK_IT	if ( Chk_Abort() ) {\
				printf("Aborting, save picture. [y/n] ");\
				gets(tmp);\
				if( tmp[0] == 'y' )\
					save_screen(gfx_screen(), out_name);\
				gfx_close();\
				close_math();\
				exit(104);\
			}

struct	ball	*bl[150];
struct	sphere	ls;

int	xsue,
	ysue,
	level,
	nob;

char	suzie[300][300],
	tmp[10],
	out_name[132];

FFP	sam;

long	gfx_screen();	/* really struct Screen, but ... */

main(argc, argv)
int	argc;
char	*argv[];
{
	FILE	*df,
		*texfile,
		*parmsf;

	static	double	xco, xco1,
			yco, yco1;

	struct	ray	rr;
	struct	vector	vp;
	int	i, i1,
		j, j1,
		pixelev,
		in = 0,
		out = 0,
		parms = 0,
		tex = 0,
		alias = 1,
		a2 = 1,
		c,
		xoffset, yoffset;	/* for centered display */

	double	xmin, xmax,
		ymin, ymax,
		xpix, ypix,
		aspect_ratio,
		xc, yc,
		dx, dx1,
		dy, dy1,
		vpx, vpy, vpz,
		lsx, lsy, lsz,
		lsrad;


	if( !open_math() ) {
		printf("couldn't open math library\n");
		exit(103);
	}

	if( !gfx_open() ) {
		printf("couldn't open gfx libraries\n");
		close_math();
		exit(103);
	}

	sam = SPFlt(1);

	/* command interp */

	for (i = 1; i < argc; i++) {
		if (argv[i][0] != '-')
			booboo ("Options start with a '-' ");
		c = argv[i][1];

		switch (c) {

			case ('i'): /* input file */

				if (in)
					booboo("Sorry, but you may only have one input file");
				in = 1;
				if(
					(i + 1) >= argc ||
					argv[i + 1][0] == '-'
				)	/* no arg */
					df = stdin;
				else if( ! ( df = fopen (argv[++i], "r") ) )
					booboo ("input file not found");
				break;

			case ('o'): /* output file */
				if (out)
					booboo ("Sorry, but you may have only one output file");
				out = 1;
				if (
					(i + 1) >= argc ||
					argv[i + 1][0] == '-'
				)	/* no arg */
					booboo("-o stdout option no longer supported");
				else
					strcpy( out_name, argv[++i]);
				break;

			case ('p'): /* parms file */
				if (parms)
					booboo ("Sorry, but you may only have one parameters file");
				parms = 1;
				if (
					(i + 1) >= argc ||
					argv[i + 1][0] == '-'
				)	/* no arg */
					parmsf = stdin;
				else if(! (parmsf = fopen(argv[++i], "r") ) )
					booboo ("parameters file not found");
				break;

			case ('r'): /* rotate results */
				fprintf(
					stderr,
					"ignoring -r, option no longer supported\n"
				);
				break;

			case ('s'): /* susie file */
				if (tex)
					booboo ("Sorry, but you may have only one image file");
				if (
					(i + 1) >= argc ||
					argv[i + 1][0] == '-'
				)	/* no arg */
					booboo ("-s requires an argument");
				tex = 1;
				if (!(texfile = fopen (argv[++i], "r") ) )
					booboo ("image file not found");
				break;

			case ('a'): /* anti-aliasing value */
				if (argv[i][2] < '1' || argv[i][2] > '9') {
					printf("%c\n",argv[i][2]);
					booboo ("-a needs a numerical argument");}
					alias = (int) atof ( &(argv[i][2]) );
					/* Find number of subcells per pixel*/
					a2  = alias * alias;
					break;

			case ('S'): /* amount of susie */
				if (argv[i][2] < '0' || argv[i][2] > '9') {
					printf("%c\n",argv[i][2]);
					booboo ("-S needs a numerical argument");
				}
					sam = ieee_to_ffp( atof (&(argv[i][2]) ) );
				break;
			default:
				booboo ("Unrecognized option. Better try again");
		} /* switch */
	} /* for */


	if (!in)
		if ( ! (df = fopen ("tracer.ball", "r") ) )
			booboo ("tracer.ball not found");

	if (!out)
		strcpy( out_name, "tracer.pic");

	if (!parms)
		if ( ! (parmsf = fopen ("tracer.param", "r") ) )
			booboo ("tracer.param not found");

	if (!tex)
		if ( ! (texfile = fopen ("tracer.pat", "r") ) )
			booboo ("tracer.pat not found");

	/* read parameters from file */
	fscanf(
		parmsf,
		"%lf %lf %lf %lf %lf %lf %lf",
		&xmin, &xmax,
		&ymin, &ymax,
		&xpix, &ypix,
		&aspect_ratio
	);
	fscanf(
		parmsf,
		"%lf %lf %lf %lf %lf %lf %lf",
		&vpx, &vpy, &vpz,
		&lsx, &lsy, &lsz,
		&lsrad
	);

	fclose (parmsf);


	nob = g_bal (df);		/* Read ball data file.		*/
	g_bod (texfile);		/* Read & normalize background. */

	/* Set view point location.	*/
	MV (ieee_to_ffp(vpx), ieee_to_ffp(vpy), ieee_to_ffp(vpz), vp);

	/* Set light source location	*/
	MV (ieee_to_ffp(lsx), ieee_to_ffp(lsy), ieee_to_ffp(lsz), ls.cent);

	/* and radius.		*/
	ls.rad = ieee_to_ffp(lsrad);

#ifdef	FOOIE
	/* just so that I remember this line was. ok to delete it */
	fprintf (filep, "%d %d\n", (int) (xpix), (int) (ypix));
#endif

	dx = xmax - xmin;			/* Find size of viewport   */
	dy = ymax - ymin;

	if ( aspect_ratio != 0.0 ) {
		xc = (xmax + xmin) / 2.0;	/* Find center of viewport */
		yc = (ymax + ymin) / 2.0;
		if (aspect_ratio < 0.0)
			aspect_ratio *= -xpix / ypix;

		/* Adjust viewport to fit display?  */
		if (dx < (dy * aspect_ratio)) {

			/* Yes - make a bigger x axis range. */
			dx = dy * aspect_ratio;
			xmin = xc - dx / 2.0;
			xmax = xmin + dx;

		} else if ( dx > ( dy * aspect_ratio) ) {

			/* Yes - make a bigger y axis range. */
			dy = dx / aspect_ratio;
			ymin = yc - dy / 2.0;
			ymax = ymin + dy;

		};
	};

	dx /= xpix;		/* Find the size of each pixel in x */
	dy /= ypix;		/* and y units. */
	dx1 = dx / alias;	/* Find the size of each subcell in */
	dy1 = dy / alias;	/* x and y units. */

	/* for centering in amiga specific window dimensions */
	xoffset = (640 - (int) xpix) >> 1;
	yoffset = (400 - (int) ypix) >> 1;

	yco = ymin + (dy / 2.0);
	for( j=ypix; j > 0; yco += dy, j-- ) {

		xco = xmax - (dx / 2.0);
		for ( i=xpix; i > 0; xco -= dx, i-- ) {

			pixelev = 0;
			for (yco1 = yco, i1 = alias; i1 > 0; yco1 -= dy1, i1--)
				for (xco1 = xco, j1 = alias; j1 > 0; xco1 += dx1, j1--) {
					MV (ieee_to_ffp(xco1), ieee_to_ffp(yco1), SPFlt(0), rr.org);
					SV (rr.dir, rr.org, vp);
					pixelev += shade (&rr);
				};
			do_pixel( (i+xoffset), (j-yoffset), (pixelev/a2) );
			CHECK_IT;
		}
		printf(".");
	}

	save_screen( gfx_screen(), out_name );

	gfx_close();
	close_math();
}

booboo(str)
char	*str;
{
	printf ("%s\n", str);
	gfx_close();
	close_math();
	exit (-1);
}
