Ejemplo n.º 1
0
/*
 *  The only argument is the name of the database file.
 */
void
ph_dirbuild(struct pkg_conn *UNUSED(pc), char *buf)
{
    long max_argc = 0;
    char **argv = NULL;
    struct rt_i *rtip = NULL;
    size_t n = 0;

    if (debug)  fprintf(stderr, "ph_dirbuild: %s\n", buf);

    for (n = 0; n < strlen(buf); n++) {
	if (isspace((int)buf[n]))
	    max_argc++;
    }
    argv = (char **)bu_calloc(max_argc+1, sizeof(char *), "alloc argv");

    if ((bu_argv_from_string(argv, max_argc, buf)) <= 0)  {
	/* No words in input */
	(void)free(buf);
	bu_free(argv, "free argv");
	return;
    }

    if (seen_dirbuild)  {
	bu_log("ph_dirbuild:  MSG_DIRBUILD already seen, ignored\n");
	(void)free(buf);
	bu_free(argv, "free argv");
	return;
    }

    title_file = bu_strdup(argv[0]);
    bu_free(argv, "free argv");

    /* Build directory of GED database */
    if ((rtip=rt_dirbuild(title_file, idbuf, sizeof(idbuf))) == RTI_NULL)
	bu_exit(2, "ph_dirbuild:  rt_dirbuild(%s) failure\n", title_file);
    APP.a_rt_i = rtip;
    seen_dirbuild = 1;

    /*
     *  Initialize all the per-CPU memory resources.
     *  Go for the max, as TCL interface may change npsw as we run.
     */
    for (n=0; n < MAX_PSW; n++)  {
	rt_init_resource(&resource[n], n, rtip);
	bn_rand_init(resource[n].re_randptr, n);
    }

    if (pkg_send(MSG_DIRBUILD_REPLY,
		   idbuf, strlen(idbuf)+1, pcsrv) < 0)
	fprintf(stderr, "MSG_DIRBUILD_REPLY error\n");
}
Ejemplo n.º 2
0
/**
 * load database and prepare for raytracing
 */
void
fit_prep(struct fitness_state *fstate, int rows, int cols)
{
    fstate->max_cpus = fstate->ncpu = 1;/*bu_avail_cpus();*/
    fstate->capture = 0;
    fstate->res[X] = rows;
    fstate->res[Y] = cols;
    fstate->ray = NULL;

    bu_semaphore_init(TOTAL_SEMAPHORES);
    rt_init_resource(&rt_uniresource, fstate->max_cpus, NULL);
    bn_rand_init(rt_uniresource.re_randptr, 0);
}
Ejemplo n.º 3
0
/**
 *	P O P _ I N I T --- initialize a population of a given size
 */
void
pop_init (struct population *p, int size)
{
    p->parent = bu_malloc(sizeof(struct individual) * size, "parent");
    p->child  = bu_malloc(sizeof(struct individual) * size, "child");
    p->size = size;
    p->db_c = p->db_p = DBI_NULL;
    p->name = bu_malloc(sizeof(char *) * size, "names");

#define SEED 33
    /* init in main() bn_rand_init(randomer, SEED);*/
    bn_rand_init(randomer, SEED);
}
Ejemplo n.º 4
0
/**
 * Creates one metaball object with 'count' random points using
 * LIBWDB's mk_metaball() interface.
 */
