/*
 * options.c
 *
 * Copyright (C) 1989, 1991, Craig E. Kolb
 * All rights reserved.
 *
 * This software may be freely copied, modified, and redistributed
 * provided that this copyright notice is preserved on all copies.
 *
 * You may not distribute this software, in whole or in part, as part of
 * any commercial product without the express consent of the authors.
 *
 * There is no warranty or other guarantee of fitness of this software
 * for any purpose.  It is provided solely "as is".
 *
 * $Id: options.c,v 4.0 91/07/17 14:46:47 kolb Exp Locker: kolb $
 *
 * $Log:	options.c,v $
 * Revision 4.0  91/07/17  14:46:47  kolb
 * Initial version.
 * 
 */
#include "rayshade.h"
#include "options.h"
#include "stats.h"
#include "viewing.h"
 
RSOptions	Options;
 
static void usage();
 
void
RSOptionsSet(argc, argv)
int argc;
char **argv;
{
	extern void OpenStatsFile();
 
	Options.progname = strsave(argv[0]);
	Options.inputname = (char *)NULL;
	while (--argc) {
		argv++;
		if (argv[0][0] != '-') {
			/*
			 * Must be the input file name.
			 * If already given, complain and then exit.
			 */
			if (Options.inputname != (char *)NULL) {
				usage();	
				exit(1);
			}
			Options.inputname = strsave(argv[0]);
			continue;
		}
		/* else */
		switch(argv[0][1]) {
			case 'A':
				/*
				 * First frame number
				 */
				Options.startframe = atoi(argv[1]);
				argv++; argc--;
				break;
#ifdef URT
			case 'a':
				Options.alpha = !Options.alpha;
				break;
#endif
			case 'C':
				Options.cutoff.r = atof(argv[1]);
				Options.cutoff.g = atof(argv[2]);
				Options.cutoff.b = atof(argv[3]);
				Options.cutoff_set = TRUE;
				argv += 3; argc -= 3;
				break;
#ifdef URT
			case 'c':
				Options.appending = TRUE;
				break;
#endif
			case 'D':
				Options.maxdepth = atoi(argv[1]);
				Options.maxdepth_set = TRUE;
				argv++; argc--;
				break;
			case 'E':
				Options.eyesep = atof(argv[1]);
				Options.eyesep_set = TRUE;
				argc--; argv++;
				break;
#ifdef URT
			case 'e':
				Options.exp_output = TRUE;
				break;
#endif
#ifdef RPC
			case 'i':{
				int i;
#define SERVERFILENAME "rayshade.srv"
				char *arg;
				FILE *serverfile;
				void rpc_client();
				arg=strsave(&argv[0][2]);
				Options.serverfilename=SERVERFILENAME;
				if(*arg=='-'){	
					Options.is_rpc_server=TRUE;
					Options.serverexestring=arg;
				} else {
					i=atoi(arg);
					if(i)
						Options.squaresize=i;
					Options.is_rpc_client=TRUE;
				}
				break;
			}

			case 'd':
				Options.display=TRUE;
				break;
#endif
			case 'F':
				Options.report_freq = atoi(argv[1]);
				if (Options.report_freq < 1)
					Options.report_freq = 1;
				Options.freq_set = TRUE;
				argv++; argc--;
				break;
			case 'f':
				Options.flipnorm = !Options.flipnorm;
				break;
			case 'G':
				Options.gamma = atof(argv[1]);
				argv++; argc--;
				break;
			case 'g':
				Options.gaussian = !Options.gaussian;
				break;
			case 'h':
				usage();
				exit(0);
				break;
			case 'j':
				Options.jitter = !Options.jitter;
				Options.jitter_set = TRUE;
				break;
			case 'l':
				Options.stereo = LEFT;
				break;
#ifdef URT
			case 'm':
				Options.samplemap = !Options.samplemap;
				break;
#endif
			case 'N':
				Options.totalframes = atof(argv[1]);
				Options.totalframes_set = TRUE;
				argv++; argc--;
				break;
			case 'n':
				Options.no_shadows = !Options.no_shadows;
				break;
			case 'O':
				Options.imgname = strsave(argv[1]);
				argv++;
				argc--;
				break;
			case 'o':
				Options.shadowtransp = !Options.shadowtransp;
				break;
			case 'P':
				Options.cppargs = argv[1];
				argv++; argc--;
				break;
			case 'p':
				/*
				 * Preview-quality rendering
				 * no shadows
				 * max depth of 0
				 * 1 jittered sample/pixel
				 */
				Options.no_shadows = TRUE;
				Options.maxdepth = 0;
				Options.maxdepth_set = TRUE;
				Options.jitter = TRUE;
				Options.jitter_set = TRUE;
				Options.samples = 1;
				Options.samples_set = TRUE;
				break;
			case 'q':
				Options.quiet = TRUE;
				break;
			case 'R':
				Screen.xres = atoi(argv[1]);
				Screen.yres = atoi(argv[2]);
				Options.resolution_set = TRUE;
				argv += 2;
				argc -= 2;
				break;
			case 'r':
				Options.stereo = RIGHT;
				break;
			case 'S':
				Options.samples = atoi(argv[1]);
				if (Options.samples < 1)
					Options.samples = 1;
				Options.samples_set = TRUE;
				argv++; argc--;
				break;
			case 's':
				Options.cache = !Options.cache;
				break;
			case 'T':
				Options.contrast.r = atof(argv[1]);
				Options.contrast.g = atof(argv[2]);
				Options.contrast.b = atof(argv[3]);
				Options.contrast_set = TRUE;
				argv += 3;
				argc -= 3;
				break;
			case 'v':
				Options.verbose = TRUE;
				break;
			case 'V':
				Options.verbose = TRUE;
				if (argv[1][0] == '-') {
					/* User probably blew it, and
					 * it's difficult to remove a file
					 * that begins with '-'...
					 */
					usage();
					exit(2);
				}
				Options.statsname = strsave(argv[1]);
				OpenStatsFile();
				argv++; argc--;
				break;
#ifdef URT
			case 'W':
				Options.xmin = atof(argv[1]);
				Options.xmax = atof(argv[2]);
				Options.ymin = atof(argv[3]);
				Options.ymax = atof(argv[4]);
				Options.window_set = TRUE;
				argv += 4; argc -= 4;
				break;
#endif
#ifdef LINDA
			case 'X':
				Options.workers = atoi(argv[1]);
				if (Options.workers<0 || Options.workers>17) {
					RLerror(RL_PANIC, "%d workers?\n",
							Options.workers);
				}
				argv++; argc--;
				break;
			case 'w':
				Options.verbose_worker =
					!Options.verbose_worker;
				break;
#endif
			default:
				RLerror(RL_PANIC,"Bad argument: %s\n",argv[0]);
		}
	}
}
 
