double rt_read_timer(char *str, int len) { struct bu_vls vls = BU_VLS_INIT_ZERO; double cpu; int todo; if (!str) return rt_get_timer((struct bu_vls *)0, (double *)0); cpu = rt_get_timer(&vls, (double *)0); todo = bu_vls_strlen(&vls); if (todo > len) todo = len; bu_strlcpy(str, bu_vls_addr(&vls), todo); return cpu; }
void do_pixel(int cpu, int pat_num, int pixelnum) { struct application a; struct pixel_ext pe; vect_t stereo_point; /* Ref point on eye or view plane */ vect_t point; /* Ref point on eye or view plane */ vect_t colorsum = {(fastf_t)0.0, (fastf_t)0.0, (fastf_t)0.0}; int samplenum = 0; static const double one_over_255 = 1.0 / 255.0; const int pindex = (pixelnum * sizeof(RGBpixel)); if (lightmodel == 8) { /* Add timer here to start pixel-time for heat * graph, when asked. */ rt_prep_timer(); } /* Obtain fresh copy of global application struct */ a = APP; /* struct copy */ a.a_resource = &resource[cpu]; if (incr_mode) { register int i = 1<<incr_level; a.a_y = pixelnum/i; a.a_x = pixelnum - (a.a_y * i); /* a.a_x = pixelnum%i; */ if (incr_level != 0) { /* See if already done last pass */ if (((a.a_x & 1) == 0) && ((a.a_y & 1) == 0)) return; } a.a_x <<= (incr_nlevel-incr_level); a.a_y <<= (incr_nlevel-incr_level); } else { a.a_y = pixelnum/width; a.a_x = pixelnum - (a.a_y * width); /* a.a_x = pixelnum%width; */ } if (Query_one_pixel) { if (a.a_x == query_x && a.a_y == query_y) { rdebug = query_rdebug; RTG.debug = query_debug; } else { RTG.debug = rdebug = 0; } } if (sub_grid_mode) { if (a.a_x < sub_xmin || a.a_x > sub_xmax) return; if (a.a_y < sub_ymin || a.a_y > sub_ymax) return; } if (fullfloat_mode) { register struct floatpixel *fp; fp = &curr_float_frame[a.a_y*width + a.a_x]; if (fp->ff_frame >= 0) { return; /* pixel was reprojected */ } } /* Check the pixel map to determine if this image should be * rendered or not. */ if (pixmap) { a.a_user= 1; /* Force Shot Hit */ if (pixmap[pindex + RED] + pixmap[pindex + GRN] + pixmap[pindex + BLU]) { /* non-black pixmap pixel */ a.a_color[RED]= (double)(pixmap[pindex + RED]) * one_over_255; a.a_color[GRN]= (double)(pixmap[pindex + GRN]) * one_over_255; a.a_color[BLU]= (double)(pixmap[pindex + BLU]) * one_over_255; /* we're done */ view_pixel(&a); if ((size_t)a.a_x == width-1) { view_eol(&a); /* End of scan line */ } return; } } /* our starting point, used for non-jitter */ VJOIN2 (point, viewbase_model, a.a_x, dx_model, a.a_y, dy_model); /* not tracing the corners of a prism by default */ a.a_pixelext=(struct pixel_ext *)NULL; /* black or no pixmap, so compute the pixel(s) */ /* LOOP BELOW IS UNROLLED ONE SAMPLE SINCE THAT'S THE COMMON CASE. * * XXX - If you edit the unrolled or non-unrolled section, be sure * to edit the other section. */ if (hypersample == 0) { /* not hypersampling, so just do it */ /****************/ /* BEGIN UNROLL */ /****************/ if (jitter & JITTER_CELL) { jitter_start_pt(point, &a, samplenum, pat_num); } if (a.a_rt_i->rti_prismtrace) { /* compute the four corners */ pe.magic = PIXEL_EXT_MAGIC; VJOIN2(pe.corner[0].r_pt, viewbase_model, a.a_x, dx_model, a.a_y, dy_model); VJOIN2(pe.corner[1].r_pt, viewbase_model, (a.a_x+1), dx_model, a.a_y, dy_model); VJOIN2(pe.corner[2].r_pt, viewbase_model, (a.a_x+1), dx_model, (a.a_y+1), dy_model); VJOIN2(pe.corner[3].r_pt, viewbase_model, a.a_x, dx_model, (a.a_y+1), dy_model); a.a_pixelext = &pe; } if (rt_perspective > 0.0) { VSUB2(a.a_ray.r_dir, point, eye_model); VUNITIZE(a.a_ray.r_dir); VMOVE(a.a_ray.r_pt, eye_model); if (a.a_rt_i->rti_prismtrace) { VSUB2(pe.corner[0].r_dir, pe.corner[0].r_pt, eye_model); VSUB2(pe.corner[1].r_dir, pe.corner[1].r_pt, eye_model); VSUB2(pe.corner[2].r_dir, pe.corner[2].r_pt, eye_model); VSUB2(pe.corner[3].r_dir, pe.corner[3].r_pt, eye_model); } } else { VMOVE(a.a_ray.r_pt, point); VMOVE(a.a_ray.r_dir, APP.a_ray.r_dir); if (a.a_rt_i->rti_prismtrace) { VMOVE(pe.corner[0].r_dir, a.a_ray.r_dir); VMOVE(pe.corner[1].r_dir, a.a_ray.r_dir); VMOVE(pe.corner[2].r_dir, a.a_ray.r_dir); VMOVE(pe.corner[3].r_dir, a.a_ray.r_dir); } } if (report_progress) { report_progress = 0; bu_log("\tframe %d, xy=%d, %d on cpu %d, samp=%d\n", curframe, a.a_x, a.a_y, cpu, samplenum); } a.a_level = 0; /* recursion level */ a.a_purpose = "main ray"; (void)rt_shootray(&a); if (stereo) { fastf_t right, left; right = CRT_BLEND(a.a_color); VSUB2(stereo_point, point, left_eye_delta); if (rt_perspective > 0.0) { VSUB2(a.a_ray.r_dir, stereo_point, eye_model); VUNITIZE(a.a_ray.r_dir); VADD2(a.a_ray.r_pt, eye_model, left_eye_delta); } else { VMOVE(a.a_ray.r_pt, stereo_point); } a.a_level = 0; /* recursion level */ a.a_purpose = "left eye ray"; (void)rt_shootray(&a); left = CRT_BLEND(a.a_color); VSET(a.a_color, left, 0, right); } VADD2(colorsum, colorsum, a.a_color); /**************/ /* END UNROLL */ /**************/ } else { /* hypersampling, so iterate */ for (samplenum=0; samplenum<=hypersample; samplenum++) { /* shoot at a point based on the jitter pattern number */ /**********************/ /* BEGIN NON-UNROLLED */ /**********************/ if (jitter & JITTER_CELL) { jitter_start_pt(point, &a, samplenum, pat_num); } if (a.a_rt_i->rti_prismtrace) { /* compute the four corners */ pe.magic = PIXEL_EXT_MAGIC; VJOIN2(pe.corner[0].r_pt, viewbase_model, a.a_x, dx_model, a.a_y, dy_model); VJOIN2(pe.corner[1].r_pt, viewbase_model, (a.a_x+1), dx_model, a.a_y, dy_model); VJOIN2(pe.corner[2].r_pt, viewbase_model, (a.a_x+1), dx_model, (a.a_y+1), dy_model); VJOIN2(pe.corner[3].r_pt, viewbase_model, a.a_x, dx_model, (a.a_y+1), dy_model); a.a_pixelext = &pe; } if (rt_perspective > 0.0) { VSUB2(a.a_ray.r_dir, point, eye_model); VUNITIZE(a.a_ray.r_dir); VMOVE(a.a_ray.r_pt, eye_model); if (a.a_rt_i->rti_prismtrace) { VSUB2(pe.corner[0].r_dir, pe.corner[0].r_pt, eye_model); VSUB2(pe.corner[1].r_dir, pe.corner[1].r_pt, eye_model); VSUB2(pe.corner[2].r_dir, pe.corner[2].r_pt, eye_model); VSUB2(pe.corner[3].r_dir, pe.corner[3].r_pt, eye_model); } } else { VMOVE(a.a_ray.r_pt, point); VMOVE(a.a_ray.r_dir, APP.a_ray.r_dir); if (a.a_rt_i->rti_prismtrace) { VMOVE(pe.corner[0].r_dir, a.a_ray.r_dir); VMOVE(pe.corner[1].r_dir, a.a_ray.r_dir); VMOVE(pe.corner[2].r_dir, a.a_ray.r_dir); VMOVE(pe.corner[3].r_dir, a.a_ray.r_dir); } } if (report_progress) { report_progress = 0; bu_log("\tframe %d, xy=%d, %d on cpu %d, samp=%d\n", curframe, a.a_x, a.a_y, cpu, samplenum); } a.a_level = 0; /* recursion level */ a.a_purpose = "main ray"; (void)rt_shootray(&a); if (stereo) { fastf_t right, left; right = CRT_BLEND(a.a_color); VSUB2(stereo_point, point, left_eye_delta); if (rt_perspective > 0.0) { VSUB2(a.a_ray.r_dir, stereo_point, eye_model); VUNITIZE(a.a_ray.r_dir); VADD2(a.a_ray.r_pt, eye_model, left_eye_delta); } else { VMOVE(a.a_ray.r_pt, stereo_point); } a.a_level = 0; /* recursion level */ a.a_purpose = "left eye ray"; (void)rt_shootray(&a); left = CRT_BLEND(a.a_color); VSET(a.a_color, left, 0, right); } VADD2(colorsum, colorsum, a.a_color); /********************/ /* END NON-UNROLLED */ /********************/ } /* for samplenum <= hypersample */ { /* scale the hypersampled results */ fastf_t f; f = 1.0 / (hypersample+1); VSCALE(a.a_color, colorsum, f); } } /* end unrolling else case */ /* bu_log("2: [%d, %d] : [%.2f, %.2f, %.2f]\n", pixelnum%width, pixelnum/width, a.a_color[0], a.a_color[1], a.a_color[2]); */ /* FIXME: this should work on windows after the bu_timer() is * created to replace the librt timing mechanism. */ #if !defined(_WIN32) || defined(__CYGWIN__) /* Add get_pixel_timer here to get total time taken to get pixel, when asked */ if (lightmodel == 8) { fastf_t pixelTime; fastf_t **timeTable; pixelTime = rt_get_timer(NULL,NULL); /* bu_log("PixelTime = %lf X:%d Y:%d\n", pixelTime, a.a_x, a.a_y); */ bu_semaphore_acquire(RT_SEM_LAST-2); timeTable = timeTable_init(width, height); timeTable_input(a.a_x, a.a_y, pixelTime, timeTable); bu_semaphore_release(RT_SEM_LAST-2); } #endif /* we're done */ view_pixel(&a); if ((size_t)a.a_x == width-1) { view_eol(&a); /* End of scan line */ } return; }
/** * R T _ M E T A B A L L _ T E S S * * Tessellate a metaball. */ int rt_metaball_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol) { struct rt_metaball_internal *mb; fastf_t mtol, radius; point_t center, min, max; fastf_t i, j, k, finalstep = +INFINITY; struct bu_vls times = BU_VLS_INIT_ZERO; struct wdb_metaballpt *mbpt; struct shell *s; int numtri = 0; if (r == NULL || m == NULL) return -1; *r = NULL; NMG_CK_MODEL(m); RT_CK_DB_INTERNAL(ip); mb = (struct rt_metaball_internal *)ip->idb_ptr; RT_METABALL_CK_MAGIC(mb); rt_prep_timer(); /* since this geometry isn't necessarily prepped, we have to figure out the * finalstep and bounding box manually. */ for (BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head)) V_MIN(finalstep, mbpt->fldstr); finalstep /= (fastf_t)1e5; radius = rt_metaball_get_bounding_sphere(¢er, mb->threshold, mb); if(radius < 0) { /* no control points */ bu_log("Attempting to tesselate metaball with no control points"); return -1; } rt_metaball_bbox(ip, &min, &max, tol); /* TODO: get better sampling tolerance, unless this is "good enough" */ mtol = ttol->abs; V_MAX(mtol, ttol->rel * radius * 10); V_MAX(mtol, tol->dist); *r = nmg_mrsv(m); /* new empty nmg */ s = BU_LIST_FIRST(shell, &(*r)->s_hd); /* the incredibly naïve approach. Time could be cut in half by simply * caching 4 point values, more by actually marching or doing active * refinement. This is the simplest pattern for now. */ for (i = min[X]; i < max[X]; i += mtol) for (j = min[Y]; j < max[Y]; j += mtol) for (k = min[Z]; k < max[Z]; k += mtol) { point_t p[8]; int pv = 0; /* generate the vertex values */ #define MEH(c,di,dj,dk) VSET(p[c], i+di, j+dj, k+dk); pv |= rt_metaball_point_inside((const point_t *)&p[c], mb) << c; MEH(0, 0, 0, mtol); MEH(1, mtol, 0, mtol); MEH(2, mtol, 0, 0); MEH(3, 0, 0, 0); MEH(4, 0, mtol, mtol); MEH(5, mtol, mtol, mtol); MEH(6, mtol, mtol, 0); MEH(7, 0, mtol, 0); #undef MEH if ( pv != 0 && pv != 255 ) { /* entire cube is either inside or outside */ point_t edges[12]; int rval; /* compute the edge values (if needed) */ #define MEH(a,b,c) if(!(pv&(1<<b)&&pv&(1<<c))) { \ rt_metaball_find_intersection(edges+a, mb, (const point_t *)(p+b), (const point_t *)(p+c), mtol, finalstep); \ } /* magic numbers! an edge, then the two attached vertices. * For edge/vertex mapping, refer to the awesome ascii art * at the beginning of this file. */ MEH(0 ,0,1); MEH(1 ,1,2); MEH(2 ,2,3); MEH(3 ,0,3); MEH(4 ,4,5); MEH(5 ,5,6); MEH(6 ,6,7); MEH(7 ,4,7); MEH(8 ,0,4); MEH(9 ,1,5); MEH(10,2,6); MEH(11,3,7); #undef MEH rval = nmg_mc_realize_cube(s, pv, (point_t *)edges, tol); numtri += rval; if(rval < 0) { bu_log("Error attempting to realize a cube O.o\n"); return rval; } } } nmg_mark_edges_real(&s->l.magic); nmg_region_a(*r, tol); nmg_model_fuse(m, tol); rt_get_timer(×, NULL); bu_log("metaball tesselate (%d triangles): %s\n", numtri, bu_vls_addr(×)); return 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( × ); 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( ×, 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(×) ); bu_vls_free( × ); 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); }