static void
make_meatballs(struct rt_wdb *fp, const char *name, long count)
{
    static float *ctx; /* random context */
    static const int method = 1; /* 1==ISO */
    static const fastf_t threshold = 1.0;
    static const fastf_t SZ = 1000.0;

    long i;
    fastf_t **pts;

    RT_CK_WDB(fp);

    bn_rand_init(ctx, rand());
    bu_log("Creating [%s] object with %ld random point%s\n", name, count, count > 1 ? "s" : "");

    /* allocate a dynamic array of pointers to points.  this may be
     * subject to change but is presently the format mk_metaball()
     * wants.
     */
    pts = (fastf_t **)bu_calloc(count, sizeof(fastf_t*), "alloc metaball pts array");
    for (i=0; i < count; i++) {
	pts[i] = (fastf_t *)bu_malloc(sizeof(fastf_t)*5, "alloc metaball point");
    }

    /* create random metaball point values positioned randomly within
     * a cube with random field strengths.
     */
    for (i=0; i < count; i++) {
	/* just for explicit clarity */
	fastf_t x = bn_rand_half(ctx) * SZ;
	fastf_t y = bn_rand_half(ctx) * SZ;
	fastf_t z = bn_rand_half(ctx) * SZ;
	fastf_t field_strength = bn_rand0to1(ctx) * SZ / (2.0 * sqrt(count));

	VSET(pts[i], x, y, z);
	pts[i][3] = field_strength; /* something blobbly random */
	pts[i][4] = 0.0; /* sweat/goo field is unused with iso method */
    }

    /* pack the meat, create the metaball */
    mk_metaball(fp, name, count, method, threshold, (const fastf_t **)pts);

    /* free up our junk */
    for (i=0; i < count; i++) {
	bu_free(pts[i], "dealloc metaball point");
    }
    bu_free(pts, "dealloc metaball pts array");
}
Ejemplo n.º 5
0
int
main(int argc, char **argv)
{
    register float	*randp;
    struct color_rec {
	unsigned char red, green, blue;
    } cur_color;

    bn_rand_init( randp, 0);

    if ( !get_args( argc, argv ) )  {
	(void)fputs(usage, stderr);
	bu_exit ( 1, NULL );
    }

/* fprintf(stderr, "pixfade: max = %d, multiplier = %f\n", max, multiplier); */


    for (;;)  {
	register double	t;

	if ( fread(&cur_color, 1, 3, inp) != 3 )  break;
	if ( feof(inp) )  break;

	t = cur_color.red * multiplier + bn_rand_half(randp);
	if (t > max)
	    cur_color.red   = max;
	else
	    cur_color.red = t;

	t = cur_color.green * multiplier + bn_rand_half(randp);
	if (t > max)
	    cur_color.green = max;
	else
	    cur_color.green = t;

	t = cur_color.blue * multiplier + bn_rand_half(randp);
	if (t > max)
	    cur_color.blue  = max;
	else
	    cur_color.blue = t;

	fwrite(&cur_color, 1, 3, stdout);
    }
    return 0;
}
Ejemplo n.º 6
0
int
main(int argc, char **argv)
{
    int	n;

    if (argc < 2)  {
	fprintf(stderr, "%s", srv_usage);
	return 1;
    }
    while (argv[1][0] == '-')  {
	if (BU_STR_EQUAL(argv[1], "-d"))  {
	    debug++;
	} else if (BU_STR_EQUAL(argv[1], "-x"))  {
	    sscanf(argv[2], "%x", (unsigned int *)&RTG.debug);
	    argc--; argv++;
	} else if (BU_STR_EQUAL(argv[1], "-X"))  {
	    sscanf(argv[2], "%x", (unsigned int *)&rdebug);
	    argc--; argv++;
	} else {
	    fprintf(stderr, "%s", srv_usage);
	    return 3;
	}
	argc--; argv++;
    }
    if (argc != 3 && argc != 4)  {
	fprintf(stderr, "%s", srv_usage);
	return 2;
    }

    control_host = argv[1];
    tcp_port = argv[2];

    /* Note that the LIBPKG error logger can not be
     * "bu_log", as that can cause bu_log to be entered recursively.
     * Given the special version of bu_log in use here,
     * that will result in a deadlock in bu_semaphore_acquire(res_syscall)!
     *  libpkg will default to stderr via pkg_errlog(), which is fine.
     */
    pcsrv = pkg_open(control_host, tcp_port, "tcp", "", "",
		      pkgswitch, NULL);
    if (pcsrv == PKC_ERROR)  {
	fprintf(stderr, "rtsrv: unable to contact %s, port %s\n",
		control_host, tcp_port);
	return 1;
    }

    if (argc == 4)  {
	/* Slip one command to dispatcher */
	(void)pkg_send(MSG_CMD, argv[3], strlen(argv[3])+1, pcsrv);

	/* Prevent chasing the package with an immediate TCP close */
	sleep(1);

	pkg_close(pcsrv);
	return 0;
    }

#ifdef SO_SNDBUF
    /* increase the default send buffer size to 32k since we're
     * sending pixels more than likely.
     */
    {
	int val = 32767;
	n = setsockopt(pcsrv->pkc_fd, SOL_SOCKET, SO_SNDBUF, (const void *)&val, sizeof(val));
	if (n < 0)  perror("setsockopt: SO_SNDBUF");
    }
#endif

    if (!debug)  {
	/* A fresh process */
	if (fork())
	    return 0;

	/* Go into our own process group */
	n = bu_process_id();

#ifdef HAVE_SETPGID
	if (setpgid(n, n) < 0)
	    perror("setpgid");
#else
	/* SysV uses setpgrp with no args and it can't fail,
	 * obsoleted by setpgid.
	 */
	setpgrp();
#endif

	/*
	 *  Unless controller process has specifically said
	 *  that this is an interactive session, e.g., for a demo,
	 *  drop to the lowest sensible priority.
	 */
	if (!interactive)  {
	    bu_nice_set(19);		/* lowest priority */
	}

	/* Close off the world */
	fclose(stdin);
	fclose(stdout);
	fclose(stderr);

	(void)close(0);
	(void)close(1);
	(void)close(2);

	/* For stdio & perror safety, reopen 0, 1, 2 */
	(void)open("/dev/null", 0);	/* to fd 0 */
	n = dup(0);			/* to fd 1 */
	if (n == -1)
	    perror("dup");
	n = dup(0);			/* to fd 2 */
	if (n == -1)
	    perror("dup");

#if defined(HAVE_SYS_IOCTL_H) && defined(TIOCNOTTY)
	n = open("/dev/tty", 2);
	if (n >= 0) {
	    (void)ioctl(n, TIOCNOTTY, 0);
	    (void)close(n);
	}
#endif
    }

    /* Send our version string */
    if (pkg_send(MSG_VERSION,
		   PROTOCOL_VERSION, strlen(PROTOCOL_VERSION)+1, pcsrv) < 0)  {
	fprintf(stderr, "pkg_send MSG_VERSION error\n");
	return 1;
    }
    if (debug)  fprintf(stderr, "PROTOCOL_VERSION='%s'\n", PROTOCOL_VERSION);

    /*
     *  Now that the fork() has been done, it is safe to initialize
     *  the parallel processing support.
     */

    avail_cpus = bu_avail_cpus();

    /* Need to set rtg_parallel non_zero here for RES_INIT to work */
    npsw = avail_cpus;
    if (npsw > 1)  {
	RTG.rtg_parallel = 1;
    } else
	RTG.rtg_parallel = 0;
    bu_semaphore_init(RT_SEM_LAST);

    bu_log("using %d of %d cpus\n",
	   npsw, avail_cpus);

    /*
     *  Initialize the non-parallel memory resource.
     *  The parallel guys are initialized after the rt_dirbuild().
     */
    rt_init_resource(&rt_uniresource, MAX_PSW, NULL);
    bn_rand_init(rt_uniresource.re_randptr, MAX_PSW);

    BU_LIST_INIT(&WorkHead);

    for (;;)  {
	struct pkg_queue	*lp;
	fd_set ifds;
	struct timeval tv;

	/* First, process any packages in library buffers */
	if (pkg_process(pcsrv) < 0)  {
	    bu_log("pkg_get error\n");
	    break;
	}

	/* Second, see if any input to read */
	FD_ZERO(&ifds);
	FD_SET(pcsrv->pkc_fd, &ifds);
	tv.tv_sec = BU_LIST_NON_EMPTY(&WorkHead) ? 0L : 9999L;
	tv.tv_usec = 0L;

	if (select(pcsrv->pkc_fd+1, &ifds, (fd_set *)0, (fd_set *)0,
		    &tv) != 0)  {
	    n = pkg_suckin(pcsrv);
	    if (n < 0)  {
		bu_log("pkg_suckin error\n");
		break;
	    } else if (n == 0)  {
		/* EOF detected */
		break;
	    } else {
		/* All is well */
	    }
	}

	/* Third, process any new packages in library buffers */
	if (pkg_process(pcsrv) < 0)  {
	    bu_log("pkg_get error\n");
	    break;
	}

	/* Finally, more work may have just arrived, check our list */
	if (BU_LIST_NON_EMPTY(&WorkHead))  {
	    lp = BU_LIST_FIRST(pkg_queue, &WorkHead);
	    BU_LIST_DEQUEUE(&lp->l);
	    switch (lp->type)  {
		case MSG_MATRIX:
		    ph_matrix((struct pkg_conn *)0, lp->buf);
		    break;
		case MSG_LINES:
		    ph_lines((struct pkg_conn *)0, lp->buf);
		    break;
		case MSG_OPTIONS:
		    ph_options((struct pkg_conn *)0, lp->buf);
		    break;
		case MSG_GETTREES:
		    ph_gettrees((struct pkg_conn *)0, lp->buf);
		    break;
		default:
		    bu_log("bad list element, type=%d\n", lp->type);
		    return 33;
	    }
	    BU_PUT(lp, struct pkg_queue);
	}
    }

    return 0;		/* bu_exit(0, NULL) */
}
Ejemplo n.º 7
0
/**
 * Called at the start of a run.
 *
 * Returns 1 if framebuffer should be opened, else 0.
 */
