/************************************************************************
 *									*
 *		    Copyright (c) 1988, David B. Wecker			*
 *			    All Rights Reserved				*
 *									*
 * This file is part of DBW_uRAY					*
 *									*
 * DBW_uRAY is distributed in the hope that it will be useful, but	*
 * WITHOUT ANY WARRANTY. No author or distributor accepts		*
 * responsibility to anyone for the consequences of using it or for	*
 * whether it serves any particular purpose or works at all, unless	*
 * he says so in writing. Refer to the DBW_uRAY General Public		*
 * License for full details.						*
 *									*
 * Everyone is granted permission to copy, modify and redistribute	*
 * DBW_uRAY, but only under the conditions described in the		*
 * DBW_uRAY General Public License. A copy of this license is		*
 * supposed to have been given to you along with DBW_uRAY so you	*
 * can know your rights and responsibilities. It should be in a file	*
 * named COPYING. Among other things, the copyright notice and this	*
 * notice must be preserved on all copies.				*
 ************************************************************************
 *									*
 * Authors:								*
 *	DBW - David B. Wecker						*
 *									*
 * Versions:								*
 *	V1.0 881023 DBW	- First released version			*
 *	V1.1 881110 DBW - Fixed scan coherence code			*
 *	V1.2 881125 DBW - Removed ALL scan coherence code (useless)	*
 *			  added "fat" extent boxes			*
 *									*
 ************************************************************************/

#define URAY_MAIN 1
#include "uray.h"

/************************************************************************/
/************* top level routines ***************************************/
/************************************************************************/

/* ray trace 1 pixel on the screen and store it away */
dotrace(v1)
VEC	v1;
    {
    int	    i;
    VEC	    v2;

    /* compute the point we're looking at (from 0,0,0) */
     v1[0] = (double)col-(double)cols/2.0;

    /* normalize the direction, and ray trace it */
    vunit(v1,v2);
    trace(-1, 1.0, BLACK, v2, v2, NULL);

    /* scale the color and store it */
    for (i=0; i<3; i++) {
	if (v2[i] < 0.0) v2[i] = 0.0;
	if (v2[i] > 1.0) v2[i] = 1.0;
	outary[i][col] = (unsigned char)(v2[i]*255.9);
	}

#if DEBUG_pixels
    printf("(%3d,%3d) = [%02x %02x %02x] [%4.2f %4.2f %4.2f]\n",
	row,col,outary[0][col],outary[1][col],outary[2][col],v2[0],v2[1],v2[2]);
#endif

    }


/* interrupt handler for any errors */
handler(sig) {
    leave("signal %d received... exiting",sig);
    }



main(argc,argv)
char	**argv;
    {
    int	    i,j;
    VEC	    v1;

    /* definitions for doing elapsed user time */
    double  dtime;
#   ifdef U__X
	struct  tms	    etime;
#	endif
#   ifdef VMS
	struct	tbuffer     etime;
	double		    btime;
#	endif
#   ifdef AMIGA
	unsigned long		bsecs,bmicros,csecs,cmicros;
	struct IntuitionBase    *OpenLibrary();
#	endif

    printf(VERSION);

    /* grab as many errors as possible */
    signal(SIGINT,handler);	/* ^C hit  */
    signal(SIGFPE,handler);	/* floating point error (/ 0) */
    signal(SIGILL,handler);	/* illegal instruction */
    signal(SIGSEGV,handler);	/* segmentation violation (addr err) */

    /* Get the starting time */
#   ifdef AMIGA
	IntuitionBase = OpenLibrary("intuition.library",0L);
	if (!IntuitionBase) exit(0);

	CurrentTime(&bsecs,&bmicros);
#   endif


#   ifdef VMS
	times(&etime);
	btime = ((double)etime.proc_user_time)/100.0;
#	endif

    /* get a base file name */
    if (argc > 1) basnam = argv[1];

    /* get all the object definitions in to memory */
    readinput();

    /* build a tree of object extents */
    doextents();

#   if DEBUG_dumpnodes
	dumpnodes(nodes,0);
#	endif

    /* get the current time (after setting up extents) */
#   ifdef U__X
	times(&etime);
	dtime = ((double)etime.tms_utime)/60.0;
#	endif

#   ifdef VMS
	times(&etime);
	dtime = ((double)etime.proc_user_time)/100.0 - btime;
#	endif

#   ifdef AMIGA
	CurrentTime(&csecs,&cmicros);
	if (cmicros < bmicros) {
	    cmicros += 1000000;
	    csecs   -= 1;
	    }
	dtime  =  (double)(csecs-bsecs);
	dtime += ((double)(cmicros-bmicros)) / 1000000.0;
#	endif

    printf("\nExtent setup time: %12.2f\n\n",dtime);

    /* compute the number of output bytes in a scan line */
    if	    (bpp == 24) obpsl = cols;
    else if (bpp == 12) obpsl = cols >> 1;
    else if (bpp) leave("BPP must be either 12, 24 or 0");
    bpp	    /= 3;

    /* create output files */
    coutputs();

    /* define depth of the screen */
    v1[2] = ((double)(rows+cols))/4.0/tan((double)aov/114.5915590261);

    /* now ray trace each pixel */
    for (row=startrow; row<endrow; row++) {

	/* define row we're looking at */
	v1[1] = ((double)rows/2.0-(double)row) * aspect;

	/* ray trace all pixels */
	for (col=0; col<cols; col++) dotrace(v1);

	/* output the line */
	woutputs((short)row);

	}

    printf("\n\n");


    /* get the ending elapsed time */
#   ifdef U__X
	times(&etime);
	dtime = ((double)etime.tms_utime)/60.0;
#	endif

#   ifdef VMS
	times(&etime);
	dtime = ((double)etime.proc_user_time)/100.0 - btime;
#	endif

#   ifdef AMIGA
	CurrentTime(&csecs,&cmicros);
	if (cmicros < bmicros) {
	    cmicros += 1000000;
	    csecs   -= 1;
	    }
	dtime  =  (double)(csecs-bsecs);
	dtime += ((double)(cmicros-bmicros)) / 1000000.0;
#	endif

    printf("\nTotal  run   time: %12.2f\n\n",dtime);
    printf("False hits: Extents = %10d, Nodes = %10d\n",fehits,fnhits);
    printf("Good  hits: Extents = %10d, Nodes = %10d\n",gehits,gnhits);
    printf("Total hits: Extents = %10d, Nodes = %10d\n\n",
	fehits+gehits,fnhits+gnhits);

    /* all done, so finish up */
    leave(NULL);
    }
