PageRenderTime 86ms CodeModel.GetById 51ms RepoModel.GetById 0ms app.codeStats 0ms

/brlcad/tags/rel-7-14-0/src/rt/do.c

https://bitbucket.org/vrrm/brl-cad-copy-for-fast-history-browsing-in-git
C | 1052 lines | 698 code | 123 blank | 231 comment | 143 complexity | 625c38e8fa97966d73b13670123312fe MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, LGPL-2.1, Apache-2.0, AGPL-3.0, LGPL-3.0, GPL-3.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, 0BSD, BSD-3-Clause
  1. /* D O . C
  2. * BRL-CAD
  3. *
  4. * Copyright (c) 1987-2008 United States Government as represented by
  5. * the U.S. Army Research Laboratory.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public License
  9. * version 2.1 as published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this file; see the file named COPYING for more
  18. * information.
  19. */
  20. /** @file do.c
  21. *
  22. * Routines that process the various commands, and manage
  23. * the overall process of running the raytracing process.
  24. *
  25. */
  26. #include "common.h"
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include <ctype.h>
  31. #include <math.h>
  32. #ifdef HAVE_SYS_TYPES_H
  33. # include <sys/types.h>
  34. #endif
  35. #ifdef HAVE_SYS_STAT_H
  36. # include <sys/stat.h>
  37. #endif
  38. #include "vmath.h"
  39. #include "raytrace.h"
  40. #include "fb.h"
  41. #include "rtprivate.h"
  42. #include "bu.h"
  43. /***** Variables shared with viewing model *** */
  44. extern FILE *outfp; /* optional pixel output file */
  45. extern double azimuth, elevation;
  46. extern mat_t view2model;
  47. extern mat_t model2view;
  48. /***** end of sharing with viewing model *****/
  49. extern void grid_setup(void);
  50. extern void worker(int cpu, genptr_t arg);
  51. /***** variables shared with worker() ******/
  52. extern struct application ap;
  53. extern int hypersample; /* number of extra rays to fire */
  54. extern fastf_t aspect; /* view aspect ratio X/Y */
  55. extern fastf_t cell_width; /* model space grid cell width */
  56. extern fastf_t cell_height; /* model space grid cell height */
  57. extern point_t eye_model; /* model-space location of eye */
  58. extern fastf_t eye_backoff; /* dist of eye from center */
  59. extern fastf_t rt_perspective; /* persp (degrees X) 0 => ortho */
  60. extern int width; /* # of pixels in X */
  61. extern int height; /* # of lines in Y */
  62. extern mat_t Viewrotscale; /* view orientation quaternion */
  63. extern fastf_t viewsize;
  64. extern int incr_mode; /* !0 for incremental resolution */
  65. extern int incr_level; /* current incremental level */
  66. extern int incr_nlevel; /* number of levels */
  67. extern int npsw;
  68. extern struct resource resource[];
  69. /***** end variables shared with worker() */
  70. /***** variables shared with rt.c *****/
  71. extern char *string_pix_start; /* string spec of starting pixel */
  72. extern char *string_pix_end; /* string spec of ending pixel */
  73. extern int pix_start; /* pixel to start at */
  74. extern int pix_end; /* pixel to end at */
  75. extern int nobjs; /* Number of cmd-line treetops */
  76. extern char **objtab; /* array of treetop strings */
  77. extern int matflag; /* read matrix from stdin */
  78. extern int desiredframe; /* frame to start at */
  79. extern int finalframe; /* frame to halt at */
  80. extern int curframe; /* current frame number */
  81. extern char *outputfile; /* name of base of output file */
  82. extern int interactive; /* human is watching results */
  83. extern int save_overlaps; /* flag for setting rti_save_overlaps */
  84. /***** end variables shared with rt.c *****/
  85. /***** variables shared with viewg3.c *****/
  86. struct bu_vls ray_data_file; /* file name for ray data output */
  87. /***** end variables shared with viewg3.c *****/
  88. /***** variables for frame buffer black pixel rendering *****/
  89. unsigned char *pixmap = NULL; /* Pixel Map for rerendering of black pixels */
  90. void def_tree(register struct rt_i *rtip);
  91. void do_ae(double azim, double elev);
  92. void res_pr(void);
  93. void memory_summary(void);
  94. /*
  95. * O L D _ F R A M E
  96. *
  97. * Acquire particulars about a frame, in the old format.
  98. * Returns -1 if unable to acquire info, 0 if successful.
  99. */
  100. int
  101. old_frame(FILE *fp)
  102. {
  103. register int i;
  104. char number[128];
  105. /* Visible part is from -1 to +1 in view space */
  106. if ( fscanf( fp, "%128s", number ) != 1 ) return(-1);
  107. viewsize = atof(number);
  108. if ( fscanf( fp, "%128s", number ) != 1 ) return(-1);
  109. eye_model[X] = atof(number);
  110. if ( fscanf( fp, "%128s", number ) != 1 ) return(-1);
  111. eye_model[Y] = atof(number);
  112. if ( fscanf( fp, "%128s", number ) != 1 ) return(-1);
  113. eye_model[Z] = atof(number);
  114. for ( i=0; i < 16; i++ ) {
  115. if ( fscanf( fp, "%128s", number ) != 1 )
  116. return(-1);
  117. Viewrotscale[i] = atof(number);
  118. }
  119. return(0); /* OK */
  120. }
  121. /*
  122. * O L D _ W A Y
  123. *
  124. * Determine if input file is old or new format, and if
  125. * old format, handle process * Returns 0 if new way, 1 if old way (and all done).
  126. * Note that the rewind() will fail on ttys, pipes, and sockets (sigh).
  127. */
  128. int
  129. old_way(FILE *fp)
  130. {
  131. int c;
  132. viewsize = -42.0;
  133. /* Sneek a peek at the first character, and then put it back */
  134. if ( (c = fgetc( fp )) == EOF ) {
  135. /* Claim old way, all (ie, nothing) done */
  136. return(1);
  137. }
  138. if ( ungetc( c, fp ) != c )
  139. bu_exit(EXIT_FAILURE, "do.c:old_way() ungetc failure\n");
  140. /*
  141. * Old format files start immediately with a %.9e format,
  142. * so the very first character should be a digit or '-'.
  143. */
  144. if ( (c < '0' || c > '9') && c != '-' ) {
  145. return( 0 ); /* Not old way */
  146. }
  147. if ( old_frame( fp ) < 0 || viewsize <= 0.0 ) {
  148. rewind( fp );
  149. return(0); /* Not old way */
  150. }
  151. bu_log("Interpreting command stream in old format\n");
  152. def_tree( ap.a_rt_i ); /* Load the default trees */
  153. curframe = 0;
  154. do {
  155. if ( finalframe >= 0 && curframe > finalframe )
  156. return(1);
  157. if ( curframe >= desiredframe )
  158. do_frame( curframe );
  159. curframe++;
  160. } while ( old_frame( fp ) >= 0 && viewsize > 0.0 );
  161. return(1); /* old way, all done */
  162. }
  163. /*
  164. * C M _ S T A R T
  165. *
  166. * Process "start" command in new format input stream
  167. */
  168. int cm_start( int argc, char **argv)
  169. {
  170. char *buf = (char *)NULL;
  171. int frame;
  172. frame = atoi(argv[1]);
  173. if ( finalframe >= 0 && frame > finalframe )
  174. return(-1); /* Indicate EOF -- user declared a halt */
  175. if ( frame >= desiredframe ) {
  176. curframe = frame;
  177. return(0);
  178. }
  179. /* Skip over unwanted frames -- find next frame start */
  180. while ( (buf = rt_read_cmd( stdin )) != (char *)0 ) {
  181. register char *cp;
  182. cp = buf;
  183. while ( *cp && isspace(*cp) ) cp++; /* skip spaces */
  184. if ( strncmp( cp, "start", 5 ) != 0 ) continue;
  185. while ( *cp && !isspace(*cp) ) cp++; /* skip keyword */
  186. while ( *cp && isspace(*cp) ) cp++; /* skip spaces */
  187. frame = atoi(cp);
  188. bu_free( buf, "rt_read_cmd command buffer (skipping frames)" );
  189. buf = (char *)0;
  190. if ( finalframe >= 0 && frame > finalframe )
  191. return(-1); /* "EOF" */
  192. if ( frame >= desiredframe ) {
  193. curframe = frame;
  194. return(0);
  195. }
  196. }
  197. return(-1); /* EOF */
  198. }
  199. int cm_vsize( int argc, char **argv)
  200. {
  201. viewsize = atof( argv[1] );
  202. return(0);
  203. }
  204. int cm_eyept(int argc, char **argv)
  205. {
  206. register int i;
  207. for ( i=0; i<3; i++ )
  208. eye_model[i] = atof( argv[i+1] );
  209. return(0);
  210. }
  211. int cm_lookat_pt(int argc, char **argv)
  212. {
  213. point_t pt;
  214. vect_t dir;
  215. int yflip = 0;
  216. quat_t quat;
  217. if ( argc < 4 )
  218. return(-1);
  219. pt[X] = atof(argv[1]);
  220. pt[Y] = atof(argv[2]);
  221. pt[Z] = atof(argv[3]);
  222. if ( argc > 4 )
  223. yflip = atoi(argv[4]);
  224. /*
  225. * eye_pt should have been specified before here and
  226. * different from the lookat point or the lookat point will
  227. * be from the "front"
  228. */
  229. if (VAPPROXEQUAL(pt, eye_model, VDIVIDE_TOL)) {
  230. VSETALLN(quat, 0.5, 4);
  231. quat_quat2mat(Viewrotscale, quat); /* front */
  232. } else {
  233. VSUB2( dir, pt, eye_model );
  234. VUNITIZE( dir );
  235. bn_mat_lookat( Viewrotscale, dir, yflip );
  236. }
  237. return(0);
  238. }
  239. int cm_vrot( int argc, char **argv)
  240. {
  241. register int i;
  242. for ( i=0; i<16; i++ )
  243. Viewrotscale[i] = atof( argv[i+1] );
  244. return(0);
  245. }
  246. int cm_orientation(int argc, char **argv)
  247. {
  248. register int i;
  249. quat_t quat;
  250. for ( i=0; i<4; i++ )
  251. quat[i] = atof( argv[i+1] );
  252. quat_quat2mat( Viewrotscale, quat );
  253. return(0);
  254. }
  255. int cm_end(int argc, char **argv)
  256. {
  257. struct rt_i *rtip = ap.a_rt_i;
  258. if ( rtip && BU_LIST_IS_EMPTY( &rtip->HeadRegion ) ) {
  259. def_tree( rtip ); /* Load the default trees */
  260. }
  261. /* If no matrix or az/el specified yet, use params from cmd line */
  262. if ( Viewrotscale[15] <= 0.0 )
  263. do_ae( azimuth, elevation );
  264. if ( do_frame( curframe ) < 0 ) return(-1);
  265. return(0);
  266. }
  267. int cm_tree( int argc, const char **argv)
  268. {
  269. register struct rt_i *rtip = ap.a_rt_i;
  270. struct bu_vls times;
  271. if ( argc <= 1 ) {
  272. def_tree( rtip ); /* Load the default trees */
  273. return(0);
  274. }
  275. bu_vls_init( &times );
  276. rt_prep_timer();
  277. if ( rt_gettrees(rtip, argc-1, &argv[1], npsw) < 0 )
  278. bu_log("rt_gettrees(%s) FAILED\n", argv[0]);
  279. (void)rt_get_timer( &times, NULL );
  280. if (rt_verbosity & VERBOSE_STATS)
  281. bu_log("GETTREE: %s\n", bu_vls_addr(&times) );
  282. bu_vls_free( &times );
  283. return(0);
  284. }
  285. int cm_multiview( int argc, char **argv)
  286. {
  287. register struct rt_i *rtip = ap.a_rt_i;
  288. int i;
  289. static int a[] = {
  290. 35, 0,
  291. 0, 90, 135, 180, 225, 270, 315,
  292. 0, 90, 135, 180, 225, 270, 315
  293. };
  294. static int e[] = {
  295. 25, 90,
  296. 30, 30, 30, 30, 30, 30, 30,
  297. 60, 60, 60, 60, 60, 60, 60
  298. };
  299. if ( rtip && BU_LIST_IS_EMPTY( &rtip->HeadRegion ) ) {
  300. def_tree( rtip ); /* Load the default trees */
  301. }
  302. for ( i=0; i<(sizeof(a)/sizeof(a[0])); i++ ) {
  303. do_ae( (double)a[i], (double)e[i] );
  304. (void)do_frame( curframe++ );
  305. }
  306. return(-1); /* end RT by returning an error */
  307. }
  308. /*
  309. * C M _ A N I M
  310. *
  311. * Experimental animation code
  312. *
  313. * Usage: anim <path> <type> args
  314. */
  315. int cm_anim(int argc, const char **argv)
  316. {
  317. if ( db_parse_anim( ap.a_rt_i->rti_dbip, argc, argv ) < 0 ) {
  318. bu_log("cm_anim: %s %s failed\n", argv[1], argv[2]);
  319. return(-1); /* BAD */
  320. }
  321. return(0);
  322. }
  323. /*
  324. * C M _ C L E A N
  325. *
  326. * Clean out results of last rt_prep(), and start anew.
  327. */
  328. int cm_clean(int argc, char **argv)
  329. {
  330. /* Allow lighting model to clean up (e.g. lights, materials, etc) */
  331. view_cleanup( ap.a_rt_i );
  332. rt_clean( ap.a_rt_i );
  333. if (R_DEBUG&RDEBUG_RTMEM_END)
  334. bu_prmem( "After cm_clean" );
  335. return(0);
  336. }
  337. /*
  338. * C M _ C L O S E D B
  339. *
  340. * To be invoked after a "clean" command, to close out the ".g" database.
  341. * Intended for memory debugging, to help chase down memory "leaks".
  342. * This terminates the program, as there is no longer a database.
  343. */
  344. int cm_closedb(int argc, char **argv)
  345. {
  346. db_close( ap.a_rt_i->rti_dbip );
  347. ap.a_rt_i->rti_dbip = DBI_NULL;
  348. bu_free( (genptr_t)ap.a_rt_i, "struct rt_i" );
  349. ap.a_rt_i = RTI_NULL;
  350. bu_prmem( "After _closedb" );
  351. bu_exit(0, NULL);
  352. return( 1 ); /* for compiler */
  353. }
  354. /* viewing module specific variables */
  355. extern struct bu_structparse view_parse[];
  356. struct bu_structparse set_parse[] = {
  357. #if !defined(__alpha) /* XXX Alpha does not support this initialization! */
  358. {"%d", 1, "width", bu_byteoffset(width), BU_STRUCTPARSE_FUNC_NULL },
  359. {"%d", 1, "height", bu_byteoffset(height), BU_STRUCTPARSE_FUNC_NULL },
  360. {"%d", 1, "save_overlaps", bu_byteoffset(save_overlaps), BU_STRUCTPARSE_FUNC_NULL },
  361. {"%f", 1, "perspective", bu_byteoffset(rt_perspective), BU_STRUCTPARSE_FUNC_NULL },
  362. {"%f", 1, "angle", bu_byteoffset(rt_perspective), BU_STRUCTPARSE_FUNC_NULL },
  363. #if !defined(_WIN32) || defined(__CYGWIN__)
  364. {"%d", 1, "rt_bot_minpieces", bu_byteoffset(rt_bot_minpieces), BU_STRUCTPARSE_FUNC_NULL },
  365. {"%d", 1, "rt_bot_tri_per_piece", bu_byteoffset(rt_bot_tri_per_piece), BU_STRUCTPARSE_FUNC_NULL },
  366. {"%f", 1, "rt_cline_radius", bu_byteoffset(rt_cline_radius), BU_STRUCTPARSE_FUNC_NULL },
  367. #endif
  368. {"%V", 1, "ray_data_file", bu_byteoffset(ray_data_file), BU_STRUCTPARSE_FUNC_NULL },
  369. {"i", bu_byteoffset(view_parse[0]), "View_Module-Specific Parameters", 0, BU_STRUCTPARSE_FUNC_NULL },
  370. #endif
  371. {"", 0, (char *)0, 0, BU_STRUCTPARSE_FUNC_NULL }
  372. };
  373. /*
  374. * C M _ S E T
  375. *
  376. * Allow variable values to be set or examined.
  377. */
  378. int cm_set(int argc, char **argv)
  379. {
  380. struct bu_vls str;
  381. if ( argc <= 1 ) {
  382. bu_struct_print( "Generic and Application-Specific Parameter Values",
  383. set_parse, (char *)0 );
  384. return(0);
  385. }
  386. bu_vls_init( &str );
  387. bu_vls_from_argv( &str, argc-1, (const char **)argv+1 );
  388. if ( bu_struct_parse( &str, set_parse, (char *)0 ) < 0 ) {
  389. bu_vls_free( &str );
  390. return(-1);
  391. }
  392. bu_vls_free( &str );
  393. return(0);
  394. }
  395. /*
  396. * C M _ A E
  397. */
  398. int cm_ae( int argc, char **argv)
  399. {
  400. azimuth = atof(argv[1]); /* set elevation and azimuth */
  401. elevation = atof(argv[2]);
  402. do_ae(azimuth, elevation);
  403. return(0);
  404. }
  405. /*
  406. * C M _ O P T
  407. */
  408. int cm_opt(int argc, char **argv)
  409. {
  410. int old_bu_optind=bu_optind; /* need to restore this value after calling get_args() */
  411. if ( get_args( argc, argv ) <= 0 ) {
  412. bu_optind = old_bu_optind;
  413. return(-1);
  414. }
  415. bu_optind = old_bu_optind;
  416. return(0);
  417. }
  418. /*
  419. * D E F _ T R E E
  420. *
  421. * Load default tree list, from command line.
  422. */
  423. void
  424. def_tree(register struct rt_i *rtip)
  425. {
  426. struct bu_vls times;
  427. RT_CK_RTI(rtip);
  428. bu_vls_init( &times );
  429. rt_prep_timer();
  430. if ( rt_gettrees(rtip, nobjs, (const char **)objtab, npsw) < 0 )
  431. bu_log("rt_gettrees(%s) FAILED\n", objtab[0]);
  432. (void)rt_get_timer( &times, NULL );
  433. if (rt_verbosity & VERBOSE_STATS)
  434. bu_log("GETTREE: %s\n", bu_vls_addr(&times));
  435. bu_vls_free( &times );
  436. memory_summary();
  437. }
  438. /*
  439. * D O _ P R E P
  440. *
  441. * This is a separate function primarily as a service to REMRT.
  442. */
  443. void
  444. do_prep(struct rt_i *rtip)
  445. {
  446. struct bu_vls times;
  447. RT_CHECK_RTI(rtip);
  448. if ( rtip->needprep ) {
  449. /* Allow lighting model to set up (e.g. lights, materials, etc) */
  450. view_setup(rtip);
  451. /* Allow RT library to prepare itself */
  452. bu_vls_init( &times );
  453. rt_prep_timer();
  454. rt_prep_parallel(rtip, npsw);
  455. (void)rt_get_timer( &times, NULL );
  456. if (rt_verbosity & VERBOSE_STATS)
  457. bu_log( "PREP: %s\n", bu_vls_addr(&times) );
  458. bu_vls_free( &times );
  459. }
  460. memory_summary();
  461. if (rt_verbosity & VERBOSE_STATS) {
  462. bu_log("%s: %d nu, %d cut, %d box (%d empty)\n",
  463. rtip->rti_space_partition == RT_PART_NUGRID ?
  464. "NUGrid" : "NUBSP",
  465. rtip->rti_ncut_by_type[CUT_NUGRIDNODE],
  466. rtip->rti_ncut_by_type[CUT_CUTNODE],
  467. rtip->rti_ncut_by_type[CUT_BOXNODE],
  468. rtip->nempty_cells );
  469. #if 0
  470. rt_pr_cut_info( rtip, "main" );
  471. #endif
  472. }
  473. }
  474. /*
  475. * D O _ F R A M E
  476. *
  477. * Do all the actual work to run a frame.
  478. *
  479. * Returns -1 on error, 0 if OK.
  480. */
  481. int
  482. do_frame(int framenumber)
  483. {
  484. struct bu_vls times;
  485. char framename[128] = {0}; /* File name to hold current frame */
  486. struct rt_i *rtip = ap.a_rt_i;
  487. double utime = 0.0; /* CPU time used */
  488. double nutime = 0.0; /* CPU time used, normalized by ncpu */
  489. double wallclock; /* # seconds of wall clock time */
  490. int npix, i; /* # of pixel values to be done */
  491. int lim;
  492. vect_t work, temp;
  493. quat_t quat;
  494. if (rt_verbosity & VERBOSE_FRAMENUMBER)
  495. bu_log( "\n...................Frame %5d...................\n",
  496. framenumber);
  497. /* Compute model RPP, etc */
  498. do_prep( rtip );
  499. if (rt_verbosity & VERBOSE_VIEWDETAIL)
  500. bu_log("Tree: %d solids in %d regions\n",
  501. rtip->nsolids, rtip->nregions );
  502. if (Query_one_pixel) {
  503. query_rdebug = R_DEBUG;
  504. query_debug = RT_G_DEBUG;
  505. rt_g.debug = rdebug = 0;
  506. }
  507. if ( rtip->nsolids <= 0 )
  508. bu_exit(3, "rt ERROR: No solids\n");
  509. if (rt_verbosity & VERBOSE_VIEWDETAIL)
  510. bu_log("Model: X(%g,%g), Y(%g,%g), Z(%g,%g)\n",
  511. rtip->mdl_min[X], rtip->mdl_max[X],
  512. rtip->mdl_min[Y], rtip->mdl_max[Y],
  513. rtip->mdl_min[Z], rtip->mdl_max[Z] );
  514. /*
  515. * Perform Grid setup.
  516. * This may alter cell size or width/height.
  517. */
  518. grid_setup();
  519. /* az/el 0, 0 is when screen +Z is model +X */
  520. VSET( work, 0, 0, 1 );
  521. MAT3X3VEC( temp, view2model, work );
  522. bn_ae_vec( &azimuth, &elevation, temp );
  523. if (rt_verbosity & VERBOSE_VIEWDETAIL)
  524. bu_log(
  525. "View: %g azimuth, %g elevation off of front view\n",
  526. azimuth, elevation);
  527. quat_mat2quat( quat, model2view );
  528. if (rt_verbosity & VERBOSE_VIEWDETAIL) {
  529. bu_log("Orientation: %g, %g, %g, %g\n", V4ARGS(quat) );
  530. bu_log("Eye_pos: %g, %g, %g\n", V3ARGS(eye_model) );
  531. bu_log("Size: %gmm\n", viewsize);
  532. #if 0
  533. /*
  534. * This code shows how the model2view matrix can be reconstructed
  535. * using the information from the Orientation, Eye_pos, and Size
  536. * messages.
  537. */
  538. {
  539. mat_t rotscale, xlate;
  540. mat_t new;
  541. quat_t newquat;
  542. bn_mat_print("model2view", model2view);
  543. quat_quat2mat( rotscale, quat );
  544. rotscale[15] = 0.5 * viewsize;
  545. MAT_IDN( xlate );
  546. MAT_DELTAS_VEC_NEG( xlate, eye_model);
  547. bn_mat_mul( new, rotscale, xlate );
  548. bn_mat_print("reconstructed m2v", new);
  549. quat_mat2quat( newquat, new );
  550. HPRINT( "reconstructed orientation:", newquat );
  551. }
  552. #endif
  553. bu_log("Grid: (%g, %g) mm, (%d, %d) pixels\n",
  554. cell_width, cell_height,
  555. width, height );
  556. bu_log("Beam: radius=%g mm, divergence=%g mm/1mm\n",
  557. ap.a_rbeam, ap.a_diverge );
  558. }
  559. /* Process -b and ??? options now, for this frame */
  560. if ( pix_start == -1 ) {
  561. pix_start = 0;
  562. pix_end = height * width - 1;
  563. }
  564. if ( string_pix_start ) {
  565. int xx, yy;
  566. register char *cp = string_pix_start;
  567. xx = atoi(cp);
  568. while ( *cp >= '0' && *cp <= '9' ) cp++;
  569. while ( *cp && (*cp < '0' || *cp > '9') ) cp++;
  570. yy = atoi(cp);
  571. bu_log("only pixel %d %d\n", xx, yy);
  572. if ( xx * yy >= 0 ) {
  573. pix_start = yy * width + xx;
  574. pix_end = pix_start;
  575. }
  576. }
  577. if ( string_pix_end ) {
  578. int xx, yy;
  579. register char *cp = string_pix_end;
  580. xx = atoi(cp);
  581. while ( *cp >= '0' && *cp <= '9' ) cp++;
  582. while ( *cp && (*cp < '0' || *cp > '9') ) cp++;
  583. yy = atoi(cp);
  584. bu_log("ending pixel %d %d\n", xx, yy);
  585. if ( xx * yy >= 0 ) {
  586. pix_end = yy * width + xx;
  587. }
  588. }
  589. /*
  590. * After the parameters for this calculation have been established,
  591. * deal with CPU limits and priorities, where appropriate.
  592. * Because limits exist, they better be adequate.
  593. * We assume that the Cray can produce MINRATE pixels/sec
  594. * on images with extreme amounts of glass & mirrors.
  595. */
  596. #define MINRATE 65
  597. npix = width*height*(hypersample+1);
  598. if ( (lim = bu_cpulimit_get()) > 0 ) {
  599. bu_cpulimit_set( lim + npix / MINRATE + 100 );
  600. }
  601. /* Allocate data for pixel map for rerendering of black pixels */
  602. if (pixmap == NULL) {
  603. pixmap = (unsigned char*)bu_calloc(sizeof(RGBpixel), width*height, "pixmap allocate");
  604. }
  605. /*
  606. * If this image is unlikely to be for debugging,
  607. * be gentle to the machine.
  608. */
  609. if ( !interactive ) {
  610. if ( npix > 256*256 )
  611. bu_nice_set(10);
  612. else if ( npix > 512*512 )
  613. bu_nice_set(14);
  614. }
  615. /*
  616. * Determine output file name
  617. * On UNIX only, check to see if this is a "restart".
  618. */
  619. if ( outputfile != (char *)0 ) {
  620. if ( framenumber <= 0 ) {
  621. snprintf( framename, 128, "%s", outputfile );
  622. } else {
  623. snprintf( framename, 128, "%s.%d", outputfile, framenumber );
  624. }
  625. #ifdef HAVE_SYS_STAT_H
  626. /*
  627. * This code allows the computation of a particular frame
  628. * to a disk file to be resumed automatically.
  629. * This is worthwhile crash protection.
  630. * This use of stat() and fseek() is UNIX-specific.
  631. *
  632. * It is not appropriate for the RT "top part" to assume
  633. * anything about the data that the view module will be
  634. * storing. Therefore, it is the responsibility of
  635. * view_2init() to also detect that some existing data
  636. * is in the file, and take appropriate measures
  637. * (like reading it in).
  638. * view_2init() can depend on the file being open for both
  639. * reading and writing, but must do it's own positioning.
  640. */
  641. {
  642. struct stat sb;
  643. if ( stat( framename, &sb ) >= 0 &&
  644. sb.st_size > 0 &&
  645. sb.st_size < width*height*sizeof(RGBpixel)) {
  646. /* File exists, with partial results */
  647. register int fd;
  648. if ( (fd = open( framename, 2 )) < 0 ||
  649. (outfp = fdopen( fd, "r+" )) == NULL ) {
  650. perror( framename );
  651. if ( matflag ) return(0); /* OK */
  652. return(-1); /* Bad */
  653. }
  654. /* Read existing pix data into the frame buffer */
  655. if (sb.st_size > 0) {
  656. (void)fread(pixmap, 1, (size_t)sb.st_size, outfp);
  657. }
  658. }
  659. }
  660. #endif
  661. /* Ordinary case for creating output file */
  662. if ( outfp == NULL && (outfp = fopen( framename, "w+b" )) == NULL )
  663. {
  664. perror( framename );
  665. if ( matflag ) return(0); /* OK */
  666. return(-1); /* Bad */
  667. }
  668. if (rt_verbosity & VERBOSE_OUTPUTFILE)
  669. bu_log("Output file is '%s' %dx%d pixels\n",
  670. framename, width, height);
  671. }
  672. /* initialize lighting, may update pix_start */
  673. view_2init( &ap, framename );
  674. /* Just while doing the ray-tracing */
  675. if (R_DEBUG&RDEBUG_RTMEM)
  676. bu_debug |= (BU_DEBUG_MEM_CHECK|BU_DEBUG_MEM_LOG);
  677. rtip->nshots = 0;
  678. rtip->nmiss_model = 0;
  679. rtip->nmiss_tree = 0;
  680. rtip->nmiss_solid = 0;
  681. rtip->nmiss = 0;
  682. rtip->nhits = 0;
  683. rtip->rti_nrays = 0;
  684. if (rt_verbosity & (VERBOSE_LIGHTINFO|VERBOSE_STATS))
  685. bu_log("\n");
  686. fflush(stdout);
  687. fflush(stderr);
  688. /*
  689. * Compute the image
  690. * It may prove desirable to do this in chunks
  691. */
  692. rt_prep_timer();
  693. if ( incr_mode ) {
  694. for ( incr_level = 1; incr_level <= incr_nlevel; incr_level++ ) {
  695. if ( incr_level > 1 )
  696. view_2init( &ap, framename );
  697. do_run( 0, (1<<incr_level)*(1<<incr_level)-1 );
  698. }
  699. } else {
  700. do_run( pix_start, pix_end );
  701. /* Reset values to full size, for next frame (if any) */
  702. pix_start = 0;
  703. pix_end = height*width - 1;
  704. }
  705. bu_vls_init( &times );
  706. utime = rt_get_timer( &times, &wallclock );
  707. /*
  708. * End of application. Done outside of timing section.
  709. * Typically, writes any remaining results out.
  710. */
  711. view_end( &ap );
  712. /* Stop memory debug printing until next frame, leave full checking on */
  713. if (R_DEBUG&RDEBUG_RTMEM)
  714. bu_debug &= ~BU_DEBUG_MEM_LOG;
  715. /*
  716. * Certain parallel systems (eg, Alliant) count the entire
  717. * multi-processor complex as one computer, and charge only once.
  718. * This matches the desired behavior here.
  719. * Other vendors (eg, SGI) count each processor separately,
  720. * and charge for all of them. These results need to be normalized.
  721. * Otherwise, all we would know is that a given workload takes about
  722. * the same amount of CPU time, regardless of the number of CPUs.
  723. */
  724. #if !defined(alliant)
  725. if ( npsw > 1 ) {
  726. int avail_cpus;
  727. int ncpus;
  728. avail_cpus = bu_avail_cpus();
  729. if ( npsw > avail_cpus ) {
  730. ncpus = avail_cpus;
  731. } else {
  732. ncpus = npsw;
  733. }
  734. nutime = utime / ncpus; /* compensate */
  735. } else
  736. #endif
  737. nutime = utime;
  738. /* prevent a bogus near-zero time to prevent infinate and near-infinate
  739. * results without relying on IEEE floating point zero comparison.
  740. */
  741. if (NEAR_ZERO(nutime, VDIVIDE_TOL)) {
  742. bu_log("WARNING: Raytrace timings are likely to be meaningless\n");
  743. nutime = VDIVIDE_TOL;
  744. }
  745. /*
  746. * All done. Display run statistics.
  747. */
  748. if (rt_verbosity & VERBOSE_STATS)
  749. bu_log("SHOT: %s\n", bu_vls_addr( &times ) );
  750. bu_vls_free( &times );
  751. memory_summary();
  752. if (rt_verbosity & VERBOSE_STATS) {
  753. bu_log("%ld solid/ray intersections: %ld hits + %ld miss\n",
  754. rtip->nshots, rtip->nhits, rtip->nmiss );
  755. bu_log("pruned %.1f%%: %ld model RPP, %ld dups skipped, %ld solid RPP\n",
  756. rtip->nshots>0?((double)rtip->nhits*100.0)/rtip->nshots:100.0,
  757. rtip->nmiss_model, rtip->ndup, rtip->nmiss_solid );
  758. bu_log("Frame %2d: %10d pixels in %9.2f sec = %12.2f pixels/sec\n",
  759. framenumber,
  760. width*height, nutime, ((double)(width*height))/nutime );
  761. bu_log("Frame %2d: %10d rays in %9.2f sec = %12.2f rays/sec (RTFM)\n",
  762. framenumber,
  763. rtip->rti_nrays, nutime, ((double)(rtip->rti_nrays))/nutime );
  764. bu_log("Frame %2d: %10d rays in %9.2f sec = %12.2f rays/CPU_sec\n",
  765. framenumber,
  766. rtip->rti_nrays, utime, ((double)(rtip->rti_nrays))/utime );
  767. bu_log("Frame %2d: %10d rays in %9.2f sec = %12.2f rays/sec (wallclock)\n",
  768. framenumber,
  769. rtip->rti_nrays,
  770. wallclock, ((double)(rtip->rti_nrays))/wallclock );
  771. }
  772. if ( outfp != NULL ) {
  773. /* Protect finished product */
  774. if ( outputfile != (char *)0 )
  775. (void)bu_fchmod(outfp, 0444);
  776. (void)fclose(outfp);
  777. outfp = NULL;
  778. }
  779. if (R_DEBUG&RDEBUG_STATS) {
  780. /* Print additional statistics */
  781. res_pr();
  782. }
  783. bu_log("\n");
  784. bu_free(pixmap, "pixmap allocate");
  785. pixmap = (unsigned char *)NULL;
  786. return(0); /* OK */
  787. }
  788. /*
  789. * D O _ A E
  790. *
  791. * Compute the rotation specified by the azimuth and elevation
  792. * parameters. First, note that these are specified relative
  793. * to the GIFT "front view", ie, model (X, Y, Z) is view (Z, X, Y):
  794. * looking down X axis, Y right, Z up.
  795. * A positive azimuth represents rotating the *eye* around the
  796. * Y axis, or, rotating the *model* in -Y.
  797. * A positive elevation represents rotating the *eye* around the
  798. * X axis, or, rotating the *model* in -X.
  799. */
  800. void
  801. do_ae(double azim, double elev)
  802. {
  803. vect_t temp;
  804. vect_t diag;
  805. mat_t toEye;
  806. struct rt_i *rtip = ap.a_rt_i;
  807. if ( rtip->nsolids <= 0 )
  808. bu_exit(EXIT_FAILURE, "do_ae: no solids active\n");
  809. if ( rtip->nregions <= 0 )
  810. bu_exit(EXIT_FAILURE, "do_ae: no regions active\n");
  811. if ( rtip->mdl_max[X] >= INFINITY ) {
  812. bu_log("do_ae: infinite model bounds? setting a unit minimum\n");
  813. VSETALL( rtip->mdl_min, -1 );
  814. }
  815. if ( rtip->mdl_max[X] <= -INFINITY ) {
  816. bu_log("do_ae: infinite model bounds? setting a unit maximum\n");
  817. VSETALL( rtip->mdl_max, 1 );
  818. }
  819. /*
  820. * Enlarge the model RPP just slightly, to avoid nasty
  821. * effects with a solid's face being exactly on the edge
  822. * NOTE: This code is duplicated out of librt/tree.c/rt_prep(),
  823. * and has to appear here to enable the viewsize calculation to
  824. * match the final RPP.
  825. */
  826. rtip->mdl_min[X] = floor( rtip->mdl_min[X] );
  827. rtip->mdl_min[Y] = floor( rtip->mdl_min[Y] );
  828. rtip->mdl_min[Z] = floor( rtip->mdl_min[Z] );
  829. rtip->mdl_max[X] = ceil( rtip->mdl_max[X] );
  830. rtip->mdl_max[Y] = ceil( rtip->mdl_max[Y] );
  831. rtip->mdl_max[Z] = ceil( rtip->mdl_max[Z] );
  832. MAT_IDN( Viewrotscale );
  833. bn_mat_angles( Viewrotscale, 270.0+elev, 0.0, 270.0-azim );
  834. /* Look at the center of the model */
  835. MAT_IDN( toEye );
  836. toEye[MDX] = -((rtip->mdl_max[X]+rtip->mdl_min[X])/2.0);
  837. toEye[MDY] = -((rtip->mdl_max[Y]+rtip->mdl_min[Y])/2.0);
  838. toEye[MDZ] = -((rtip->mdl_max[Z]+rtip->mdl_min[Z])/2.0);
  839. /* Fit a sphere to the model RPP, diameter is viewsize,
  840. * unless viewsize command used to override.
  841. */
  842. if ( viewsize <= 0 ) {
  843. VSUB2( diag, rtip->mdl_max, rtip->mdl_min );
  844. viewsize = MAGNITUDE( diag );
  845. if ( aspect > 1 ) {
  846. /* don't clip any of the image when autoscaling */
  847. viewsize *= aspect;
  848. }
  849. }
  850. Viewrotscale[15] = 0.5*viewsize; /* Viewscale */
  851. bn_mat_mul( model2view, Viewrotscale, toEye );
  852. bn_mat_inv( view2model, model2view );
  853. VSET( temp, 0, 0, eye_backoff );
  854. MAT4X3PNT( eye_model, view2model, temp );
  855. }
  856. /*
  857. * R E S _ P R
  858. */
  859. void
  860. res_pr(void)
  861. {
  862. register struct resource *res;
  863. register int i;
  864. fprintf(stderr, "\nResource use summary, by processor:\n");
  865. res = &resource[0];
  866. for ( i=0; i<npsw; i++, res++ ) {
  867. fprintf(stderr, "---CPU %d:\n", i);
  868. if ( res->re_magic != RESOURCE_MAGIC ) {
  869. fprintf(stderr, "Bad magic number!!\n");
  870. continue;
  871. }
  872. fprintf(stderr, "seg len=%10ld get=%10ld free=%10ld\n",
  873. res->re_seglen, res->re_segget, res->re_segfree );
  874. fprintf(stderr, "partition len=%10ld get=%10ld free=%10ld\n",
  875. res->re_partlen, res->re_partget, res->re_partfree );
  876. #if 0
  877. fprintf(stderr, "bitv_elem len=%10ld get=%10ld free=%10ld\n",
  878. res->re_bitvlen, res->re_bitvget, res->re_bitvfree );
  879. #endif
  880. fprintf(stderr, "boolstack len=%10ld\n",
  881. res->re_boolslen);
  882. }
  883. }
  884. /*
  885. * Command table for RT control script language
  886. */
  887. struct command_tab rt_cmdtab[] = {
  888. {"start", "frame number", "start a new frame",
  889. cm_start, 2, 2},
  890. {"viewsize", "size in mm", "set view size",
  891. cm_vsize, 2, 2},
  892. {"eye_pt", "xyz of eye", "set eye point",
  893. cm_eyept, 4, 4},
  894. {"lookat_pt", "x y z [yflip]", "set eye look direction, in X-Y plane",
  895. cm_lookat_pt, 4, 5},
  896. {"viewrot", "4x4 matrix", "set view direction from matrix",
  897. cm_vrot, 17, 17},
  898. {"orientation", "quaturnion", "set view direction from quaturnion",
  899. cm_orientation, 5, 5},
  900. {"end", "", "end of frame setup, begin raytrace",
  901. cm_end, 1, 1},
  902. {"multiview", "", "produce stock set of views",
  903. cm_multiview, 1, 1},
  904. {"anim", "path type args", "specify articulation animation",
  905. cm_anim, 4, 999},
  906. {"tree", "treetop(s)", "specify alternate list of tree tops",
  907. cm_tree, 1, 999},
  908. {"clean", "", "clean articulation from previous frame",
  909. cm_clean, 1, 1},
  910. {"_closedb", "", "Close .g database, (for memory debugging)",
  911. cm_closedb, 1, 1},
  912. {"set", "", "show or set parameters",
  913. cm_set, 1, 999},
  914. {"ae", "azim elev", "specify view as azim and elev, in degrees",
  915. cm_ae, 3, 3},
  916. {"opt", "-flags", "set flags, like on command line",
  917. cm_opt, 2, 999},
  918. {(char *)0, (char *)0, (char *)0,
  919. 0, 0, 0 /* END */}
  920. };
  921. /*
  922. * Local Variables:
  923. * mode: C
  924. * tab-width: 8
  925. * indent-tabs-mode: t
  926. * c-file-style: "stroustrup"
  927. * End:
  928. * ex: shiftwidth=4 tabstop=8
  929. */