int
view_init(struct application *ap, char *file, char *UNUSED(obj), int minus_o, int minus_F)
{
    /*
     * Allocate a scanline for each processor.
     */
    ap->a_hit = rayhit;
    ap->a_miss = raymiss;
    ap->a_onehit = 1;

    /*
     * Does the user want occlusion checking?
     *
     * If so, load and prep.
     */
    if (bu_vls_strlen(&occlusion_objects) != 0) {
	struct db_i *dbip;
	int nObjs;
	const char **objs;
	int i;

	bu_log("rtedge: loading occlusion geometry from %s.\n", file);

	if (Tcl_SplitList(NULL, bu_vls_addr(&occlusion_objects), &nObjs,
			  &objs) == TCL_ERROR) {
	    bu_log("rtedge: occlusion list = %s\n",
		   bu_vls_addr(&occlusion_objects));
	    bu_exit(EXIT_FAILURE, "rtedge: could not parse occlusion objects list.\n");
	}

	for (i=0; i<nObjs; ++i) {
	    bu_log("rtedge: occlusion object %d = %s\n", i, objs[i]);
	}


	if ((dbip = db_open(file, DB_OPEN_READONLY)) == DBI_NULL)
	    bu_exit(EXIT_FAILURE, "rtedge: could not open geometry database file %s.\n", file);
	RT_CK_DBI(dbip);

#if 0
	/* FIXME: calling this when db_open()'s mapped file doesn't
	 * fail will cause duplicate directory entries.  need to make
	 * sure db_dirbuild rebuilds from scratch or only updates
	 * existing entries when they exist.
	 */
	if (db_dirbuild(dbip) < 0)
	    bu_exit(EXIT_FAILURE, "rtedge: could not read database.\n");
#endif

	occlusion_rtip = rt_new_rti(dbip); /* clones dbip */

	for (i=0; i < MAX_PSW; i++) {
	    rt_init_resource(&occlusion_resources[i], i, occlusion_rtip);
	    bn_rand_init(occlusion_resources[i].re_randptr, i);
	}

	db_close(dbip);			 /* releases original dbip */

	for (i=0; i<nObjs; ++i)
	    if (rt_gettree(occlusion_rtip, objs[i]) < 0)
		bu_log("rtedge: gettree failed for %s\n", objs[i]);
	    else
		bu_log("rtedge: got tree for object %d = %s\n", i, objs[i]);

	bu_log("rtedge: occlusion rt_gettrees done.\n");

	rt_prep(occlusion_rtip);

	bu_log("rtedge: occlusion prep done.\n");

	/*
	 * Create a set of application structures for the occlusion
	 * geometry. Need one per cpu, the upper half does the per-
	 * thread allocation in worker, but that's off limits.
	 */
	occlusion_apps = (struct application **)bu_calloc(npsw, sizeof(struct application *),
							  "occlusion application structure array");
	for (i=0; i<npsw; ++i) {
	    BU_ALLOC(occlusion_apps[i], struct application);
	    RT_APPLICATION_INIT(occlusion_apps[i]);

	    occlusion_apps[i]->a_rt_i = occlusion_rtip;
	    occlusion_apps[i]->a_resource = (struct resource *)BU_PTBL_GET(&occlusion_rtip->rti_resources, i);
	    occlusion_apps[i]->a_onehit = 1;
	    occlusion_apps[i]->a_hit = occlusion_hit;
	    occlusion_apps[i]->a_miss = occlusion_miss;
	    if (rpt_overlap)
		occlusion_apps[i]->a_logoverlap = (void (*)(struct application *, const struct partition *, const struct bu_ptbl *, const struct partition *))NULL;
	    else
		occlusion_apps[i]->a_logoverlap = rt_silent_logoverlap;

	}
	bu_log("rtedge: will perform occlusion testing.\n");

	/*
	 * If an inclusion mode has not been specified, use the default.
	 */
	if (occlusion_mode == OCCLUSION_MODE_NONE) {
	    occlusion_mode = OCCLUSION_MODE_DEFAULT;
	    bu_log("rtedge: occlusion mode = %d\n", occlusion_mode);
	}

	if ((occlusion_mode != OCCLUSION_MODE_NONE) &&
	    (overlay == OVERLAY_MODE_UNSET)) {
	    bu_log("rtedge: automagically activating overlay mode.\n");
	    overlay = OVERLAY_MODE_DOIT;
	}

    }

    if (occlusion_mode != OCCLUSION_MODE_NONE &&
	bu_vls_strlen(&occlusion_objects) == 0) {
	bu_exit(EXIT_FAILURE, "rtedge: occlusion mode set, but no objects were specified.\n");
    }

    /* if non-default/inverted background was requested, swap the
     * foreground and background colors.
     */
    if (!default_background) {
	color tmp;
	tmp[RED] = fgcolor[RED];
	tmp[GRN] = fgcolor[GRN];
	tmp[BLU] = fgcolor[BLU];
	fgcolor[RED] = bgcolor[RED];
	fgcolor[GRN] = bgcolor[GRN];
	fgcolor[BLU] = bgcolor[BLU];
	bgcolor[RED] = tmp[RED];
	bgcolor[GRN] = tmp[GRN];
	bgcolor[BLU] = tmp[BLU];
    }

    if (minus_o && (overlay || blend)) {
	/*
	 * Output is to a file stream.  Do not allow parallel
	 * processing since we can't seek to the rows.
	 */
	RTG.rtg_parallel = 0;
	bu_log("view_init: deactivating parallelism due to -o option.\n");
	/*
	 * The overlay and blend cannot be used in -o mode.  Note that
	 * the overlay directive takes precedence, they can't be used
	 * together.
	 */
	overlay = 0;
	blend = 0;
	bu_log("view_init: deactivating overlay and blending due to -o option.\n");
    }

    if (overlay)
	bu_log("view_init: will perform simple overlay.\n");
    else if (blend)
	bu_log("view_init: will perform blending.\n");

    return minus_F || (!minus_o && !minus_F); /* we need a framebuffer */
}
Ejemplo n.º 8
0
/*
 *			M A I N
 */