void
RSOptionsList()
{
	if (Options.totalframes > 1) {
		fprintf(Stats.fstats,"Rendering frames %d through %d.\n",
			Options.startframe, Options.endframe);
	} else {
		fprintf(Stats.fstats,"Rendering frame %d.\n", Options.startframe);
	}
 
	fprintf(Stats.fstats,"Screen resolution: %d x %d\n",
		Screen.xres,Screen.yres);
	fprintf(Stats.fstats,"Image window: (%d - %d), (%d - %d).\n",
			Screen.minx, Screen.maxx, Screen.miny, Screen.maxy);
 
	if (Options.jitter)
		fprintf(Stats.fstats,"Using jittered sampling, ");
	fprintf(Stats.fstats,"Max sampling rate %d %s/pixel.\n",
		Options.samples*Options.samples,
		Options.samples == 1 ? "sample" : "samples");
 
	fprintf(Stats.fstats,
		"Maximum contrast: %g red, %g green, %g blue.\n",
		Options.contrast.r, Options.contrast.g,
		Options.contrast.b);
	fprintf(Stats.fstats,"Maximum ray depth: %d.  Cutoff thresh: %g %g %g.\n",
			Options.maxdepth,
			Options.cutoff.r, Options.cutoff.g, Options.cutoff.b);
	if (Options.stereo == LEFT)
		fprintf(Stats.fstats,"Rendering image for left eye.\n");
	else if (Options.stereo == RIGHT)
		fprintf(Stats.fstats,"Rendering image for right eye.\n");
	if (Options.no_shadows) {
		fprintf(Stats.fstats,"No shadows are rendered.\n");
	} else if (Options.shadowtransp) {
		fprintf(Stats.fstats,
			"Object opacity affects depth of shadowing.\n");
	}
	if (!Options.cache)
		fprintf(Stats.fstats,"Shadow caching is disabled.\n");
	if (Options.totalframes != 1)
		fprintf(Stats.fstats,"Rendering %d frames.\n",
			Options.totalframes);
}
 
