PageRenderTime 31ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/brlcad/tags/rel-7-16-10/src/rt/do.c

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