int main(int argc, char **argv)
{
    struct rt_i *rtip = NULL;
    char *title_file = NULL, *title_obj = NULL;	/* name of file and first object */
    char idbuf[RT_BUFSIZE] = {0};		/* First ID record info */
    void	application_init();
    struct bu_vls	times;
    int i;

#if defined(_WIN32) && !defined(__CYGWIN__)
    setmode(fileno(stdin), O_BINARY);
    setmode(fileno(stdout), O_BINARY);
    setmode(fileno(stderr), O_BINARY);
#else
    bu_setlinebuf( stdout );
    bu_setlinebuf( stderr );
#endif

#ifdef HAVE_SBRK
    beginptr = (char *) sbrk(0);
#endif
    azimuth = 35.0;			/* GIFT defaults */
    elevation = 25.0;

    AmbientIntensity=0.4;
    background[0] = background[1] = 0.0;
    background[2] = 1.0/255.0; /* slightly non-black */

    /* Before option processing, get default number of processors */
    npsw = bu_avail_cpus();		/* Use all that are present */
    if ( npsw > MAX_PSW )  npsw = MAX_PSW;

    /* Before option processing, do application-specific initialization */
    RT_APPLICATION_INIT( &ap );
    application_init();

    /* Process command line options */
    if ( !get_args( argc, argv ) )  {
	(void)fputs(usage, stderr);
	return 1;
    }
    /* Identify the versions of the libraries we are using. */
    if (rt_verbosity & VERBOSE_LIBVERSIONS) {
	(void)fprintf(stderr, "%s%s%s%s\n",
		      brlcad_ident(title),
		      rt_version(),
		      bn_version(),
		      bu_version()
	    );
    }
#if defined(DEBUG)
    (void)fprintf(stderr, "Compile-time debug symbols are available\n");
#endif
#if defined(NO_BOMBING_MACROS) || defined(NO_MAGIC_CHECKING) || defined(NO_BADRAY_CECHKING) || defined(NO_DEBUG_CHECKING)
    (void)fprintf(stderr, "WARNING: Run-time debugging is disabled and may enhance performance\n");
#endif

    /* Identify what host we're running on */
    if (rt_verbosity & VERBOSE_LIBVERSIONS) {
	char	hostname[512] = {0};
#ifndef _WIN32
	if ( gethostname( hostname, sizeof(hostname) ) >= 0 &&
	     hostname[0] != '\0' )
	    (void)fprintf(stderr, "Running on %s\n", hostname);
#else
	sprintf(hostname, "Microsoft Windows");
	(void)fprintf(stderr, "Running on %s\n", hostname);
#endif
    }

    if ( bu_optind >= argc )  {
	fprintf(stderr, "%s:  MGED database not specified\n", argv[0]);
	(void)fputs(usage, stderr);
	return 1;
    }

    if (rpt_overlap)
	ap.a_logoverlap = ((void (*)())0);
    else
	ap.a_logoverlap = rt_silent_logoverlap;

    /* If user gave no sizing info at all, use 512 as default */
    if ( width <= 0 && cell_width <= 0 )
	width = 512;
    if ( height <= 0 && cell_height <= 0 )
	height = 512;

    /* If user didn't provide an aspect ratio, use the image
     * dimensions ratio as a default.
     */
    if (aspect <= 0.0) {
	aspect = (fastf_t)width / (fastf_t)height;
    }

    if ( sub_grid_mode ) {
	/* check that we have a legal subgrid */
	if ( sub_xmax >= width || sub_ymax >= height ) {
	    fprintf( stderr, "rt: illegal values for subgrid %d,%d,%d,%d\n",
		     sub_xmin, sub_ymin, sub_xmax, sub_ymax );
	    fprintf( stderr, "\tFor a %d X %d image, the subgrid must be within 0, 0,%d,%d\n",
		     width, height, width-1, height-1 );
	    return 1;
	}
    }

    if ( incr_mode )  {
	int x = height;
	if ( x < width )  x = width;
	incr_nlevel = 1;
	while ( (1<<incr_nlevel) < x )
	    incr_nlevel++;
	height = width = 1<<incr_nlevel;
	if (rt_verbosity & VERBOSE_INCREMENTAL)
	    fprintf(stderr,
		    "incremental resolution, nlevels = %d, width=%d\n",
		    incr_nlevel, width);
    }

    /*
     *  Handle parallel initialization, if applicable.
     */
#ifndef PARALLEL
    npsw = 1;			/* force serial */
#endif

    if ( npsw < 0 )  {
	/* Negative number means "all but" npsw */
	npsw = bu_avail_cpus() + npsw;
    }


    /* allow debug builds to go higher than the max */
    if (!(bu_debug & BU_DEBUG_PARALLEL)) {
	if ( npsw > MAX_PSW ) {
	    npsw = MAX_PSW;
	}
    }

    if (npsw > 1) {
	rt_g.rtg_parallel = 1;
	if (rt_verbosity & VERBOSE_MULTICPU)
	    fprintf(stderr, "Planning to run with %d processors\n", npsw );
    } else {
	rt_g.rtg_parallel = 0;
    }

    /* Initialize parallel processor support */
    bu_semaphore_init( RT_SEM_LAST );

    /*
     *  Do not use bu_log() or bu_malloc() before this point!
     */

    if ( bu_debug )  {
	bu_printb( "libbu bu_debug", bu_debug, BU_DEBUG_FORMAT );
	bu_log("\n");
    }

    if ( RT_G_DEBUG )  {
	bu_printb( "librt rt_g.debug", rt_g.debug, DEBUG_FORMAT );
	bu_log("\n");
    }
    if ( rdebug )  {
	bu_printb( "rt rdebug", rdebug, RDEBUG_FORMAT );
	bu_log("\n");
    }

    /* We need this to run rt_dirbuild */
    rt_init_resource( &rt_uniresource, MAX_PSW, NULL );
    bn_rand_init( rt_uniresource.re_randptr, 0 );

    title_file = argv[bu_optind];
    title_obj = argv[bu_optind+1];
    nobjs = argc - bu_optind - 1;
    objtab = &(argv[bu_optind+1]);

    if ( nobjs <= 0 )  {
	bu_log("%s: no objects specified -- raytrace aborted\n", argv[0]);
	return 1;
    }

    /* Echo back the command line arugments as given, in 3 Tcl commands */
    if (rt_verbosity & VERBOSE_MODELTITLE) {
	struct bu_vls str;
	bu_vls_init(&str);
	bu_vls_from_argv( &str, bu_optind, (const char **)argv );
	bu_vls_strcat( &str, "\nopendb "  );
	bu_vls_strcat( &str, title_file );
	bu_vls_strcat( &str, ";\ntree " );
	bu_vls_from_argv( &str,
			  nobjs <= 16 ? nobjs : 16,
			  (const char **)argv+bu_optind+1 );
	if ( nobjs > 16 )
	    bu_vls_strcat( &str, " ...");
	else
	    bu_vls_putc( &str, ';' );
	bu_log("%s\n", bu_vls_addr(&str) );
	bu_vls_free(&str);
    }

    /* Build directory of GED database */
    bu_vls_init( &times );
    rt_prep_timer();
    if ( (rtip=rt_dirbuild(title_file, idbuf, sizeof(idbuf))) == RTI_NULL ) {
	bu_log("rt:  rt_dirbuild(%s) failure\n", title_file);
	return 2;
    }
    ap.a_rt_i = rtip;
    (void)rt_get_timer( &times, NULL );
    if (rt_verbosity & VERBOSE_MODELTITLE)
	bu_log("db title:  %s\n", idbuf);
    if (rt_verbosity & VERBOSE_STATS)
	bu_log("DIRBUILD: %s\n", bu_vls_addr(&times) );
    bu_vls_free( &times );
    memory_summary();

    /* Copy values from command line options into rtip */
    rtip->rti_space_partition = space_partition;
    rtip->rti_nugrid_dimlimit = nugrid_dimlimit;
    rtip->rti_nu_gfactor = nu_gfactor;
    rtip->useair = use_air;
    rtip->rti_save_overlaps = save_overlaps;
    if ( rt_dist_tol > 0 )  {
	rtip->rti_tol.dist = rt_dist_tol;
	rtip->rti_tol.dist_sq = rt_dist_tol * rt_dist_tol;
    }
    if ( rt_perp_tol > 0 )  {
	rtip->rti_tol.perp = rt_perp_tol;
	rtip->rti_tol.para = 1 - rt_perp_tol;
    }
    if (rt_verbosity & VERBOSE_TOLERANCE)
	rt_pr_tol( &rtip->rti_tol );

    /* before view_init */
    if ( outputfile && strcmp( outputfile, "-") == 0 )
	outputfile = (char *)0;

    /*
     *  Initialize application.
     *  Note that width & height may not have been set yet,
     *  since they may change from frame to frame.
     */
    if ( view_init( &ap, title_file, title_obj, outputfile!=(char *)0, framebuffer!=(char *)0 ) != 0 )  {
	/* Framebuffer is desired */
	register int xx, yy;
	int	zoom;

	/* Ask for a fb big enough to hold the image, at least 512. */
	/* This is so MGED-invoked "postage stamps" get zoomed up big enough to see */
	xx = yy = 512;
	if ( width > xx || height > yy )  {
	    xx = width;
	    yy = height;
	}
	bu_semaphore_acquire( BU_SEM_SYSCALL );
	fbp = fb_open( framebuffer, xx, yy );
	bu_semaphore_release( BU_SEM_SYSCALL );
	if ( fbp == FBIO_NULL )  {
	    fprintf(stderr, "rt:  can't open frame buffer\n");
	    return 12;
	}

	bu_semaphore_acquire( BU_SEM_SYSCALL );
	/* If fb came out smaller than requested, do less work */
	if ( fb_getwidth(fbp) < width )  width = fb_getwidth(fbp);
	if ( fb_getheight(fbp) < height )  height = fb_getheight(fbp);

	/* If the fb is lots bigger (>= 2X), zoom up & center */
	if ( width > 0 && height > 0 )  {
	    zoom = fb_getwidth(fbp)/width;
	    if ( fb_getheight(fbp)/height < zoom )
		zoom = fb_getheight(fbp)/height;
	} else {
	    zoom = 1;
	}
	(void)fb_view( fbp, width/2, height/2,
		       zoom, zoom );
	bu_semaphore_release( BU_SEM_SYSCALL );
    }
    if ( (outputfile == (char *)0) && (fbp == FBIO_NULL) )  {
	/* If not going to framebuffer, or to a file, then use stdout */
	if ( outfp == NULL )  outfp = stdout;
	/* output_is_binary is changed by view_init, as appropriate */
	if ( output_is_binary && isatty(fileno(outfp)) )  {
	    fprintf(stderr, "rt:  attempting to send binary output to terminal, aborting\n");
	    return 14;
	}
    }

    /*
     *  Initialize all the per-CPU memory resources.
     *  The number of processors can change at runtime, init them all.
     */
    for ( i=0; i < MAX_PSW; i++ )  {
	rt_init_resource( &resource[i], i, rtip );
	bn_rand_init( resource[i].re_randptr, i );
    }
    memory_summary();

#ifdef SIGUSR1
    (void)signal( SIGUSR1, siginfo_handler );
#endif
#ifdef SIGINFO
    (void)signal( SIGINFO, siginfo_handler );
#endif

    if ( !matflag )  {
	int frame_retval;
	def_tree( rtip );		/* Load the default trees */
	do_ae( azimuth, elevation );
	frame_retval = do_frame( curframe );
	if (frame_retval != 0) {
	    /* Release the framebuffer, if any */
	    if ( fbp != FBIO_NULL ) {
		fb_close(fbp);
	    }

	    return 1;
	}
    } else if ( !isatty(fileno(stdin)) && old_way( stdin ) )  {
	; /* All is done */
    } else {
	register char	*buf;
	register int	ret;
	/*
	 * New way - command driven.
	 * Process sequence of input commands.
	 * All the work happens in the functions
	 * called by rt_do_cmd().
	 */
	while ( (buf = rt_read_cmd( stdin )) != (char *)0 )  {
	    if ( R_DEBUG&RDEBUG_PARSE )
		fprintf(stderr, "cmd: %s\n", buf );
	    ret = rt_do_cmd( rtip, buf, rt_cmdtab );
	    bu_free( buf, "rt_read_cmd command buffer" );
	    if ( ret < 0 )
		break;
	}
	if ( curframe < desiredframe )  {
	    fprintf(stderr,
		    "rt:  Desired frame %d not reached, last was %d\n",
		    desiredframe, curframe);
	}
    }

    /* Release the framebuffer, if any */
    if (fbp != FBIO_NULL) {
	fb_close(fbp);
    }

    return(0);
}