static void
usage()
{
	fprintf(stderr,"usage: %s [options] [filename]\n", Options.progname);
	fprintf(stderr,"Where options include:\n");
	fprintf(stderr,"\t-A frame\t(Begin with given frame #.)\n");
#ifdef URT
	fprintf(stderr,"\t-a \t\t(Toggle writing of alpha channel.)\n");
#endif
	fprintf(stderr,"\t-C thresh\t(Set adaptive ray tree cutoff value.)\n");
#ifdef URT
	fprintf(stderr,"\t-c \t\t(Continue interrupted rendering.)\n");
#endif
	fprintf(stderr,"\t-D depth\t(Set maximum ray tree depth.)\n");
	fprintf(stderr,"\t-E eye_sep\t(Set eye separation in stereo pairs.)\n");
#ifdef URT
	fprintf(stderr,"\t-e \t\t(Write exponential RLE file.)\n");
#endif
	fprintf(stderr,"\t-F freq\t\t(Set frequency of status report.)\n");
	fprintf(stderr,"\t-G gamma\t(Use given gamma correction exponent.)\n");
	fprintf(stderr,"\t-h \t\t(Print this message.)\n");
	fprintf(stderr,"\t-l \t\t(Render image for left eye view.)\n");
	fprintf(stderr,"\t-N number\t(Render given number of frames.)\n");
	fprintf(stderr,"\t-n \t\t(Do not render shadows.)\n");
	fprintf(stderr,"\t-O outfile \t(Set output file name.)\n");
	fprintf(stderr,"\t-o \t\t(Toggle opacity effect on shadowing.)\n");
	fprintf(stderr,"\t-P cpp-args\t(Options to pass to C pre-processor.\n");
	fprintf(stderr,"\t-p \t\t(Preview-quality rendering.)\n");
	fprintf(stderr,"\t-q \t\t(Run quietly.)\n");
	fprintf(stderr,"\t-R xres yres\t(Render at given resolution.)\n");
	fprintf(stderr,"\t-r \t\t(Render image for right eye view.)\n");
	fprintf(stderr,"\t-S samples\t(Max density of samples^2 samples.)\n");
	fprintf(stderr,"\t-s \t\t(Don't cache shadowing information.)\n");
	fprintf(stderr,"\t-T r g b\t(Set contrast threshold (0. - 1.).)\n");
	fprintf(stderr,"\t-V filename \t(Write verbose output to filename.)\n");
	fprintf(stderr,"\t-v \t\t(Verbose output.)\n");
#ifdef URT
	fprintf(stderr,"\t-W x y x y \t(Render subwindow.)\n");
#endif
#ifdef LINDA
	fprintf(stderr,"\t-X workers\t(Number of workers.)\n");
	fprintf(stderr,"\t-w \t\t(Verbose worker output.)\n");
#endif

#ifdef RPC
	fprintf(stderr,"\n\n\nThis is the adaption of Craig Kolb`s Rayshade 4.0\n");
	fprintf(stderr," to the RRLib. With the RRLib you can distribute \n");
	fprintf(stderr," the Rendering of rectangular pictures on a hetergeneus TCP/IP Networks,\n");
	fprintf(stderr," in order to make it faster. This works by dividing one frame\n");
	fprintf(stderr," in little squares. There are no restictions about the number of Servers\n");
	fprintf(stderr," The RS adaption to RRLib doesn't need any NFS, FTP or something like this.\n");
	fprintf(stderr," All Data go directly mem to mem over the Network, even imagefiles and maps\n");
	fprintf(stderr," But RRLib is developed with Sun's ONC-RPC (TM) and needs it's Portmapper\n");
	fprintf(stderr," Ask your SysAdmin to install the Portmapper, when you get a error message.\n");
	fprintf(stderr," your system UNIX (TM)  must have a portmapper /etc/portmap \n");
	fprintf(stderr," startet in the /etc/rc.local. otherwise get a free copy from SUN\n\n\n");
	fprintf(stderr," The RRLib is fault tolerant.  A server may crash or be aborted\n");
	fprintf(stderr," killed  by user or rsh, the client remarks it and sends the outstanding\n");
	fprintf(stderr," square to another server, you can start a new private server, \n");
	fprintf(stderr," but you don't have to. If you  don't, the client sends the square to one\n");
	fprintf(stderr," of the remaining servers. If there isn't any server anymore, you have\n");
	fprintf(stderr," to invoke a new one, or you can abort the client.\n\n\n");
	fprintf(stderr," The RRLib is loadbalancing and doesn`t fork.\n\n");
	fprintf(stderr," If you use ten servers on ten workstations you will observe that \n");
	fprintf(stderr," rayshade with the RRLib is  about 8 times faster refering to complex scenes\n");
	fprintf(stderr," than without RRLib on one of the same machines.\n");
	fprintf(stderr," Simple scenes are about 5 times faster. \n\n\n");
	fprintf(stderr," Every render program, that is able to render subwindows,\n");
	fprintf(stderr," can be adapted to the RRLib even binaries like Pixars \n");
	fprintf(stderr," Render Man (TM)\n");

	fprintf(stderr," \tRayshade 4.0, Verion for the remote render library \n");
	fprintf(stderr," \t(C) & but no warranties by\n");
	fprintf(stderr," \tWilfried Koch\n");
	fprintf(stderr," \tPalanter Str. 46\n");
	fprintf(stderr," \tD-5000 Koeln 41\n");
	fprintf(stderr," \tGermany\n");
	fprintf(stderr," \temail: bj030@aix370.rrz.uni-koeln.de\n");


	fprintf(stderr," \nWriting the rayshade.srv file:\n");

	fprintf(stderr," \tThe rayshade.srv file , which holds a List of the servers,\n");
	fprintf(stderr," \tmust be in the current directory\n");
	fprintf(stderr," \tfrom where you start the client with ray -i[n] ... rayshade options\n");

	fprintf(stderr," \tThere are two modes of connecting client and servers which you can mix: \n");

	fprintf(stderr," \t\n\nExample Mode 2 (public servers ):\n");
	fprintf(stderr," --------------------\n");
	fprintf(stderr," \tthe rayshade.srv file  must look like this\n\n");
	
	fprintf(stderr," \t	2 host1\n");
	fprintf(stderr," \t	2 host2\n");
	fprintf(stderr," \t	2 host3\n");
	fprintf(stderr," \t	2 host4\n");
	fprintf(stderr," \t	2 host5\n");
	fprintf(stderr," \t	-1 end  (!don't forget) \n\n");


	fprintf(stderr," You must type ray -i- on 5 hosts (host1 - host5) : \n");
	fprintf(stderr," 	host1%% ray-i- ....... host5%% ray -i-\n");
	fprintf(stderr," By this 5 servers are invoked on 5 hosts\n");
	fprintf(stderr," After this you can invoke the client by ray -i[n]\n ");
	fprintf(stderr," followed by the normal rayshade arguments\n");

	fprintf(stderr," Servers invoked only by -i- are public and can be used\n");
	fprintf(stderr," by other clients too, they don't exit after the client finished\n");
	fprintf(stderr," Public Mode is not fully tested yet.\n\n");

	
	fprintf(stderr," Example Mode 1 (private servers):\n");
	fprintf(stderr," --------------------\n");
	fprintf(stderr,"	1  rsh  host1  -n   nice -19 path/ray 2>/dev/null -i-\n");
	fprintf(stderr,"	1  rsh  host2  -n   nice -19 path/ray 2>/dev/null  -i-\n");
	fprintf(stderr,"	1  rsh  host3  -n   nice -19 path/ray 2>/dev/null  -i-\n");
	fprintf(stderr,"	1  rsh  host4  -n   nice -19 path/ray 2>/dev/null  -i-\n");
	fprintf(stderr,"	1  rsh  host5  -n   nice -19 path/ray 2>/dev/null  -i-\n");
	fprintf(stderr,"	-1  end (don't forget !)\n\n");

	fprintf(stderr,"Don't forget tho place the clients host/user name in ~/.rhosts\n");
	fprintf(stderr,"on your servers host account. Don't use blank lines in rayshade.srv\n\n");
	fprintf(stderr,"After you invoked ray -i ... on the client's host.\n");
	fprintf(stderr,"the client cats its 'number@hostaname &' behind -i-\n");
	fprintf(stderr,"and passes the string behind mode number '1' to system()\n");
	fprintf(stderr,"The Servers are private and exit after the client is ready\n\n");


	
	fprintf(stderr,"If you don`t have a rayshade.srv file in the current \n"); 
	fprintf(stderr,"directory, you have to invoke some servers by hand or a batch\n");
	fprintf(stderr,"- after you started the client - with following option:\n\n");
	
	fprintf(stderr," -i-n@host	invoke rayshade as a private server. \n");
	fprintf(stderr,"                n ist the Transient number of the client, it prints\n");
	fprintf(stderr,"                after it's invocation. host is the client's hostname\n\n");
	fprintf(stderr,"!!!! You can invoke any number of additional servers  !!!!!\n");
	fprintf(stderr,"!!!! at any time to any client on any host during Rendering !!!!!!\n\n");

	
	fprintf(stderr," other options :\n\n");	
	
	fprintf(stderr," -i[n]		invoke rayshade as a client. n is optional and determs\n");	
	fprintf(stderr,"		the size of squares in pixels, a frame is devided in,\n");	
	fprintf(stderr,"		default is 100.\n");	

	fprintf(stderr," -d		display the frame(s) on a 24 Bit X-Display\n");	
	fprintf(stderr," 		You can watch the squares coming in from the servers\n");	
	fprintf(stderr," 		Don`t worry, sometimes they are a little bit dark, but in the \n");
	fprintf(stderr," 		output file they are correct\n\n\n");	

	fprintf(stderr,"Known BUGS:	A lot of orthographical mistakes in this text\n\n\n");

	fprintf(stderr, " Now a very simple example:\n\n");
	fprintf(stderr, "\t first  type on client host:\n");
	fprintf(stderr, "\t client%% ray -i exa/csg.ray\n");
	fprintf(stderr, "\t CLIENT client     Transient No. 3 RRID 710551186\n\n");
	fprintf(stderr, "\t Note the transient number (here it's 3) and type on the server hosts:\n\n");
	fprintf(stderr, "\t server1%% ray -i-3@client\n");
	fprintf(stderr, "\t server2%% ray -i-3@client\n");
	fprintf(stderr, "\t    .\n");
	fprintf(stderr, "\t    .\n");
	fprintf(stderr, "\t    .\n\n");

	fprintf(stderr,"Feel free to trace Animations with squares as big as the frame\n");	
	fprintf(stderr,"Every Rayshade Option works, also -O -c offcourse. If you use -c\n");	
	fprintf(stderr,"without having a fragment of a outputfile, the client crashs. I think it's\n");
	fprintf(stderr,"a bug in Rayshade.\n");	
	fprintf(stderr,"The Rayshade adoption still works  in the normal local manner \n");	
	fprintf(stderr,"when not using -i or -i-\n\n");	
	fprintf(stderr,"Thanks to Craig for his great raytracer, to Bob Lyon for ONC-RPC\n");
	fprintf(stderr,"and especially  to J.R. Corbin for the documentation of it: \n");	
	fprintf(stderr,	"The Art of Distibuted Applications \n");	

#endif
	
 
}
