BRL-CAD
prep.c
Go to the documentation of this file.
1 /* P R E P . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1990-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library 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 library 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 /** @addtogroup ray */
21 /** @{ */
22 /** @file librt/prep.c
23  *
24  * Manage one-time preparations to be done before actual ray-tracing
25  * can commence.
26  *
27  */
28 
29 #include "common.h"
30 
31 #include <stdlib.h>
32 #include <stddef.h>
33 #include <math.h>
34 #include <string.h>
35 #include "bio.h"
36 
37 
38 #include "bu/parallel.h"
39 #include "vmath.h"
40 #include "bn.h"
41 #include "raytrace.h"
42 #include "plot3.h"
43 
44 
45 extern void rt_ck(struct rt_i *rtip);
46 
47 HIDDEN void rt_solid_bitfinder(register union tree *treep, struct region *regp, struct resource *resp);
48 
49 
50 /* XXX Need rt_init_rtg(), rt_clean_rtg() */
51 
52 /**
53  * Given a db_i database instance, create an rt_i instance. If caller
54  * just called db_open, they need to do a db_close(), because we have
55  * cloned our own instance of the db_i.
56  */
57 struct rt_i *
58 rt_new_rti(struct db_i *dbip)
59 {
60  register struct rt_i *rtip;
61  register int i;
62 
63  RT_CK_DBI(dbip);
64 
65  /* XXX Move to rt_global_init() ? */
66  if (BU_LIST_FIRST(bu_list, &RTG.rtg_vlfree) == 0) {
67  char *envflags;
68  envflags = getenv("LIBRT_DEBUG");
69  if (envflags) {
70  if (RTG.debug)
71  bu_log("WARNING: discarding LIBRT_DEBUG value in favor of application specified flags\n");
72  else
73  RTG.debug = strtol(envflags, NULL, 0x10);
74  }
75 
77  }
78 
79  BU_ALLOC(rtip, struct rt_i);
80  rtip->rti_magic = RTI_MAGIC;
81  for (i=0; i < RT_DBNHASH; i++) {
82  BU_LIST_INIT(&(rtip->rti_solidheads[i]));
83  }
84  rtip->rti_dbip = db_clone_dbi(dbip, (long *)rtip);
85  rtip->needprep = 1;
86 
87  BU_LIST_INIT(&rtip->HeadRegion);
88 
89  /* This table is used for discovering the per-cpu resource structures */
90  bu_ptbl_init(&rtip->rti_resources, MAX_PSW, "rti_resources ptbl");
91  BU_PTBL_END(&rtip->rti_resources) = MAX_PSW; /* Make 'em all available */
92 
94 
95  /* list of invisible light regions to be deleted after light_init() */
96  bu_ptbl_init(&rtip->delete_regs, 8, "rt_i delete regions list");
97 
98  VSETALL(rtip->mdl_min, INFINITY);
99  VSETALL(rtip->mdl_max, -INFINITY);
100  VSETALL(rtip->rti_inf_box.bn.bn_min, -0.1);
101  VSETALL(rtip->rti_inf_box.bn.bn_max, 0.1);
103 
104  /* XXX These defaults need to be improved */
105  rtip->rti_tol.magic = BN_TOL_MAGIC;
106  rtip->rti_tol.dist = 0.0005;
107  rtip->rti_tol.dist_sq = rtip->rti_tol.dist * rtip->rti_tol.dist;
108  rtip->rti_tol.perp = 1e-6;
109  rtip->rti_tol.para = 1 - rtip->rti_tol.perp;
110 
112  rtip->rti_ttol.abs = 0.0;
113  rtip->rti_ttol.rel = 0.01;
114  rtip->rti_ttol.norm = 0;
115 
116  /* This sets the space partitioning algorithm to Mike's original
117  * non-uniform binary space partitioning tree. If you change this
118  * to anything else, you must also modify "rt_find_backing_dist()"
119  * (in shoot.c), to handle the different algorithm -JRA
120  */
122 
123  rtip->rti_nugrid_dimlimit = 0;
125 
126  /*
127  * Zero the solid instancing counters in dbip database instance.
128  * Done here because the same dbip could be used by multiple
129  * rti's, and rt_gettrees() can be called multiple times on this
130  * one rtip.
131  *
132  * There is a race (collision!) here on d_uses if rt_gettrees() is
133  * called on another rtip of the same dbip before this rtip is
134  * done with all its treewalking.
135  */
136  for (i=0; i < RT_DBNHASH; i++) {
137  register struct directory *dp;
138 
139  dp = rtip->rti_dbip->dbi_Head[i];
140  for (; dp != RT_DIR_NULL; dp = dp->d_forw)
141  dp->d_uses = 0;
142  }
143 
144  return rtip;
145 }
146 
147 
148 /**
149  * Release all the dynamic storage acquired by rt_dirbuild() and any
150  * subsequent ray-tracing operations.
151  *
152  * Any PARALLEL resource structures are freed by rt_clean(). Note
153  * that the rt_g structure needs to be cleaned separately.
154  */
155 void
156 rt_free_rti(struct rt_i *rtip)
157 {
158  RT_CK_RTI(rtip);
159 
160  rt_clean(rtip);
161 
162 #if 0
163  /* XXX These can't be freed here either, because we allocated
164  * them all on rt_uniresource, which doesn't discriminate
165  * on which db_i they go with.
166  */
167 
168  /* The 'struct directory' guys are malloc()ed in big blocks */
169  resp->re_directory_hd = NULL; /* abandon list */
170  if (BU_LIST_IS_INITIALIZED(&resp->re_directory_blocks.l)) {
171  struct directory **dpp;
172  BU_CK_PTBL(&resp->re_directory_blocks);
173  for (BU_PTBL_FOR(dpp, (struct directory **), &resp->re_directory_blocks)) {
174  RT_CK_DIR(*dpp); /* Head of block will be a valid seg */
175  bu_free((void *)(*dpp), "struct directory block");
176  }
177  bu_ptbl_free(&resp->re_directory_blocks);
178  }
179 #endif
180 
181  db_close_client(rtip->rti_dbip, (long *)rtip);
182  rtip->rti_dbip = (struct db_i *)NULL;
183 
184  /* Freeing the actual resource structures' memory is the app's job */
185  bu_ptbl_free(&rtip->rti_resources);
186  bu_ptbl_free(&rtip->delete_regs);
187 
188  bu_free((char *)rtip, "struct rt_i");
189 }
190 
191 
192 /**
193  * This routine should be called just before the first call to
194  * rt_shootray(). It should only be called ONCE per execution, unless
195  * rt_clean() is called in between.
196  *
197  * Because this can be called from rt_shootray(), it may potentially
198  * be called ncpu times, hence the critical section.
199  */
200 void
201 rt_prep_parallel(register struct rt_i *rtip, int ncpu)
202 {
203  register struct region *regp;
204  register struct soltab *stp;
205  register int i;
206  struct resource *resp;
207  vect_t diag;
208 
209  RT_CK_RTI(rtip);
210 
211  if (RT_G_DEBUG&DEBUG_REGIONS) bu_log("rt_prep_parallel(%s, %d, ncpu=%d) START\n",
212  rtip->rti_dbip->dbi_filename,
213  rtip->rti_dbip->dbi_uses, ncpu);
214 
215  bu_semaphore_acquire(RT_SEM_RESULTS); /* start critical section */
216  if (!rtip->needprep) {
217  bu_log("WARNING: rt_prep_parallel(%s, %d) invoked a second time, ignored",
218  rtip->rti_dbip->dbi_filename,
219  rtip->rti_dbip->dbi_uses);
221  return;
222  }
223 
224  if (rtip->nsolids <= 0) {
225  if (rtip->rti_air_discards > 0) {
226  bu_log("rt_prep_parallel(%s, %d): %d primitives discarded due to air regions\n",
227  rtip->rti_dbip->dbi_filename,
228  rtip->rti_dbip->dbi_uses,
229  rtip->rti_air_discards);
230  }
231  bu_log("rt_prep_parallel: no primitives left to prep\n");
232  rtip->needprep = 0; /* rt_gettrees left us nothing */
234  return;
235  }
236 
237  if (rtip->nregions <= 0) {
238  bu_log("rt_prep_parallel: no regions left to prep\n");
239  rtip->needprep = 0; /* rt_gettrees left us nothing */
241  return;
242  }
243 
244  /* In case everything is a halfspace, set a minimum space */
245  if (rtip->mdl_min[X] >= INFINITY) {
246  bu_log("All primitives are halfspaces, setting minimum\n");
247  VSETALL(rtip->mdl_min, -1);
248  }
249  if (rtip->mdl_max[X] <= -INFINITY) {
250  bu_log("All primitives are halfspaces, setting maximum\n");
251  VSETALL(rtip->mdl_max, 1);
252  }
253 
254  /*
255  * Enlarge the model RPP just slightly, to avoid nasty effects
256  * with a solid's face being exactly on the edge
257  */
258  rtip->mdl_min[X] = floor(rtip->mdl_min[X]);
259  rtip->mdl_min[Y] = floor(rtip->mdl_min[Y]);
260  rtip->mdl_min[Z] = floor(rtip->mdl_min[Z]);
261  rtip->mdl_max[X] = ceil(rtip->mdl_max[X]);
262  rtip->mdl_max[Y] = ceil(rtip->mdl_max[Y]);
263  rtip->mdl_max[Z] = ceil(rtip->mdl_max[Z]);
264 
265  /* Compute radius of a model bounding sphere */
266  VSUB2(diag, rtip->mdl_max, rtip->mdl_min);
267  rtip->rti_radius = 0.5 * MAGNITUDE(diag);
268 
269  /* If a resource structure has been provided for us, use it. */
270  resp = (struct resource *)BU_PTBL_GET(&rtip->rti_resources, 0);
271  if (!resp) {
272  resp = &rt_uniresource;
273  }
274  RT_CK_RESOURCE(resp);
275 
276  /* Build array of region pointers indexed by reg_bit. Optimize
277  * each region's expression tree. Set this region's bit in the
278  * bit vector of every solid contained in the subtree.
279  */
280  rtip->Regions = (struct region **)bu_calloc(rtip->nregions, sizeof(struct region *), "rtip->Regions[]");
281  if (RT_G_DEBUG&DEBUG_REGIONS) bu_log("rt_prep_parallel(%s, %d) about to optimize regions\n",
282  rtip->rti_dbip->dbi_filename,
283  rtip->rti_dbip->dbi_uses);
284  for (BU_LIST_FOR(regp, region, &(rtip->HeadRegion))) {
285  /* Ensure bit numbers are unique */
286  BU_ASSERT_PTR(rtip->Regions[regp->reg_bit], ==, REGION_NULL);
287  rtip->Regions[regp->reg_bit] = regp;
288  rt_optim_tree(regp->reg_treetop, resp);
289  rt_solid_bitfinder(regp->reg_treetop, regp, resp);
290  if (RT_G_DEBUG&DEBUG_REGIONS) {
291  db_ck_tree(regp->reg_treetop);
292  rt_pr_region(regp);
293  }
294  }
295  if (RT_G_DEBUG&DEBUG_REGIONS) {
296  bu_log("rt_prep_parallel() printing primitives' region pointers\n");
297  RT_VISIT_ALL_SOLTABS_START(stp, rtip) {
298  bu_log("solid %s ", stp->st_name);
299  bu_pr_ptbl("st_regions", &stp->st_regions, 1);
301  }
302 
303  /* Space for array of soltab pointers indexed by solid bit number.
304  * Include enough extra space for an extra bitv_t's worth of bits,
305  * to handle round-up.
306  */
307  rtip->rti_Solids =
308  (struct soltab **)bu_calloc(rtip->nsolids + (1<<BU_BITV_SHIFT),
309  sizeof(struct soltab *),
310  "rtip->rti_Solids[]");
311  /*
312  * Build array of solid table pointers indexed by solid ID. Last
313  * element for each kind will be found in
314  * rti_sol_by_type[id][rti_nsol_by_type[id]-1]
315  */
316  RT_VISIT_ALL_SOLTABS_START(stp, rtip) {
317  /* Ensure bit numbers are unique */
318  register struct soltab **ssp = &rtip->rti_Solids[stp->st_bit];
319  if (*ssp != SOLTAB_NULL) {
320  bu_log("rti_Solids[%ld] is non-empty! rtip=%p\n", stp->st_bit, (void *)rtip);
321  bu_log("Existing entry is (st_rtip=%p):\n", (void *)(*ssp)->st_rtip);
322  rt_pr_soltab(*ssp);
323  bu_log("2nd soltab also claiming that bit is (st_rtip=%p):\n", (void *)stp->st_rtip);
324  rt_pr_soltab(stp);
325  }
326  BU_ASSERT_PTR(*ssp, ==, SOLTAB_NULL);
327  *ssp = stp;
328  rtip->rti_nsol_by_type[stp->st_id]++;
330 
331  /* Find solid type with maximum length (for rt_shootray) */
332  rtip->rti_maxsol_by_type = 0;
333  for (i=0; i <= ID_MAX_SOLID; i++) {
334  if (rtip->rti_nsol_by_type[i] > rtip->rti_maxsol_by_type)
335  rtip->rti_maxsol_by_type = rtip->rti_nsol_by_type[i];
336  }
337  /* Malloc the storage and zero the counts */
338  for (i=0; i <= ID_MAX_SOLID; i++) {
339  if (rtip->rti_nsol_by_type[i] <= 0) continue;
340  rtip->rti_sol_by_type[i] = (struct soltab **)bu_calloc(
341  rtip->rti_nsol_by_type[i],
342  sizeof(struct soltab *),
343  "rti_sol_by_type[]");
344  rtip->rti_nsol_by_type[i] = 0;
345  }
346  /* Fill in the array and rebuild the count (aka index) */
347  RT_VISIT_ALL_SOLTABS_START(stp, rtip) {
348  register int id;
349  id = stp->st_id;
350  rtip->rti_sol_by_type[id][rtip->rti_nsol_by_type[id]++] = stp;
352  if (RT_G_DEBUG & (DEBUG_DB|DEBUG_SOLIDS)) {
353  bu_log("rt_prep_parallel(%s, %d) printing number of primitives by type\n",
354  rtip->rti_dbip->dbi_filename,
355  rtip->rti_dbip->dbi_uses);
356  for (i=1; i <= ID_MAX_SOLID; i++) {
357  bu_log("%5d %s (%d)\n",
358  rtip->rti_nsol_by_type[i],
359  OBJ[i].ft_name,
360  i);
361  }
362  }
363 
364  /* If region-id expression file exists, process it */
365  rt_regionfix(rtip);
366 
367  /* For plotting, compute a slight enlargement of the model RPP, to
368  * allow room for rays clipped to the model RPP to be depicted.
369  * Always do this, because application debugging may use it too.
370  */
371  {
372  register fastf_t f, diff;
373 
374  diff = (rtip->mdl_max[X] - rtip->mdl_min[X]);
375  f = (rtip->mdl_max[Y] - rtip->mdl_min[Y]);
376  if (f > diff) diff = f;
377  f = (rtip->mdl_max[Z] - rtip->mdl_min[Z]);
378  if (f > diff) diff = f;
379  diff *= 0.1; /* 10% expansion of box */
380  rtip->rti_pmin[0] = rtip->mdl_min[0] - diff;
381  rtip->rti_pmin[1] = rtip->mdl_min[1] - diff;
382  rtip->rti_pmin[2] = rtip->mdl_min[2] - diff;
383  rtip->rti_pmax[0] = rtip->mdl_max[0] + diff;
384  rtip->rti_pmax[1] = rtip->mdl_max[1] + diff;
385  rtip->rti_pmax[2] = rtip->mdl_max[2] + diff;
386  }
387 
388  /*
389  * Partition space
390  *
391  * Multiple CPUs can be used here.
392  */
393  for (i=1; i<=CUT_MAXIMUM; i++) rtip->rti_ncut_by_type[i] = 0;
394  rt_cut_it(rtip, ncpu);
395 
396  /* Release storage used for bounding RPPs of solid "pieces" */
397  RT_VISIT_ALL_SOLTABS_START(stp, rtip) {
398  if (stp->st_piece_rpps) {
399  bu_free((char *)stp->st_piece_rpps, "st_piece_rpps[]");
400  stp->st_piece_rpps = NULL;
401  }
403 
404  /* Plot bounding RPPs */
405  if ((RT_G_DEBUG&DEBUG_PL_BOX)) {
406  FILE *plotfp;
407 
408  plotfp = fopen("rtrpp.plot3", "wb");
409  if (plotfp != NULL) {
410  /* Plot solid bounding boxes, in white */
411  pl_color(plotfp, 255, 255, 255);
412  rt_plot_all_bboxes(plotfp, rtip);
413  (void)fclose(plotfp);
414  }
415  }
416 
417  /* Plot solid outlines */
418  if ((RT_G_DEBUG&DEBUG_PL_SOLIDS)) {
419  FILE *plotfp;
420 
421  plotfp = fopen("rtsolids.plot3", "wb");
422  if (plotfp != NULL) {
423  rt_plot_all_solids(plotfp, rtip, resp);
424  (void)fclose(plotfp);
425  }
426  }
427  rtip->needprep = 0; /* prep is done */
428  bu_semaphore_release(RT_SEM_RESULTS); /* end critical section */
429 
430  if (RT_G_DEBUG&DEBUG_REGIONS) bu_log("rt_prep_parallel(%s, %d, ncpu=%d) FINISH\n",
431  rtip->rti_dbip->dbi_filename,
432  rtip->rti_dbip->dbi_uses, ncpu);
433 }
434 
435 
436 /**
437  * Compatibility stub. Only uses 1 CPU.
438  */
439 void
440 rt_prep(register struct rt_i *rtip)
441 {
442  RT_CK_RTI(rtip);
443  rt_prep_parallel(rtip, 1);
444 }
445 
446 
447 /**
448  * Plot the bounding boxes of all the active solids. Color may be set
449  * in advance by the caller.
450  */
451 void
452 rt_plot_all_bboxes(FILE *fp, struct rt_i *rtip)
453 {
454  register struct soltab *stp;
455 
456  RT_CK_RTI(rtip);
457  pdv_3space(fp, rtip->rti_pmin, rtip->rti_pmax);
458  RT_VISIT_ALL_SOLTABS_START(stp, rtip) {
459  /* Ignore "dead" solids in the list. (They failed prep) */
460  if (stp->st_aradius <= 0) continue;
461  /* Don't draw infinite solids */
462  if (stp->st_aradius >= INFINITY)
463  continue;
464  pdv_3box(fp, stp->st_min, stp->st_max);
466 }
467 
468 
469 void
471  FILE *fp,
472  struct rt_i *rtip,
473  struct resource *resp)
474 {
475  register struct soltab *stp;
476 
477  RT_CK_RTI(rtip);
478 
479  pdv_3space(fp, rtip->rti_pmin, rtip->rti_pmax);
480 
481  RT_VISIT_ALL_SOLTABS_START(stp, rtip) {
482  /* Ignore "dead" solids in the list. (They failed prep) */
483  if (stp->st_aradius <= 0) continue;
484 
485  /* Don't draw infinite solids */
486  if (stp->st_aradius >= INFINITY)
487  continue;
488 
489  (void)rt_plot_solid(fp, rtip, stp, resp);
491 }
492 
493 
494 /**
495  * "Draw" a solid with the same kind of wireframes that MGED would
496  * display, appending vectors to an already initialized vlist head.
497  *
498  * Returns -
499  * <0 failure
500  * 0 OK
501  */
502 int
504  struct bu_list *vhead,
505  struct rt_i *rtip,
506  const struct soltab *stp,
507  struct resource *resp)
508 {
509  struct rt_db_internal intern;
510  int ret;
511 
512  if (rt_db_get_internal(&intern, stp->st_dp, rtip->rti_dbip, stp->st_matp, resp) < 0) {
513  bu_log("rt_vlist_solid(%s): rt_db_get_internal() failed\n", stp->st_name);
514  return -1; /* FAIL */
515  }
516  RT_CK_DB_INTERNAL(&intern);
517 
518  ret = -1;
519  if (OBJ[intern.idb_type].ft_plot) {
520  ret = OBJ[intern.idb_type].ft_plot(vhead, &intern, &rtip->rti_ttol, &rtip->rti_tol, NULL);
521  }
522  if (ret < 0) {
523  bu_log("rt_vlist_solid(%s): ft_plot() failure\n", stp->st_name);
524  rt_db_free_internal(&intern);
525  return -2;
526  }
527  rt_db_free_internal(&intern);
528 
529  return 0;
530 }
531 
532 
533 /**
534  * Plot a solid with the same kind of wireframes that MGED would
535  * display, in UNIX-plot form, on the indicated file descriptor. The
536  * caller is responsible for calling pdv_3space().
537  *
538  * Returns -
539  * <0 failure
540  * 0 OK
541  */
542 int
544  register FILE *fp,
545  struct rt_i *rtip,
546  const struct soltab *stp,
547  struct resource *resp)
548 {
549  struct bu_list vhead;
550  struct region *regp;
551 
552  RT_CK_RTI(rtip);
553  RT_CK_SOLTAB(stp);
554 
555  BU_LIST_INIT(&vhead);
556 
557  if (rt_vlist_solid(&vhead, rtip, stp, resp) < 0) {
558  bu_log("rt_plot_solid(%s): rt_vlist_solid() failed\n",
559  stp->st_name);
560  return -1; /* FAIL */
561  }
562 
563  if (BU_LIST_IS_EMPTY(&vhead)) {
564  bu_log("rt_plot_solid(%s): no vectors to plot?\n",
565  stp->st_name);
566  return -3; /* FAIL */
567  }
568 
569  /* Take color from one region */
570  if ((regp = (struct region *)BU_PTBL_GET(&stp->st_regions, 0)) != REGION_NULL) {
571  pl_color(fp,
572  (int)(255*regp->reg_mater.ma_color[0]),
573  (int)(255*regp->reg_mater.ma_color[1]),
574  (int)(255*regp->reg_mater.ma_color[2]));
575  }
576 
577  rt_vlist_to_uplot(fp, &vhead);
578 
579  RT_FREE_VLIST(&vhead);
580  return 0; /* OK */
581 }
582 
583 
584 void
586  int cpu_num,
587  struct rt_i *rtip)
588 {
589  if (!resp)
590  return;
591 
592  BU_ASSERT_LONG(cpu_num, >=, 0);
593  BU_ASSERT_LONG(cpu_num, <, MAX_PSW);
594 
595  if (rtip)
596  RT_CK_RTI(rtip);
597 
598  if (resp == &rt_uniresource) {
599  cpu_num = 0;
600  } else {
601  if (rtip != NULL && rtip->rti_treetop) {
602  /* this is a submodel */
603  BU_ASSERT_LONG(cpu_num, <, (long)rtip->rti_resources.blen);
604  }
605  }
606 
607  /* point to the random number table so we can draw. set to
608  * MAX_PSW*cpu_num just to keep each core a good distance away
609  * from each other, but that's not a really great reason.
610  */
611  bn_rand_init(resp->re_randptr, MAX_PSW*cpu_num);
612 
613  if (!BU_LIST_IS_INITIALIZED(&resp->re_seg))
614  BU_LIST_INIT(&resp->re_seg);
615 
617  bu_ptbl_init(&resp->re_seg_blocks, 64, "re_seg_blocks ptbl");
618 
620  bu_ptbl_init(&resp->re_directory_blocks, 64, "re_directory_blocks ptbl");
621 
622  if (!BU_LIST_IS_INITIALIZED(&resp->re_parthead))
623  BU_LIST_INIT(&resp->re_parthead);
624 
626  BU_LIST_INIT(&resp->re_solid_bitv);
627 
630 
631  if (!BU_LIST_IS_INITIALIZED(&resp->re_nmgfree))
632  BU_LIST_INIT(&resp->re_nmgfree);
633 
634  resp->re_boolstack = NULL;
635  resp->re_boolslen = 0;
636 
637  resp->re_cpu = cpu_num;
638  resp->re_magic = RESOURCE_MAGIC;
639 
640  if (rtip == NULL)
641  return; /* only in rt_uniresource case */
642 
643  /* Ensure that this CPU's resource structure is registered in rt_i */
644  /* It may already be there when we're called from rt_clean_resource */
645  {
646  struct resource *ores = (struct resource *)BU_PTBL_GET(&rtip->rti_resources, cpu_num);
647  if (ores != NULL && ores != resp) {
648  bu_log("rt_init_resource(cpu=%d) re-registering resource, had %p, new=%p\n",
649  cpu_num,
650  (void *)ores,
651  (void *)resp);
652  return;
653  }
654  BU_PTBL_SET(&rtip->rti_resources, cpu_num, resp);
655  }
656 }
657 
658 
659 /**
660  * This method contains all the code that was formerly in
661  * rt_clean_resource, except for the call to rt_init_resource().
662  */
663 void
664 rt_clean_resource_basic(struct rt_i *rtip, struct resource *resp)
665 {
666  if (rtip) {
667  RT_CK_RTI(rtip);
668  }
669  RT_CK_RESOURCE(resp);
670 
671  /* The 'struct seg' guys are malloc()ed in blocks, not
672  * individually, so they're kept track of two different ways.
673  */
674  BU_LIST_INIT(&resp->re_seg); /* abandon the list of individuals */
675  if (BU_LIST_IS_INITIALIZED(&resp->re_seg_blocks.l)) {
676  struct seg **spp;
677  BU_CK_PTBL(&resp->re_seg_blocks);
678  for (BU_PTBL_FOR(spp, (struct seg **), &resp->re_seg_blocks)) {
679  RT_CK_SEG(*spp); /* Head of block will be a valid seg */
680  bu_free((void *)(*spp), "struct seg block");
681  }
682  bu_ptbl_free(&resp->re_seg_blocks);
684  }
685 
686  /* The "struct hitmiss' guys are individually malloc()ed */
687  if (BU_LIST_IS_INITIALIZED(&resp->re_nmgfree)) {
688  struct hitmiss *hitp;
689  while (BU_LIST_WHILE(hitp, hitmiss, &resp->re_nmgfree)) {
690  NMG_CK_HITMISS(hitp);
691  BU_LIST_DEQUEUE((struct bu_list *)hitp);
692  bu_free((void *)hitp, "struct hitmiss");
693  }
694  resp->re_nmgfree.forw = BU_LIST_NULL;
695  }
696 
697  /* The 'struct partition' guys are individually malloc()ed */
698  if (BU_LIST_IS_INITIALIZED(&resp->re_parthead)) {
699  struct partition *pp;
700  while (BU_LIST_WHILE(pp, partition, &resp->re_parthead)) {
701  RT_CK_PT(pp);
702  BU_LIST_DEQUEUE((struct bu_list *)pp);
703  bu_ptbl_free(&pp->pt_seglist);
704  bu_free((void *)pp, "struct partition");
705  }
706  resp->re_parthead.forw = BU_LIST_NULL;
707  }
708 
709  /* The 'struct bu_bitv' guys on re_solid_bitv are individually malloc()ed */
711  struct bu_bitv *bvp;
712  while (BU_LIST_WHILE(bvp, bu_bitv, &resp->re_solid_bitv)) {
713  BU_CK_BITV(bvp);
714  BU_LIST_DEQUEUE(&bvp->l);
715  bvp->nbits = 0; /* sanity */
716  bu_free((void *)bvp, "struct bu_bitv");
717  }
719  }
720 
721  /* The 'struct bu_ptbl' guys on re_region_ptbl are individually malloc()ed */
723  struct bu_ptbl *tabp;
724  while (BU_LIST_WHILE(tabp, bu_ptbl, &resp->re_region_ptbl)) {
725  BU_CK_PTBL(tabp);
726  BU_LIST_DEQUEUE(&tabp->l);
727  bu_ptbl_free(tabp);
728  bu_free((void *)tabp, "struct bu_ptbl");
729  }
731  }
732 
733  /* The 're_tree' guys are individually malloc()ed and linked using the 'tb_left' field */
734  if (resp->re_tree_hd != TREE_NULL) {
735  union tree *tp;
736 
737  tp = resp->re_tree_hd;
738  while (tp != TREE_NULL) {
739  resp->re_tree_hd = tp->tr_b.tb_left;
740  bu_free((char *)tp, "union tree in resource struct");
741  tp = resp->re_tree_hd;
742  }
743  }
744 
745  /* 're_boolstack' is a simple pointer */
746  if (resp->re_boolstack) {
747  bu_free((void *)resp->re_boolstack, "boolstack");
748  resp->re_boolstack = NULL;
749  resp->re_boolslen = 0;
750  }
751 
752  /* Release the state variables for 'solid pieces' */
753  rt_res_pieces_clean(resp, rtip);
754 
755  resp->re_magic = 0;
756 
757 }
758 
759 
760 /**
761  * This method performs the basic resource clean, and also frees all
762  * the directory entry blocks. The resource structure is not
763  * re-initialized.
764  *
765  * DO NOT CALL THIS METHOD IF YOU ARE STILL USING THE RT_I OR DB_I
766  * INSTANCES.
767  */
768 void
769 rt_clean_resource_complete(struct rt_i *rtip, struct resource *resp)
770 {
771  rt_clean_resource_basic(rtip, resp);
772 
774  struct directory **dpp;
776  for (BU_PTBL_FOR(dpp, (struct directory **), &resp->re_directory_blocks)) {
777  RT_CK_DIR(*dpp); /* Head of block will be a valid seg */
778  bu_free((void *)(*dpp), "struct directory block");
779  }
782  resp->re_directory_hd = NULL;
783  }
784 }
785 
786 
787 /**
788  * Deallocate the per-cpu "private" memory resources:
789  *
790  * segment freelist
791  * hitmiss freelist for NMG raytracer
792  * partition freelist
793  * solid_bitv freelist
794  * region_ptbl freelist
795  * re_boolstack
796  *
797  * Some care is required, as rt_uniresource may not be fully
798  * initialized before it gets freed.
799  *
800  * Note that the resource struct's storage is not freed (it may be
801  * static or otherwise allocated by a LIBRT application) but any
802  * dynamic memory pointed to by it is freed.
803  *
804  * One exception to this is that the re_directory_hd and
805  * re_directory_blocks are not touched unless there is no raytrace
806  * instance, because the "directory" structures (which are really part
807  * of the db_i) continue to be in use.
808  */
809 void
810 rt_clean_resource(struct rt_i *rtip, struct resource *resp)
811 {
812  rt_clean_resource_basic(rtip, resp);
813 
814  /* Reinitialize pointers, to be tidy. No storage is allocated.
815  * actually, some storage is allocated in the calls to
816  * bu_ptbl_init - JRA
817  */
818  rt_init_resource(resp, resp->re_cpu, rtip);
819 }
820 
821 
822 /**
823  * returns a bitv zero-initialized with space for least nbits back to
824  * the caller. if a resource pointer is provided, a previously
825  * allocated bitv may be reused or a new one will be allocated.
826  */
827 struct bu_bitv *
828 rt_get_solidbitv(size_t nbits, struct resource *resp)
829 {
830  struct bu_bitv *solidbits;
831  int counter=0;
832 
833  if (resp && resp->re_solid_bitv.magic != BU_LIST_HEAD_MAGIC) {
834  bu_bomb("Bad magic number in re_solid_btiv list\n");
835  }
836 
837  if (!resp || BU_LIST_IS_EMPTY(&resp->re_solid_bitv)) {
838  solidbits = bu_bitv_new((unsigned int)nbits);
839  } else {
840  /* scan list for a reusable bitv */
841  for (BU_LIST_FOR(solidbits, bu_bitv, &resp->re_solid_bitv)) {
842  if (solidbits->nbits >= nbits) {
843  BU_LIST_DEQUEUE(&solidbits->l);
844  bu_bitv_clear(solidbits);
845  break;
846  }
847  counter++;
848  }
849  /* no match, allocate a new one */
850  if (solidbits == (struct bu_bitv *)&resp->re_solid_bitv) {
851  solidbits = bu_bitv_new((unsigned int)nbits);
852  }
853  }
854 
855  return solidbits;
856 }
857 
858 
859 /**
860  * Release all the dynamic storage associated with a particular rt_i
861  * structure, except for the database instance information (dir, etc.)
862  * and the rti_resources ptbl.
863  *
864  * Note that an animation script can invoke a "clean" operation before
865  * anything has been prepped.
866  */
867 void
868 rt_clean(register struct rt_i *rtip)
869 {
870  register struct region *regp;
871  register struct bu_list *head;
872  register struct soltab *stp;
873  int i;
874 
875  RT_CK_RTI(rtip);
876 
877  /* DEBUG: Ensure that all region trees are valid */
878  for (BU_LIST_FOR(regp, region, &(rtip->HeadRegion))) {
879  RT_CK_REGION(regp);
880  db_ck_tree(regp->reg_treetop);
881  }
882  /*
883  * Clear out the region table db_free_tree() will delete most
884  * soltab structures.
885  */
886  while (BU_LIST_WHILE(regp, region, &rtip->HeadRegion)) {
887  RT_CK_REGION(regp);
888  BU_LIST_DEQUEUE(&(regp->l));
890  bu_free((void *)regp->reg_name, "region name str");
891  regp->reg_name = (char *)0;
892  if (regp->reg_mater.ma_shader) {
893  bu_free((void *)regp->reg_mater.ma_shader, "ma_shader");
894  regp->reg_mater.ma_shader = (char *)NULL;
895  }
896  bu_avs_free(&(regp->attr_values));
897  bu_free((void *)regp, "struct region");
898  }
899  rtip->nregions = 0;
900 
901  /*
902  * Clear out the solid table, AFTER doing the region table. Can't
903  * use RT_VISIT_ALL_SOLTABS_START here
904  */
905  head = &(rtip->rti_solidheads[0]);
906  for (; head < &(rtip->rti_solidheads[RT_DBNHASH]); head++) {
907  while (BU_LIST_WHILE(stp, soltab, head)) {
908  RT_CHECK_SOLTAB(stp);
909  rt_free_soltab(stp);
910  }
911  }
912  rtip->nsolids = 0;
913 
914  /* Clean out the array of pointers to regions, if any */
915  if (rtip->Regions) {
916  bu_free((char *)rtip->Regions, "rtip->Regions[]");
917  rtip->Regions = (struct region **)0;
918 
919  /* Free space partitions */
920  rt_fr_cut(rtip, &(rtip->rti_CutHead));
921  memset((char *)&(rtip->rti_CutHead), 0, sizeof(union cutter));
922  rt_fr_cut(rtip, &(rtip->rti_inf_box));
923  memset((char *)&(rtip->rti_inf_box), 0, sizeof(union cutter));
924  }
925  rt_cut_clean(rtip);
926 
927  /* Free animation structures */
928  /* XXX modify to only free those from this rtip */
929  if (rtip->rti_dbip)
930  db_free_anim(rtip->rti_dbip);
931 
932  /* Free array of solid table pointers indexed by solid ID */
933  for (i=0; i <= ID_MAX_SOLID; i++) {
934  if (rtip->rti_nsol_by_type[i] <= 0) continue;
935  if (rtip->rti_sol_by_type[i]) {
936  bu_free((char *)rtip->rti_sol_by_type[i], "sol_by_type");
937  }
938  rtip->rti_sol_by_type[i] = (struct soltab **)0;
939  rtip->rti_nsol_by_type[i] = 0;
940  }
941  if (rtip->rti_Solids) {
942  bu_free((char *)rtip->rti_Solids, "rtip->rti_Solids[]");
943  rtip->rti_Solids = (struct soltab **)0;
944  }
945 
946  /*
947  * Clean out every cpu's "struct resource". These are provided by
948  * the caller's application (or are defaulted to rt_uniresource)
949  * and can't themselves be freed. rt_shootray() saved a table of
950  * them for us to use here. rt_uniresource may or may not be in
951  * this table.
952  */
954  struct resource **rpp;
955  BU_CK_PTBL(&rtip->rti_resources);
956  for (BU_PTBL_FOR(rpp, (struct resource **), &rtip->rti_resources)) {
957  /* After using a submodel, some entries may be NULL
958  * while others are not NULL
959  */
960  if (*rpp == NULL) continue;
961  RT_CK_RESOURCE(*rpp);
962  /* Clean but do not free the resource struct */
963  rt_clean_resource(rtip, *rpp);
964 #if 0
965 /* XXX Can't do this, or 'clean' command in RT animation script will dump core. */
966 /* rt expects them to stay inited and remembered, forever. */
967 /* Submodels will clean up after themselves */
968  /* Forget remembered ptr, but keep ptbl allocated */
969  *rpp = NULL;
970 #endif
971  }
972  }
973 
974  if (rtip->Orca_hash_tbl) {
975  bu_free((char *)rtip->Orca_hash_tbl, "rtip->Orca_hash_tbl");
976  rtip->Orca_hash_tbl = NULL;
977  }
978  if (rt_uniresource.re_magic) {
979  rt_clean_resource(rtip, &rt_uniresource);/* Used for rt_optim_tree() */
980  }
981 
982  /*
983  * Re-initialize everything important.
984  * This duplicates the code in rt_new_rti().
985  */
986 
988  VMOVE(rtip->rti_inf_box.bn.bn_min, rtip->mdl_min);
989  VMOVE(rtip->rti_inf_box.bn.bn_max, rtip->mdl_max);
990  VSETALL(rtip->mdl_min, INFINITY);
991  VSETALL(rtip->mdl_max, -INFINITY);
992 
996 
997  if (rtip->rti_dbip) {
998  /*
999  * Zero the solid instancing counters in dbip database
1000  * instance. Done here because the same dbip could be used by
1001  * multiple rti's, and rt_gettrees() can be called multiple
1002  * times on this one rtip.
1003  *
1004  * FIXME: There is a race (collision!) here on d_uses if
1005  * rt_gettrees() is called on another rtip of the same dbip
1006  * before this rtip is done with all its treewalking.
1007  *
1008  * This must be done for each 'clean' to keep
1009  * rt_find_identical_solid() working properly as d_uses goes
1010  * up.
1011  */
1012  for (i=0; i < RT_DBNHASH; i++) {
1013  register struct directory *dp;
1014 
1015  dp = rtip->rti_dbip->dbi_Head[i];
1016  for (; dp != RT_DIR_NULL; dp = dp->d_forw)
1017  dp->d_uses = 0;
1018  }
1019  }
1020 
1021  bu_ptbl_reset(&rtip->delete_regs);
1022 
1023  rtip->rti_magic = RTI_MAGIC;
1024  rtip->needprep = 1;
1025 }
1026 
1027 
1028 /**
1029  * Remove a region from the linked list. Used to remove a particular
1030  * region from the active database, presumably after some useful
1031  * information has been extracted (e.g., a light being converted to
1032  * implicit type), or for special effects.
1033  *
1034  * Returns -
1035  * 0 success
1036  */
1037 int
1038 rt_del_regtree(struct rt_i *rtip, register struct region *delregp, struct resource *resp)
1039 {
1040  if (rtip) RT_CK_RTI(rtip);
1041  RT_CK_RESOURCE(resp);
1042  RT_CK_REGION(delregp);
1043 
1044  if (RT_G_DEBUG & DEBUG_REGIONS)
1045  bu_log("rt_del_regtree(%s): region deleted\n", delregp->reg_name);
1046 
1047  BU_LIST_DEQUEUE(&(delregp->l));
1048 
1049  db_free_tree(delregp->reg_treetop, resp);
1050  delregp->reg_treetop = TREE_NULL;
1051  bu_free((char *)delregp->reg_name, "region name str");
1052  delregp->reg_name = (char *)0;
1053  bu_avs_free(&(delregp->attr_values));
1054  bu_free((char *)delregp, "struct region");
1055  return 0;
1056 }
1057 
1058 
1059 /**
1060  * Used to walk the boolean tree, setting bits for all the solids in
1061  * the tree to the provided bit vector. Should be called AFTER the
1062  * region bits have been assigned.
1063  */
1064 HIDDEN void
1065 rt_solid_bitfinder(register union tree *treep, struct region *regp, struct resource *resp)
1066 {
1067  register union tree **sp;
1068  register struct soltab *stp;
1069  register union tree **stackend;
1070 
1071  RT_CK_REGION(regp);
1072  RT_CK_RESOURCE(resp);
1073 
1074  while ((sp = resp->re_boolstack) == (union tree **)0)
1075  rt_grow_boolstack(resp);
1076  stackend = &(resp->re_boolstack[resp->re_boolslen-1]);
1077 
1078  *sp++ = TREE_NULL;
1079  *sp++ = treep;
1080  while ((treep = *--sp) != TREE_NULL) {
1081  RT_CK_TREE(treep);
1082  switch (treep->tr_op) {
1083  case OP_NOP:
1084  break;
1085  case OP_SOLID:
1086  stp = treep->tr_a.tu_stp;
1087  RT_CK_SOLTAB(stp);
1088  bu_ptbl_ins(&stp->st_regions, (long *)regp);
1089  break;
1090  case OP_UNION:
1091  case OP_INTERSECT:
1092  case OP_SUBTRACT:
1093  /* BINARY type */
1094  /* push both nodes - search left first */
1095  *sp++ = treep->tr_b.tb_right;
1096  *sp++ = treep->tr_b.tb_left;
1097  if (sp >= stackend) {
1098  register int off = sp - resp->re_boolstack;
1099  rt_grow_boolstack(resp);
1100  sp = &(resp->re_boolstack[off]);
1101  stackend = &(resp->re_boolstack[resp->re_boolslen-1]);
1102  }
1103  break;
1104  default:
1105  bu_log("rt_solid_bitfinder: op=x%x\n", treep->tr_op);
1106  break;
1107  }
1108  }
1109 }
1110 
1111 
1112 /**
1113  * Check as many of the in-memory data structures as is practical.
1114  * Useful for detecting memory corruption, and inappropriate sharing
1115  * between different LIBRT instances.
1116  */
1117 void
1118 rt_ck(register struct rt_i *rtip)
1119 {
1120  struct region *regp;
1121  struct soltab *stp;
1122 
1123  RT_CK_RTI(rtip);
1124  RT_CK_DBI(rtip->rti_dbip);
1125 
1126  db_ck_directory(rtip->rti_dbip);
1127 
1128  RT_VISIT_ALL_SOLTABS_START(stp, rtip) {
1129  RT_CK_SOLTAB(stp);
1131 
1132  for (BU_LIST_FOR(regp, region, &(rtip->HeadRegion))) {
1133  RT_CK_REGION(regp);
1134  db_ck_tree(regp->reg_treetop);
1135  }
1136  /* rti_CutHead */
1137 
1138 }
1139 
1140 
1141 /**
1142  * Loads a new set of attribute values (corresponding to the provided
1143  * list of attribute names) for each region structure in the provided
1144  * rtip.
1145  *
1146  * Returns -
1147  * The number of region structures affected
1148  */
1149 int rt_load_attrs(struct rt_i *rtip, char **attrs)
1150 {
1151  struct region *regp;
1152  struct bu_attribute_value_set avs;
1153  struct directory *dp;
1154  const char *reg_name;
1155  const char *attr;
1156  int attr_count=0;
1157  int region_count=0;
1158  int did_set, i;
1159 
1160  RT_CHECK_RTI(rtip);
1161  RT_CK_DBI(rtip->rti_dbip);
1162 
1163  if (db_version(rtip->rti_dbip) < 5)
1164  return 0;
1165 
1166  while (attrs[attr_count])
1167  attr_count++;
1168 
1169  for (BU_LIST_FOR(regp, region, &(rtip->HeadRegion))) {
1170  RT_CK_REGION(regp);
1171 
1172  did_set = 0;
1173  if ((reg_name=strrchr(regp->reg_name, '/')) == NULL)
1174  reg_name = regp->reg_name;
1175  else
1176  reg_name++;
1177 
1178  if ((dp=db_lookup(rtip->rti_dbip, reg_name, LOOKUP_NOISY)) == RT_DIR_NULL)
1179  continue;
1180 
1181  bu_avs_init_empty(&avs);
1182  if (db5_get_attributes(rtip->rti_dbip, &avs, dp)) {
1183  bu_log("rt_load_attrs: Failed to get attributes for region %s\n", reg_name);
1184  continue;
1185  }
1186 
1187  bu_avs_init_empty(&(regp->attr_values));
1188  for (i=0; i<attr_count; i++) {
1189  if ((attr = bu_avs_get(&avs, attrs[i])) == NULL)
1190  continue;
1191 
1192  bu_avs_add(&(regp->attr_values), attrs[i], attr);
1193  did_set = 1;
1194  }
1195 
1196  if (did_set)
1197  region_count++;
1198 
1199  bu_avs_free(&avs);
1200  }
1201 
1202  return region_count;
1203 }
1204 
1205 
1206 /**
1207  * Routine called by "rt_find_paths". Used for recursing through a
1208  * tree to find a path to the specified "end". The resulting path is
1209  * returned in "curr_path".
1210  */
1211 static void
1212 rt_find_path(struct db_i *dbip,
1213  union tree *tp,
1214  struct directory *end,
1215  struct bu_ptbl *paths,
1216  struct db_full_path **curr_path,
1217  struct resource *resp)
1218 {
1219  int curr_path_index=(*curr_path)->fp_len;
1220  struct db_full_path *newpath;
1221  struct directory *dp;
1222  struct rt_db_internal intern;
1223  struct rt_comb_internal *comb;
1224 
1225  switch (tp->tr_op) {
1226  case OP_DB_LEAF:
1227  dp = db_lookup(dbip, tp->tr_l.tl_name, 1);
1228  if (dp == RT_DIR_NULL) {
1229  bu_log("Unable to lookup geometry [%s]\nAborting.\n", tp->tr_l.tl_name);
1230  return;
1231  }
1232  db_add_node_to_full_path(*curr_path, dp);
1233  if (dp == end) {
1234  bu_ptbl_ins(paths, (long *)(*curr_path));
1235  BU_ALLOC(newpath, struct db_full_path);
1236 
1237  db_full_path_init(newpath);
1238  db_dup_full_path(newpath, (*curr_path));
1239  (*curr_path) = newpath;
1240  } else if ((dp->d_flags & RT_DIR_COMB) && !(dp->d_flags & RT_DIR_REGION)) {
1241  if (rt_db_get_internal(&intern, dp, dbip, NULL, resp) < 0) {
1242  bu_log("Unable to load [%s]\nAborting.\n", tp->tr_l.tl_name);
1243  return;
1244  }
1245  comb = (struct rt_comb_internal *)intern.idb_ptr;
1246  rt_find_path(dbip, comb->tree, end, paths, curr_path, resp);
1247  rt_db_free_internal(&intern);
1248  }
1249  break;
1250  case OP_UNION:
1251  case OP_SUBTRACT:
1252  case OP_INTERSECT:
1253  case OP_XOR:
1254  /* binary, process both subtrees */
1255  rt_find_path(dbip, tp->tr_b.tb_left, end, paths, curr_path, resp);
1256  (*curr_path)->fp_len = curr_path_index;
1257  rt_find_path(dbip, tp->tr_b.tb_right, end, paths, curr_path, resp);
1258  break;
1259  case OP_NOT:
1260  case OP_GUARD:
1261  rt_find_path(dbip, tp->tr_b.tb_left, end, paths, curr_path, resp);
1262  break;
1263  default:
1264  bu_log("ERROR: rt_find_path(): Unrecognized OP (%d)\n", tp->tr_op);
1265  break;
1266  }
1267 }
1268 
1269 
1270 /**
1271  * Routine to find all the paths from the "start" to the "end". The
1272  * resulting paths are returned in "paths"
1273  */
1274 int
1275 rt_find_paths(struct db_i *dbip,
1276  struct directory *start,
1277  struct directory *end,
1278  struct bu_ptbl *paths,
1279  struct resource *resp)
1280 {
1281  struct rt_db_internal intern;
1282  struct db_full_path *path;
1283  struct rt_comb_internal *comb;
1284 
1285  BU_ALLOC(path, struct db_full_path);
1286  db_full_path_init(path);
1287  db_add_node_to_full_path(path, start);
1288 
1289  if (start == end) {
1290  bu_ptbl_ins(paths, (long *)path);
1291  return 0;
1292  }
1293 
1294  if (!(start->d_flags & RT_DIR_COMB) || (start->d_flags & RT_DIR_REGION)) {
1295  bu_log("Cannot find path from %s to %s\n",
1296  start->d_namep, end->d_namep);
1297  db_free_full_path(path);
1298  bu_free((char *)path, "path");
1299  return 1;
1300  }
1301 
1302  if (rt_db_get_internal(&intern, start, dbip, NULL, resp) < 0) {
1303  db_free_full_path(path);
1304  bu_free((char *)path, "path");
1305  return 1;
1306  }
1307 
1308  comb = (struct rt_comb_internal *)intern.idb_ptr;
1309  rt_find_path(dbip, comb->tree, end, paths, &path, resp);
1310  rt_db_free_internal(&intern);
1311 
1312  return 0;
1313 }
1314 
1315 
1316 /**
1317  * This routine searches the provided path (in the form of a string)
1318  * for the specified object name.
1319  *
1320  * Returns:
1321  * 1 - the specified object name is somewhere along the path
1322  * 0 - the specified object name does not appear in this path
1323  */
1324 int
1325 obj_in_path(const char *path, const char *obj)
1326 {
1327  size_t obj_len=strlen(obj);
1328  const char *ptr;
1329 
1330  ptr = strstr(path, obj);
1331 
1332  while (ptr) {
1333  if (ptr == path) {
1334  /* obj may be first element in path */
1335  ptr += obj_len;
1336  if (*ptr == '\0' || *ptr == '/') {
1337  /* found object in path */
1338  return 1;
1339  }
1340  } else if (*(ptr-1) == '/') {
1341  ptr += obj_len;
1342  if (*ptr == '\0' || *ptr == '/') {
1343  /* found object in path */
1344  return 1;
1345  }
1346  } else {
1347  ptr++;
1348  }
1349 
1350  ptr = strstr(ptr, obj);
1351  }
1352 
1353  return 0;
1354 }
1355 
1356 
1357 HIDDEN int
1359  const struct db_full_path *pathp,
1360  const struct rt_comb_internal *comb,
1361  void *UNUSED(client_data))
1362 {
1363  if (tsp) {
1364  RT_CK_RTI(tsp->ts_rtip);
1365  RT_CK_RESOURCE(tsp->ts_resp);
1366  }
1367  if (pathp) RT_CK_FULL_PATH(pathp);
1368  if (comb) RT_CK_COMB(comb);
1369 
1370  /* Ignore "air" regions unless wanted */
1371  if (tsp) {
1372  if (tsp->ts_rtip->useair == 0 && tsp->ts_aircode != 0) {
1373  tsp->ts_rtip->rti_air_discards++;
1374  return -1; /* drop this region */
1375  }
1376  }
1377  return 0;
1378 }
1379 
1380 
1381 HIDDEN union tree *
1383  const struct db_full_path *pathp,
1384  union tree *tree,
1385  void *UNUSED(client_data))
1386 {
1387  if (tsp) {
1388  RT_CK_RTI(tsp->ts_rtip);
1389  RT_CK_RESOURCE(tsp->ts_resp);
1390  }
1391  if (pathp) RT_CK_FULL_PATH(pathp);
1392  if (tree) RT_CK_TREE(tree);
1393 
1394  return (union tree *)NULL;
1395 }
1396 
1397 
1398 HIDDEN union tree *
1400  const struct db_full_path *pathp,
1401  struct rt_db_internal *ip,
1402  void *client_data)
1403 {
1404  register struct soltab *stp;
1405  struct directory *dp;
1406  register matp_t mat;
1407  struct rt_i *rtip;
1408  struct bu_list *mid;
1409  struct rt_reprep_obj_list *objs=(struct rt_reprep_obj_list *)client_data;
1410 
1411  RT_CK_DBTS(tsp);
1412  RT_CK_DBI(tsp->ts_dbip);
1413  RT_CK_FULL_PATH(pathp);
1414  RT_CK_DB_INTERNAL(ip);
1415  rtip = tsp->ts_rtip;
1416  RT_CK_RTI(rtip);
1417  RT_CK_RESOURCE(tsp->ts_resp);
1418  dp = DB_FULL_PATH_CUR_DIR(pathp);
1419 
1420  if (!dp)
1421  return NULL;
1422 
1423  /* Determine if this matrix is an identity matrix */
1424 
1425  if (!bn_mat_is_equal(tsp->ts_mat, bn_mat_identity, &rtip->rti_tol)) {
1426  /* Not identity matrix */
1427  mat = (matp_t)tsp->ts_mat;
1428  } else {
1429  /* Identity matrix */
1430  mat = (matp_t)0;
1431  }
1432 
1433  /* find corresponding soltab structure */
1434  mid = BU_LIST_FIRST(bu_list, &dp->d_use_hd);
1435  while (mid != &dp->d_use_hd) {
1436  stp = BU_LIST_MAIN_PTR(soltab, mid, l2);
1437  RT_CK_SOLTAB(stp);
1438 
1439  mid = BU_LIST_PNEXT(bu_list, mid);
1440 
1441  if (((mat == (matp_t)0) && (stp->st_matp == (matp_t)0)) ||
1442  bn_mat_is_equal(mat, stp->st_matp, &rtip->rti_tol)) {
1443  if (stp->st_rtip == rtip) {
1444  long bit=stp->st_bit;
1445  struct region *rp;
1446  size_t i, j;
1447 
1448  /* found soltab for this instance */
1449 
1450  /* check all regions using this soltab add any that
1451  * are below an object to be unprepped to the
1452  * "unprep_regions" list
1453  */
1454  for (i=0; i<BU_PTBL_LEN(&stp->st_regions); i++) {
1455  rp = (struct region *)BU_PTBL_GET(&stp->st_regions, i);
1456  for (j=0; j<objs->nunprepped; j++) {
1457  if (obj_in_path(rp->reg_name, objs->unprepped[j])) {
1458  /* this region has an unprep object in its
1459  * path
1460  */
1461  bu_ptbl_ins_unique(&objs->unprep_regions, (long *)rp);
1462  bu_ptbl_rm(&stp->st_regions, (long *)rp);
1463  break;
1464  }
1465  }
1466  }
1467  if (stp->st_uses <= 1) {
1468  /* soltab structure will actually be freed */
1469  remove_from_bsp(stp, &rtip->rti_inf_box, &rtip->rti_tol);
1470  remove_from_bsp(stp, &rtip->rti_CutHead, &rtip->rti_tol);
1471  rtip->rti_Solids[bit] = (struct soltab *)NULL;
1472  }
1473  rt_free_soltab(stp);
1474  return (union tree *)NULL;
1475  }
1476  }
1477  }
1478 
1479  bu_log("ERROR: internal failure unprepping [%s]\n", dp->d_namep);
1480  return (union tree *)NULL;
1481 }
1482 
1483 
1484 /**
1485  * This routine "unpreps" the list of object names that appears in the
1486  * "unprepped" list of the "objs" structure.
1487  */
1488 int
1489 rt_unprep(struct rt_i *rtip, struct rt_reprep_obj_list *objs, struct resource *resp)
1490 {
1491  struct bu_ptbl unprep_regions;
1492  struct db_full_path *path;
1493  size_t i, j, k;
1494 
1495  rt_res_pieces_clean(resp, rtip);
1496 
1497  /* find all paths from top objects to objects being unprepped */
1498  bu_ptbl_init(&objs->paths, 5, "paths");
1499  for (i=0; i<objs->ntopobjs; i++) {
1500  struct directory *start, *end;
1501 
1502  start = db_lookup(rtip->rti_dbip, objs->topobjs[i], 1);
1503  if (start == RT_DIR_NULL) {
1504  for (k=0; k<BU_PTBL_LEN(&objs->paths); k++) {
1505  path = (struct db_full_path *)BU_PTBL_GET(&objs->paths, k);
1506  db_free_full_path(path);
1507  }
1508  bu_ptbl_free(&objs->paths);
1509  return 1;
1510  }
1511  for (j=0; j<objs->nunprepped; j++) {
1512  end = db_lookup(rtip->rti_dbip, objs->unprepped[j], 1);
1513  if (end == RT_DIR_NULL) {
1514  for (k=0; k<BU_PTBL_LEN(&objs->paths); k++) {
1515  path = (struct db_full_path *)BU_PTBL_GET(&objs->paths, k);
1516  db_free_full_path(path);
1517  }
1518  bu_ptbl_free(&objs->paths);
1519  return 1;
1520  }
1521  rt_find_paths(rtip->rti_dbip, start, end, &objs->paths, resp);
1522  }
1523  }
1524 
1525  if (BU_PTBL_LEN(&objs->paths) < 1) {
1526  bu_log("rt_unprep(): Failed to find any paths to objects to reprep!!\n");
1527  bu_ptbl_free(&objs->paths);
1528  }
1529 
1530  /* accumulate state along each path */
1531  objs->tsp = (struct db_tree_state **)bu_calloc(
1532  BU_PTBL_LEN(&objs->paths),
1533  sizeof(struct db_tree_state *),
1534  "objs->tsp");
1535 
1536  bu_ptbl_init(&objs->unprep_regions, 5, "unprep_regions");
1537 
1538  for (i=0; i<BU_PTBL_LEN(&objs->paths); i++) {
1539  struct db_full_path another_path;
1540  struct db_tree_state *tree_state;
1541  char *obj_name;
1542 
1543  BU_ALLOC(tree_state, struct db_tree_state);
1544 
1545  *tree_state = rt_initial_tree_state; /* struct copy */
1546  tree_state->ts_dbip = rtip->rti_dbip;
1547  tree_state->ts_resp = resp;
1548  tree_state->ts_rtip = rtip;
1549  tree_state->ts_tol = &rtip->rti_tol;
1550  objs->tsp[i] = tree_state;
1551 
1552  db_full_path_init(&another_path);
1553  path = (struct db_full_path *)BU_PTBL_GET(&objs->paths, i);
1554  if (db_follow_path(tree_state, &another_path, path, 1, 0)) {
1555  bu_log("rt_unprep(): db_follow_path failed!!\n");
1556  for (k=0; k<BU_PTBL_LEN(&objs->paths); k++) {
1557  if (objs->tsp[k]) {
1558  db_free_db_tree_state(objs->tsp[k]);
1559  bu_free((char *)objs->tsp[k], "tree_state");
1560  }
1561  path = (struct db_full_path *)BU_PTBL_GET(&objs->paths, k);
1562  db_free_full_path(path);
1563  }
1564  bu_ptbl_free(&objs->paths);
1565  bu_ptbl_free(&unprep_regions);
1566  return 1;
1567  }
1568  db_free_full_path(&another_path);
1569 
1570  /* walk tree starting from "unprepped" object, using the
1571  * appropriate tree_state. unprep solids and regions along
1572  * the way
1573  */
1574  obj_name = DB_FULL_PATH_CUR_DIR(path)->d_namep;
1575  if (!obj_name)
1576  return 1;
1577 
1578  if (db_walk_tree(rtip->rti_dbip, 1, (const char **)&obj_name, 1, tree_state,
1580  (void *)objs)) {
1581  bu_log("rt_unprep(): db_walk_tree failed!!!\n");
1582  for (k=0; k<BU_PTBL_LEN(&objs->paths); k++) {
1583  if (objs->tsp[k]) {
1584  db_free_db_tree_state(objs->tsp[k]);
1585  bu_free((char *)objs->tsp[k], "tree_state");
1586  }
1587  path = (struct db_full_path *)BU_PTBL_GET(&objs->paths, k);
1588  db_free_full_path(path);
1589  }
1590  bu_ptbl_free(&objs->paths);
1591  bu_ptbl_free(&unprep_regions);
1592  return 1;
1593  }
1594 
1595  db_free_db_tree_state(tree_state);
1596  bu_free((char *)tree_state, "tree_state");
1597  }
1598 
1599  /* eliminate regions to be unprepped */
1601  for (i=0; i<BU_PTBL_LEN(&objs->unprep_regions); i++) {
1602  struct region *rp;
1603 
1604  rp = (struct region *)BU_PTBL_GET(&objs->unprep_regions, i);
1605  BU_LIST_DEQUEUE(&rp->l);
1606  rtip->Regions[rp->reg_bit] = (struct region *)NULL;
1607 
1608  /* XXX db_free_tree(rp->reg_treetop, resp); */
1609  bu_free((void *)rp->reg_name, "region name str");
1610  rp->reg_name = (char *)0;
1611  if (rp->reg_mater.ma_shader) {
1612  bu_free((void *)rp->reg_mater.ma_shader, "ma_shader");
1613  rp->reg_mater.ma_shader = (char *)NULL;
1614  }
1615  bu_avs_free(&(rp->attr_values));
1616  bu_free((void *)rp, "struct region");
1617  }
1618 
1619  /* eliminate NULL region structures */
1620  objs->old_nregions = rtip->nregions;
1621  i = 0;
1622  while (i < rtip->nregions) {
1623  int nulls=0;
1624 
1625  while (i < rtip->nregions && !rtip->Regions[i]) {
1626  i++;
1627  nulls++;
1628  }
1629 
1630  if (nulls) {
1631  rtip->nregions -= nulls;
1632  for (j=i-nulls; j<rtip->nregions; j++) {
1633  rtip->Regions[j] = rtip->Regions[j+nulls];
1634  if (rtip->Regions[j]) {
1635  rtip->Regions[j]->reg_bit = j;
1636  }
1637  }
1638  nulls = 0;
1639  } else {
1640  i++;
1641  }
1642  }
1643 
1644  /* eliminate NULL soltabs */
1645  objs->old_nsolids = rtip->nsolids;
1646  objs->nsolids_unprepped = 0;
1647  i = 0;
1648  while (i < rtip->nsolids) {
1649  int nulls=0;
1650 
1651  while (i < rtip->nsolids && !rtip->rti_Solids[i]) {
1652  objs->nsolids_unprepped++;
1653  i++;
1654  nulls++;
1655  }
1656  if (nulls) {
1657  for (j=i-nulls; j+nulls<rtip->nsolids; j++) {
1658  rtip->rti_Solids[j] = rtip->rti_Solids[j+nulls];
1659  if (rtip->rti_Solids[j]) {
1660  rtip->rti_Solids[j]->st_bit = j;
1661  }
1662  }
1663  rtip->nsolids -= nulls;
1664  i -= nulls;
1665  } else {
1666  i++;
1667  }
1668  }
1669 
1670  return 0;
1671 }
1672 
1673 
1674 /**
1675  * This routine "re-preps" the list of objects specified in the
1676  *"unprepped" list of the "objs" structure. This structure must
1677  *previously have been passed to "rt_unprep"
1678  */
1679 int
1680 rt_reprep(struct rt_i *rtip, struct rt_reprep_obj_list *objs, struct resource *resp)
1681 {
1682  size_t i;
1683  char **argv;
1684  struct region *rp;
1685  struct soltab *stp;
1686  fastf_t old_min[3], old_max[3];
1687  size_t bitno;
1688 
1689  VMOVE(old_min, rtip->mdl_min);
1690  VMOVE(old_max, rtip->mdl_max);
1691 
1692  rtip->needprep = 1;
1693 
1694  argv = (char **)bu_calloc(BU_PTBL_LEN(&(objs->paths)), sizeof(char *), "argv");
1695  for (i=0; i<BU_PTBL_LEN(&(objs->paths)); i++) {
1696  argv[i] = db_path_to_string((const struct db_full_path *)BU_PTBL_GET(&(objs->paths), i));
1697  }
1698 
1699  rtip->rti_add_to_new_solids_list = 1;
1700  bu_ptbl_init(&rtip->rti_new_solids, 128, "rti_new_solids");
1701  if (rt_gettrees(rtip, BU_PTBL_LEN(&(objs->paths)), (const char **)argv, 1)) {
1702  return 1;
1703  }
1704  rtip->rti_add_to_new_solids_list = 0;
1705 
1706  for (i=0; i<BU_PTBL_LEN(&(objs->paths)); i++) {
1707  bu_free(argv[i], "argv[i]");
1708  }
1709  bu_free((char *)argv, "argv");
1710 
1711  rtip->needprep = 0;
1712 
1713  if (rtip->nregions > objs->old_nregions) {
1714  rtip->Regions = (struct region **)bu_realloc(rtip->Regions,
1715  rtip->nregions * sizeof(struct region *), "rtip->Regions");
1716  memset(rtip->Regions, 0, rtip->nregions);
1717  }
1718 
1719 
1720  bitno = 0;
1721  for (BU_LIST_FOR(rp, region, &(rtip->HeadRegion))) {
1722  rp->reg_bit = bitno;
1723  rtip->Regions[bitno] = rp;
1724  if (bitno >= objs->old_nregions - objs->nregions_unprepped) {
1725  point_t region_min, region_max;
1726 
1727  if (rt_bound_tree(rp->reg_treetop, region_min, region_max)) {
1728  bu_log("WARNING: Unable to compute bounding trees on [%s]\n", rp->reg_name);
1729  VSETALL(region_max, INFINITY);
1730  VSETALL(region_min, -INFINITY);
1731  }
1732  if (region_max[X] < INFINITY) {
1733  /* infinite regions are exempted from this */
1734  VMINMAX(rtip->mdl_min, rtip->mdl_max, region_min);
1735  VMINMAX(rtip->mdl_min, rtip->mdl_max, region_max);
1736  }
1737  rt_solid_bitfinder(rp->reg_treetop, rp, resp);
1738  }
1739  bitno++;
1740  }
1741 
1742  if (rtip->nsolids > objs->old_nsolids) {
1743  rtip->rti_Solids = (struct soltab **)bu_realloc(rtip->rti_Solids,
1744  rtip->nsolids * sizeof(struct soltab *),
1745  "rtip->rti_Solids");
1746  memset(rtip->rti_Solids, 0, rtip->nsolids * sizeof(struct soltab *));
1747  }
1748 
1749  bitno = 0;
1750  RT_VISIT_ALL_SOLTABS_START(stp, rtip) {
1751  stp->st_bit = bitno;
1752  rtip->rti_Solids[bitno] = stp;
1753  bitno++;
1754 
1756 
1757  for (i=0; i<BU_PTBL_LEN(&rtip->rti_new_solids); i++) {
1758  stp = (struct soltab *)BU_PTBL_GET(&rtip->rti_new_solids, i);
1759  if (stp->st_aradius >= INFINITY) {
1760  insert_in_bsp(stp, &rtip->rti_inf_box);
1761  } else {
1762  insert_in_bsp(stp, &rtip->rti_CutHead);
1763  }
1764  }
1765 
1766  bu_ptbl_free(&rtip->rti_new_solids);
1767 
1768  if (!VNEAR_EQUAL(rtip->mdl_min, old_min, SMALL_FASTF)
1769  || !VNEAR_EQUAL(rtip->mdl_max, old_max, SMALL_FASTF))
1770  {
1771  /* fill out BSP, it must completely fill the model BB */
1772  fastf_t bb[6];
1773 
1774  VSETALL(bb, INFINITY);
1775  VSETALL(&bb[3], -INFINITY);
1776  fill_out_bsp(rtip, &rtip->rti_CutHead, resp, bb);
1777  }
1778 
1779  if (BU_PTBL_LEN(&rtip->rti_resources)) {
1780  for (i=0; i<BU_PTBL_LEN(&rtip->rti_resources); i++) {
1781  struct resource *re;
1782 
1783  re = (struct resource *)BU_PTBL_GET(&rtip->rti_resources, i);
1784  if (re && rtip->rti_nsolids_with_pieces)
1785  rt_res_pieces_init(re, rtip);
1786  }
1787  } else if (rtip->rti_nsolids_with_pieces) {
1789  }
1790 
1791  return 0;
1792 }
1793 
1794 
1795 /** @} */
1796 
1797 /*
1798  * Local Variables:
1799  * mode: C
1800  * tab-width: 8
1801  * indent-tabs-mode: t
1802  * c-file-style: "stroustrup"
1803  * End:
1804  * ex: shiftwidth=4 tabstop=8
1805  */
void db_free_anim(struct db_i *dbip)
Definition: db_anim.c:223
int db_follow_path(struct db_tree_state *tsp, struct db_full_path *total_path, const struct db_full_path *new_path, int noisy, long pdepth)
Definition: db_tree.c:682
void rt_pr_soltab(const struct soltab *stp)
char * d_namep
pointer to name string
Definition: raytrace.h:859
struct bu_attribute_value_set attr_values
Attribute/value set.
Definition: raytrace.h:556
#define DEBUG_REGIONS
7 Print regions & boolean trees
Definition: raytrace.h:90
int reg_bit
constant index into Regions[]
Definition: raytrace.h:541
#define BU_LIST_FOR(p, structure, hp)
Definition: list.h:365
int rti_nsol_by_type[ID_MAX_SOLID+1]
Definition: raytrace.h:1803
Definition: raytrace.h:800
size_t nregions_unprepped
number of region structures eliminated by unprep
Definition: raytrace.h:1510
int rt_load_attrs(struct rt_i *rtip, char **attrs)
Definition: prep.c:1149
void bu_bitv_clear(struct bu_bitv *bv)
Definition: bitv.c:123
void db_add_node_to_full_path(struct db_full_path *pp, struct directory *dp)
Definition: db_fullpath.c:54
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
int rt_db_get_internal(struct rt_db_internal *ip, const struct directory *dp, const struct db_i *dbip, const mat_t mat, struct resource *resp)
Definition: dir.c:76
int rt_vlist_solid(struct bu_list *vhead, struct rt_i *rtip, const struct soltab *stp, struct resource *resp)
Definition: prep.c:503
const struct db_tree_state rt_initial_tree_state
Definition: globals.c:90
void rt_res_pieces_clean(struct resource *resp, struct rt_i *rtip)
Definition: shoot.c:72
#define RT_DBNHASH
hash table is an array of linked lists with this many array pointer elements (Memory use for 32-bit: ...
Definition: raytrace.h:755
fastf_t bn_min[3]
Definition: raytrace.h:694
struct bu_hist rti_hist_cellsize
occupancy of cut cells
Definition: raytrace.h:1806
int dbi_uses
PRIVATE: # of uses of this struct.
Definition: raytrace.h:818
double rti_radius
radius of model bounding sphere
Definition: raytrace.h:1773
void bu_avs_init_empty(struct bu_attribute_value_set *avp)
Definition: avs.c:36
int rt_unprep(struct rt_i *rtip, struct rt_reprep_obj_list *objs, struct resource *resp)
Definition: prep.c:1489
int rt_find_paths(struct db_i *dbip, struct directory *start, struct directory *end, struct bu_ptbl *paths, struct resource *resp)
Definition: prep.c:1275
int(* ft_plot)(struct bu_list *, struct rt_db_internal *, const struct rt_tess_tol *, const struct bn_tol *, const struct rt_view_info *)
Definition: raytrace.h:2096
Definition: list.h:118
struct bu_bitv * bu_bitv_new(size_t nbits)
Definition: bitv.c:91
#define BU_BITV_SHIFT
Definition: bitv.h:83
const struct directory * st_dp
Directory entry of solid.
Definition: raytrace.h:436
point_t mdl_min
min corner of model bounding RPP
Definition: raytrace.h:1769
void rt_plot_all_bboxes(FILE *fp, struct rt_i *rtip)
Definition: prep.c:452
void db_ck_directory(const struct db_i *dbip)
Definition: db_lookup.c:71
int rti_air_discards
of air regions discarded
Definition: raytrace.h:1805
void db_dup_full_path(struct db_full_path *newp, const struct db_full_path *oldp)
Definition: db_fullpath.c:87
#define RT_CK_RTI(_p)
Definition: raytrace.h:1833
#define OP_NOP
Leaf with no effect.
Definition: raytrace.h:1132
double dist
>= 0
Definition: tol.h:73
void rt_clean_resource_complete(struct rt_i *rtip, struct resource *resp)
Definition: prep.c:769
const mat_t bn_mat_identity
Matrix and vector functionality.
Definition: mat.c:46
#define BU_PTBL_FOR(ip, cast, ptbl)
Definition: ptbl.h:125
union tree ** re_boolstack
Stack for rt_booleval()
Definition: raytrace.h:1455
union tree * re_tree_hd
Head of free trees.
Definition: raytrace.h:1477
struct bu_list rtg_vlfree
head of bn_vlist freelist
Definition: raytrace.h:1698
int useair
1="air" regions are retained while prepping
Definition: raytrace.h:1756
void bu_ptbl_init(struct bu_ptbl *b, size_t len, const char *str)
Definition: ptbl.c:32
int rt_bound_tree(const union tree *tp, vect_t tree_min, vect_t tree_max)
void rt_grow_boolstack(struct resource *res)
struct bu_hist rti_hist_cutdepth
depth of cut tree
Definition: raytrace.h:1808
int rti_add_to_new_solids_list
Definition: raytrace.h:1821
#define VSETALL(a, s)
Definition: color.c:54
#define OP_XOR
Binary: L xor R, not both.
Definition: raytrace.h:1130
struct bu_list HeadRegion
ptr of list of regions in model
Definition: raytrace.h:1778
#define BU_PTBL_SET(ptbl, i, val)
Definition: ptbl.h:109
int bu_avs_add(struct bu_attribute_value_set *avp, const char *attribute, const char *value)
Definition: avs.c:78
#define RTI_MAGIC
Definition: magic.h:211
#define RT_CK_SEG(_p)
Definition: raytrace.h:377
void bu_semaphore_acquire(unsigned int i)
Definition: semaphore.c:180
size_t nbits
Definition: bitv.h:107
point_t rti_pmin
for plotting, min RPP
Definition: raytrace.h:1771
#define BU_LIST_IS_EMPTY(hp)
Definition: list.h:295
double dist_sq
dist * dist
Definition: tol.h:74
int rt_plot_solid(register FILE *fp, struct rt_i *rtip, const struct soltab *stp, struct resource *resp)
Definition: prep.c:543
struct directory * db_lookup(const struct db_i *, const char *name, int noisy)
Definition: db_lookup.c:153
Definition: raytrace.h:368
long d_uses
uses, from instancing
Definition: raytrace.h:866
size_t nregions
total # of regions participating
Definition: raytrace.h:1782
#define BU_LIST_IS_INITIALIZED(_hp)
Definition: list.h:175
#define BU_ASSERT_LONG(_lhs, _relation, _rhs)
Definition: defines.h:240
struct db_i * db_clone_dbi(struct db_i *dbip, long *client)
fastf_t bn_max[3]
Definition: raytrace.h:695
void db_free_db_tree_state(struct db_tree_state *tsp)
Definition: db_tree.c:76
#define DEBUG_PL_BOX
32 Plot(3) bounding boxes and cuts
Definition: raytrace.h:122
int db_version(struct db_i *dbip)
Definition: db5_scan.c:414
#define RT_CK_COMB(_p)
Definition: raytrace.h:955
int bu_ptbl_rm(struct bu_ptbl *b, const long *p)
void db_close_client(struct db_i *dbip, long *client)
void db_ck_tree(const union tree *tp)
Definition: db_tree.c:1255
#define BN_TOL_MAGIC
Definition: magic.h:74
void rt_vlist_to_uplot(FILE *fp, const struct bu_list *vhead)
Definition: vlist.c:446
#define SMALL_FASTF
Definition: defines.h:342
fastf_t st_aradius
Radius of APPROXIMATING sphere.
Definition: raytrace.h:433
void insert_in_bsp(struct soltab *stp, union cutter *cutp)
Definition: cut.c:2198
struct bu_list re_nmgfree
head of NMG hitmiss freelist
Definition: raytrace.h:1454
struct bu_list re_parthead
Head of freelist.
Definition: raytrace.h:1448
Header file for the BRL-CAD common definitions.
int bu_ptbl_ins_unique(struct bu_ptbl *b, long *p)
#define BU_CK_PTBL(_p)
Definition: ptbl.h:74
#define DB_FULL_PATH_CUR_DIR(_pp)
Definition: db_fullpath.h:51
void rt_regionfix(struct rt_i *rtip)
Definition: regionfix.c:36
matp_t st_matp
solid coords to model space, NULL=identity
Definition: raytrace.h:441
#define RT_DIR_REGION
region
Definition: raytrace.h:885
#define RT_FREE_VLIST(hd)
Definition: raytrace.h:1863
const char * reg_name
Identifying string.
Definition: raytrace.h:539
int bu_ptbl_ins(struct bu_ptbl *b, long *p)
void rt_prep_parallel(register struct rt_i *rtip, int ncpu)
Definition: prep.c:201
struct directory * d_forw
link to next dir entry
Definition: raytrace.h:864
int rti_nugrid_dimlimit
limit on nugrid dimensions
Definition: raytrace.h:1764
void db_full_path_init(struct db_full_path *pathp)
Definition: db_fullpath.c:40
#define RT_CHECK_SOLTAB(_p)
Definition: raytrace.h:452
union cutter rti_inf_box
List of infinite solids.
Definition: raytrace.h:1794
#define RT_CK_REGION(_p)
Definition: raytrace.h:559
HIDDEN union tree * unprep_leaf(struct db_tree_state *tsp, const struct db_full_path *pathp, struct rt_db_internal *ip, void *client_data)
Definition: prep.c:1399
void bu_ptbl_reset(struct bu_ptbl *b)
Definition: ptbl.c:49
int rti_space_partition
space partitioning method
Definition: raytrace.h:1763
void rt_free_soltab(struct soltab *stp)
Definition: tree.c:605
int ts_aircode
GIFT compat air code.
Definition: raytrace.h:1044
#define HIDDEN
Definition: common.h:86
int rt_del_regtree(struct rt_i *rtip, register struct region *delregp, struct resource *resp)
Definition: prep.c:1038
union tree * tb_left
Definition: raytrace.h:1149
struct soltab * tu_stp
Definition: raytrace.h:1156
struct bu_ptbl paths
list of all paths from topobjs to unprepped objects
Definition: raytrace.h:1504
struct region ** Regions
ptrs to regions [reg_bit]
Definition: raytrace.h:1777
HIDDEN int unprep_reg_start(struct db_tree_state *tsp, const struct db_full_path *pathp, const struct rt_comb_internal *comb, void *client_data)
Definition: prep.c:1358
Definition: ptbl.h:62
struct bu_bitv * rt_get_solidbitv(size_t nbits, struct resource *resp)
Definition: prep.c:828
const char * bu_avs_get(const struct bu_attribute_value_set *avp, const char *attribute)
Definition: avs.c:172
char ** topobjs
list of the above object names
Definition: raytrace.h:1499
double rel
rel dist tol
Definition: raytrace.h:181
void fill_out_bsp(struct rt_i *rtip, union cutter *cutp, struct resource *resp, fastf_t bb[6])
Definition: cut.c:2296
long st_bit
solids bit vector index (const)
Definition: raytrace.h:439
struct bu_ptbl re_seg_blocks
Table of malloc'ed blocks of segs.
Definition: raytrace.h:1444
size_t nunprepped
number of objects to be unprepped and re-prepped
Definition: raytrace.h:1500
int bn_mat_is_equal(const mat_t a, const mat_t b, const struct bn_tol *tol)
Definition: mat.c:925
#define OP_SUBTRACT
Binary: L subtract R.
Definition: raytrace.h:1129
uint32_t re_magic
Magic number.
Definition: raytrace.h:1441
Definition: color.c:49
struct bu_ptbl pt_seglist
all segs in this partition
Definition: raytrace.h:584
void * memset(void *s, int c, size_t n)
#define OP_INTERSECT
Binary: L intersect R.
Definition: raytrace.h:1128
struct resource rt_uniresource
default. Defined in librt/globals.c
Definition: globals.c:41
void bu_pr_ptbl(const char *title, const struct bu_ptbl *tbl, int verbose)
Definition: ptbl.c:241
#define RT_G_DEBUG
Definition: raytrace.h:1718
#define RT_PART_NUBSPT
Definition: raytrace.h:1835
#define OP_DB_LEAF
Leaf of combination, db fmt.
Definition: raytrace.h:1139
#define RESOURCE_MAGIC
Definition: magic.h:210
double rti_nu_gfactor
constant in numcells computation
Definition: raytrace.h:1812
struct bound_rpp * st_piece_rpps
bounding RPP of each piece of this solid
Definition: raytrace.h:446
#define RT_CK_DB_INTERNAL(_p)
Definition: raytrace.h:207
struct bu_ptbl rti_new_solids
Definition: raytrace.h:1822
struct rt_i * rt_new_rti(struct db_i *dbip)
Definition: prep.c:58
struct bu_list l
Definition: bitv.h:106
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
void * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
#define RT_CK_DIR(_dp)
Definition: raytrace.h:876
char ** unprepped
list of the above objects
Definition: raytrace.h:1501
void rt_clean_resource(struct rt_i *rtip, struct resource *resp)
Definition: prep.c:810
size_t rti_nsolids_with_pieces
solids using pieces
Definition: raytrace.h:1819
union cutter rti_CutHead
Head of cut tree.
Definition: raytrace.h:1793
void rt_ck(struct rt_i *rtip)
struct db_i * ts_dbip
Definition: raytrace.h:1040
#define RT_CHECK_RTI(_p)
Definition: raytrace.h:1832
#define BU_PTBL_GET(ptbl, i)
Definition: ptbl.h:108
void rt_pr_region(const struct region *rp)
void pdv_3space(register FILE *plotfp, const fastf_t *min, const fastf_t *max)
Definition: plot3.c:560
#define TREE_NULL
Definition: raytrace.h:1181
void db_free_full_path(struct db_full_path *pp)
Definition: db_fullpath.c:473
int rti_maxsol_by_type
Definition: raytrace.h:1804
mat_t ts_mat
transform matrix
Definition: raytrace.h:1050
void db_free_tree(union tree *tp, struct resource *resp)
Definition: db_tree.c:1296
void rt_cut_clean(struct rt_i *rtip)
Definition: cut.c:2036
void remove_from_bsp(struct soltab *stp, union cutter *cutp, struct bn_tol *tol)
Definition: cut.c:2116
point_t st_max
max X, Y, Z of bounding RPP
Definition: raytrace.h:438
void rt_prep(register struct rt_i *rtip)
Definition: prep.c:440
char * ma_shader
shader name & parms
Definition: raytrace.h:527
char * tl_name
Name of this leaf (bu_strdup'ed)
Definition: raytrace.h:1174
void rt_clean_resource_basic(struct rt_i *rtip, struct resource *resp)
Definition: prep.c:664
struct bu_ptbl unprep_regions
list of region structures that will be "unprepped"
Definition: raytrace.h:1506
#define BU_LIST_PNEXT(structure, p)
Definition: list.h:422
size_t nsolids_unprepped
number of soltab structures eliminated by unprep
Definition: raytrace.h:1509
struct tree::tree_node tr_b
struct bu_list l
Definition: ptbl.h:63
char ft_name[17]
Definition: raytrace.h:2043
void * bu_realloc(void *ptr, size_t siz, const char *str)
#define UNUSED(parameter)
Definition: common.h:239
#define OP_GUARD
Unary: not L, or else!
Definition: raytrace.h:1135
#define NMG_CK_HITMISS(hm)
Definition: raytrace.h:2356
#define BU_PTBL_MAGIC
Definition: magic.h:59
char * db_path_to_string(const struct db_full_path *pp)
Definition: db_fullpath.c:191
struct resource * ts_resp
Per-CPU data.
Definition: raytrace.h:1074
struct bu_hist rti_hist_cell_pieces
solid pieces per cell
Definition: raytrace.h:1807
struct bu_list d_use_hd
heads list of uses (struct soltab l2)
Definition: raytrace.h:872
struct bu_list re_region_ptbl
head of freelist
Definition: raytrace.h:1453
uint32_t magic
Magic # for mem id/check.
Definition: list.h:119
#define BU_LIST_WHILE(p, structure, hp)
Definition: list.h:410
struct bu_ptbl re_directory_blocks
Table of malloc'ed blocks.
Definition: raytrace.h:1482
struct soltab ** rti_Solids
ptrs to soltab [st_bit]
Definition: raytrace.h:1809
void rt_cut_it(struct rt_i *rtip, int ncpu)
struct bu_ptbl st_regions
ptrs to regions using this solid (const)
Definition: raytrace.h:440
int rt_reprep(struct rt_i *rtip, struct rt_reprep_obj_list *objs, struct resource *resp)
Definition: prep.c:1680
#define BU_LIST_MAIN_PTR(_type, _ptr2, _name2)
Definition: list.h:470
void bu_semaphore_release(unsigned int i)
Definition: semaphore.c:218
int obj_in_path(const char *path, const char *obj)
Definition: prep.c:1325
void pl_color(register FILE *plotfp, int r, int g, int b)
Definition: plot3.c:325
#define BU_PTBL_LEN(ptbl)
Definition: ptbl.h:107
size_t blen
Definition: ptbl.h:65
void bu_ptbl_free(struct bu_ptbl *b)
Definition: ptbl.c:226
#define MAX_PSW
Definition: parallel.h:48
struct bn_tol rti_tol
Math tolerances for this model.
Definition: raytrace.h:1765
void rt_plot_all_solids(FILE *fp, struct rt_i *rtip, struct resource *resp)
Definition: prep.c:470
float ma_color[3]
explicit color: 0..1
Definition: raytrace.h:522
#define RT_CK_DBI(_p)
Definition: raytrace.h:829
void rt_init_resource(struct resource *resp, int cpu_num, struct rt_i *rtip)
Definition: prep.c:585
#define RT_CK_FULL_PATH(_p)
Definition: db_fullpath.h:59
double perp
nearly 0
Definition: tol.h:75
uint32_t magic
Definition: raytrace.h:179
uint32_t rti_magic
magic # for integrity check
Definition: raytrace.h:1754
struct tree::tree_db_leaf tr_l
struct mater_info reg_mater
Real material information.
Definition: raytrace.h:546
union tree * tb_right
Definition: raytrace.h:1150
#define CUT_MAXIMUM
Definition: raytrace.h:721
#define BU_LIST_INIT(_hp)
Definition: list.h:148
void * idb_ptr
Definition: raytrace.h:195
#define RT_VISIT_ALL_SOLTABS_END
Definition: raytrace.h:1850
void rt_clean(register struct rt_i *rtip)
Definition: prep.c:868
size_t ntopobjs
number of objects in the original call to gettrees
Definition: raytrace.h:1498
point_t st_min
min X, Y, Z of bounding RPP
Definition: raytrace.h:437
int rti_ncut_by_type[CUT_MAXIMUM+1]
number of cuts by type
Definition: raytrace.h:1799
struct bu_list re_solid_bitv
head of freelist
Definition: raytrace.h:1452
#define RT_DIR_COMB
combination
Definition: raytrace.h:884
uint32_t magic
Definition: tol.h:72
struct directory * dbi_Head[RT_DBNHASH]
Definition: raytrace.h:814
#define DEBUG_DB
5 Database debugging
Definition: raytrace.h:88
const struct rt_functab OBJ[]
Definition: table.c:159
#define RT_CK_RESOURCE(_p)
Definition: raytrace.h:1490
#define BU_PTBL_END(ptbl)
Definition: ptbl.h:106
#define BU_ASSERT_PTR(_lhs, _relation, _rhs)
Definition: defines.h:227
#define RT_VISIT_ALL_SOLTABS_START(_s, _rti)
Definition: raytrace.h:1845
#define RT_CK_DBTS(_p)
Definition: raytrace.h:1084
struct db_i * rti_dbip
prt to Database instance struct
Definition: raytrace.h:1774
HIDDEN union tree * unprep_reg_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *tree, void *client_data)
Definition: prep.c:1382
size_t nsolids
total # of solids participating
Definition: raytrace.h:1783
struct directory * re_directory_hd
Definition: raytrace.h:1481
point_t mdl_max
max corner of model bounding RPP
Definition: raytrace.h:1770
#define RT_CK_PT(_p)
Definition: raytrace.h:589
union tree * tree
Leading to tree_db_leaf leaves.
Definition: raytrace.h:938
double abs
absolute dist tol
Definition: raytrace.h:180
#define RT_CK_SOLTAB(_p)
Definition: raytrace.h:453
#define RT_NU_GFACTOR_DEFAULT
see rt_cut_it() for a description of this
Definition: raytrace.h:1826
struct bu_list rti_solidheads[RT_DBNHASH]
active solid lists
Definition: raytrace.h:1810
#define RT_DIR_NULL
Definition: raytrace.h:875
#define LOOKUP_NOISY
Definition: raytrace.h:892
#define REGION_NULL
Definition: raytrace.h:558
int bn_type
Definition: raytrace.h:693
long re_boolslen
elements in re_boolstack[]
Definition: raytrace.h:1456
void rt_free_rti(struct rt_i *rtip)
Definition: prep.c:156
size_t old_nsolids
rtip->nsolids before unprep
Definition: raytrace.h:1507
void bu_hist_free(struct bu_hist *histp)
Definition: hist.c:32
union tree * reg_treetop
Pointer to boolean tree.
Definition: raytrace.h:540
struct rt_i * ts_rtip
Helper for rt_gettrees()
Definition: raytrace.h:1073
uint32_t debug
!0 for debug, see librt/debug.h
Definition: raytrace.h:1695
struct rt_tess_tol rti_ttol
Tessellation tolerance defaults.
Definition: raytrace.h:1766
Definition: color.c:51
#define BU_LIST_NULL
Definition: list.h:124
double norm
normal tol
Definition: raytrace.h:182
struct boxnode bn
Definition: raytrace.h:726
int re_cpu
processor number, for ID
Definition: raytrace.h:1442
#define bn_rand_init(_p, _seed)
Definition: rand.h:110
int rt_gettrees(struct rt_i *rtip, int argc, const char **argv, int ncpus)
Definition: tree.c:888
struct rt_i * st_rtip
"up" pointer to rt_i
Definition: raytrace.h:429
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
#define DEBUG_PL_SOLIDS
31 plot all solids
Definition: raytrace.h:121
long st_uses
Usage count, for instanced solids.
Definition: raytrace.h:430
#define SOLTAB_NULL
backwards compat
Definition: raytrace.h:450
#define RT_CK_TREE(_p)
Definition: raytrace.h:1182
#define RT_TESS_TOL_MAGIC
Definition: magic.h:170
#define OP_SOLID
Leaf: tr_stp -> solid.
Definition: raytrace.h:1126
struct bu_ptbl rti_resources
list of 'struct resource's encountered
Definition: raytrace.h:1811
void rt_optim_tree(union tree *tp, struct resource *resp)
Definition: tree.c:1008
int db_walk_tree(struct db_i *dbip, int argc, const char **argv, int ncpu, const struct db_tree_state *init_state, int(*reg_start_func)(struct db_tree_state *, const struct db_full_path *, const struct rt_comb_internal *, void *client_data), union tree *(*reg_end_func)(struct db_tree_state *, const struct db_full_path *, union tree *, void *client_data), union tree *(*leaf_func)(struct db_tree_state *, const struct db_full_path *, struct rt_db_internal *, void *client_data), void *client_data)
size_t old_nregions
rtip->nregions before unprep
Definition: raytrace.h:1508
int st_id
Solid ident.
Definition: raytrace.h:431
float * re_randptr
ptr into random number table
Definition: raytrace.h:1457
void pdv_3box(register FILE *plotfp, const fastf_t *a, const fastf_t *b)
Definition: plot3.c:688
#define BU_LIST_DEQUEUE(cur)
Definition: list.h:209
struct bu_list * forw
"forward", "next"
Definition: list.h:120
#define BU_LIST_MAGIC_EQUAL(_l, _magic)
Definition: list.h:135
#define CUT_BOXNODE
Definition: raytrace.h:719
#define BU_LIST_HEAD_MAGIC
Definition: magic.h:56
Definition: bitv.h:105
HIDDEN void rt_solid_bitfinder(register union tree *treep, struct region *regp, struct resource *resp)
Definition: prep.c:1065
#define ID_MAX_SOLID
Maximum defined ID_xxx for solids.
Definition: raytrace.h:494
int db5_get_attributes(const struct db_i *dbip, struct bu_attribute_value_set *avs, const struct directory *dp)
Definition: db5_io.c:1027
int d_flags
flags
Definition: raytrace.h:869
void bu_bomb(const char *str) _BU_ATTR_NORETURN
Definition: bomb.c:91
struct bu_list re_seg
Head of segment freelist.
Definition: raytrace.h:1443
const struct bn_tol * ts_tol
Math tolerance.
Definition: raytrace.h:1071
char * dbi_filename
file name
Definition: raytrace.h:805
double fastf_t
Definition: defines.h:300
#define OP_UNION
Binary: L union R.
Definition: raytrace.h:1127
#define BU_CK_BITV(_bp)
Definition: bitv.h:116
struct db_tree_state ** tsp
tree state used by tree walker in "reprep" routines
Definition: raytrace.h:1505
#define RT_SEM_RESULTS
Definition: raytrace.h:1732
void bu_avs_free(struct bu_attribute_value_set *avp)
Definition: avs.c:235
#define DEBUG_SOLIDS
6 Print prep'ed solids
Definition: raytrace.h:89
#define OP_NOT
Unary: not L.
Definition: raytrace.h:1134
void * Orca_hash_tbl
Hash table in matrices for ORCA.
Definition: raytrace.h:1779
struct bu_list l
magic # and doubly linked list
Definition: raytrace.h:538
struct tree::tree_leaf tr_a
double para
nearly 1
Definition: tol.h:76
point_t rti_pmax
for plotting, max RPP
Definition: raytrace.h:1772
void rt_db_free_internal(struct rt_db_internal *ip)
Definition: dir.c:216
struct soltab ** rti_sol_by_type[ID_MAX_SOLID+1]
Definition: raytrace.h:1802
int needprep
needs rt_prep
Definition: raytrace.h:1776
Definition: color.c:50
#define BU_LIST_FIRST(structure, hp)
Definition: list.h:312
void rt_res_pieces_init(struct resource *resp, struct rt_i *rtip)
Definition: shoot.c:46
void rt_fr_cut(struct rt_i *rtip, union cutter *cutp)
char * rti_treetop
bu_strduped, for rt_submodel rti's only
Definition: raytrace.h:1816
struct bu_ptbl delete_regs
list of region pointers to delete after light_init()
Definition: raytrace.h:1780
struct rt_g RTG
Definition: globals.c:39