BRL-CAD
bundle.c
Go to the documentation of this file.
1 /* B U N D L E . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1985-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 librt */
21 /** @{ */
22 /** @file librt/bundle.c
23  *
24  * NOTE: This is experimental code right now.
25  *
26  */
27 /** @} */
28 
29 #include "common.h"
30 
31 #include <string.h>
32 #include <math.h>
33 #include "bio.h"
34 
35 #include "vmath.h"
36 
37 #include "bn.h"
38 #include "raytrace.h"
39 
40 #include "librt_private.h"
41 
42 
43 /**
44  * Note that the direction vector r_dir must have unit length; this is
45  * mandatory, and is not ordinarily checked, in the name of
46  * efficiency.
47  *
48  * Input: Pointer to an application structure, with these mandatory
49  * fields:
50  *
51  * a_ray.r_pt Starting point of ray to be fired
52  * a_ray.r_dir UNIT VECTOR with direction to fire in (dir cosines)
53  * a_hit Routine to call when something is hit
54  * a_miss Routine to call when ray misses everything
55  *
56  * Calls user's a_miss() or a_hit() routine as appropriate. Passes
57  * a_hit() routine list of partitions, with only hit_dist fields
58  * valid. Normal computation deferred to user code, to avoid needless
59  * computation here.
60  *
61  * Formal Return: whatever the application function returns (an int).
62  *
63  * NOTE: The application functions may call rt_shootray() recursively.
64  * Thus, none of the local variables may be static.
65  *
66  * To prevent having to lock the statistics variables in a PARALLEL
67  * environment, all the statistics variables have been moved into the
68  * 'resource' structure, which is allocated per-CPU.
69  *
70  * XXX maybe parameter with NORM, UV, CURVE bits?
71  */
72 int
73 rt_shootray_bundle(register struct application *ap, struct xray *rays, int nrays)
74 {
75  struct rt_shootray_status ss;
76  struct seg new_segs; /* from solid intersections */
77  struct seg waiting_segs; /* awaiting rt_boolweave() */
78  struct seg finished_segs; /* processed by rt_boolweave() */
79  fastf_t last_bool_start;
80  struct bu_bitv *solidbits; /* bits for all solids shot so far */
81  struct bu_ptbl *regionbits; /* table of all involved regions */
82  const char *status;
83  struct partition InitialPart; /* Head of Initial Partitions */
84  struct partition FinalPart; /* Head of Final Partitions */
85  struct soltab **stpp;
86  register const union cutter *cutp;
87  struct resource *resp;
88  struct rt_i *rtip;
89  const int debug_shoot = RT_G_DEBUG & DEBUG_SHOOT;
90 
91  memset(&ss, 0, sizeof(struct rt_shootray_status));
92 
93  RT_AP_CHECK(ap);
94  if (ap->a_magic) {
95  RT_CK_AP(ap);
96  } else {
97  ap->a_magic = RT_AP_MAGIC;
98  }
99  if (ap->a_ray.magic) {
100  RT_CK_RAY(&(ap->a_ray));
101  } else {
102  ap->a_ray.magic = RT_RAY_MAGIC;
103  }
104  if (!ap->a_resource) {
105  ap->a_resource = &rt_uniresource;
106  }
108  ss.ap = ap;
109  rtip = ap->a_rt_i;
110  RT_CK_RTI(rtip);
111  resp = ap->a_resource;
112  RT_CK_RESOURCE(resp);
113  ss.resp = resp;
114 
117  bu_log("\n**********shootray_bundle cpu=%d %d, %d lvl=%d (%s)\n",
118  resp->re_cpu,
119  ap->a_x, ap->a_y,
120  ap->a_level,
121  ap->a_purpose != (char *)0 ? ap->a_purpose : "?");
122  bu_log("Pnt (%g, %g, %g) a_onehit=%d\n",
123  V3ARGS(ap->a_ray.r_pt),
124  ap->a_onehit);
125  VPRINT("Dir", ap->a_ray.r_dir);
126  }
127 
128  if (rtip->needprep)
129  rt_prep(rtip);
130 
131  InitialPart.pt_forw = InitialPart.pt_back = &InitialPart;
132  InitialPart.pt_magic = PT_HD_MAGIC;
133  FinalPart.pt_forw = FinalPart.pt_back = &FinalPart;
134  FinalPart.pt_magic = PT_HD_MAGIC;
135  ap->a_Final_Part_hdp = &FinalPart;
136 
137  BU_LIST_INIT(&new_segs.l);
138  BU_LIST_INIT(&waiting_segs.l);
139  BU_LIST_INIT(&finished_segs.l);
140  ap->a_finished_segs_hdp = &finished_segs;
141 
142  if (!BU_LIST_IS_INITIALIZED(&resp->re_parthead)) {
143  /* XXX This shouldn't happen any more */
144  bu_log("rt_shootray_bundle() resp=%p uninitialized, fixing it\n", (void *)resp);
145  /*
146  * We've been handed a mostly un-initialized resource struct,
147  * with only a magic number and a cpu number filled in.
148  * Init it and add it to the table.
149  * This is how application-provided resource structures
150  * are remembered for later cleanup by the library.
151  */
152  rt_init_resource(resp, resp->re_cpu, rtip);
153 
154  /* Ensure that this CPU's resource structure is registered */
155  BU_ASSERT_PTR(BU_PTBL_GET(&rtip->rti_resources, resp->re_cpu), !=, NULL);
156  }
157 
158  solidbits = rt_get_solidbitv(rtip->nsolids, resp);
159 
160  if (BU_LIST_IS_EMPTY(&resp->re_region_ptbl)) {
161  BU_ALLOC(regionbits, struct bu_ptbl);
162  bu_ptbl_init(regionbits, 7, "rt_shootray_bundle() regionbits ptbl");
163  } else {
164  regionbits = BU_LIST_FIRST(bu_ptbl, &resp->re_region_ptbl);
165  BU_LIST_DEQUEUE(&regionbits->l);
166  BU_CK_PTBL(regionbits);
167  }
168 
169  /* Verify that direction vector has unit length */
170  if (RT_G_DEBUG) {
171  fastf_t f, diff;
172  f = MAGSQ(ap->a_ray.r_dir);
173  if (NEAR_ZERO(f, 0.0001)) {
174  bu_bomb("rt_shootray_bundle: zero length dir vector\n");
175  }
176  diff = f - 1;
177  if (!NEAR_ZERO(diff, 0.0001)) {
178  bu_log("rt_shootray_bundle: non-unit dir vect (x%d y%d lvl%d)\n",
179  ap->a_x, ap->a_y, ap->a_level);
180  f = 1/f;
181  VSCALE(ap->a_ray.r_dir, ap->a_ray.r_dir, f);
182  }
183  }
184 
185  /* Compute the inverse of the direction cosines */
186  if (ap->a_ray.r_dir[X] < -SQRT_SMALL_FASTF) {
187  ss.abs_inv_dir[X] = -(ss.inv_dir[X]=1.0/ap->a_ray.r_dir[X]);
188  ss.rstep[X] = -1;
189  } else if (ap->a_ray.r_dir[X] > SQRT_SMALL_FASTF) {
190  ss.abs_inv_dir[X] = (ss.inv_dir[X]=1.0/ap->a_ray.r_dir[X]);
191  ss.rstep[X] = 1;
192  } else {
193  ap->a_ray.r_dir[X] = 0.0;
194  ss.abs_inv_dir[X] = ss.inv_dir[X] = INFINITY;
195  ss.rstep[X] = 0;
196  }
197  if (ap->a_ray.r_dir[Y] < -SQRT_SMALL_FASTF) {
198  ss.abs_inv_dir[Y] = -(ss.inv_dir[Y]=1.0/ap->a_ray.r_dir[Y]);
199  ss.rstep[Y] = -1;
200  } else if (ap->a_ray.r_dir[Y] > SQRT_SMALL_FASTF) {
201  ss.abs_inv_dir[Y] = (ss.inv_dir[Y]=1.0/ap->a_ray.r_dir[Y]);
202  ss.rstep[Y] = 1;
203  } else {
204  ap->a_ray.r_dir[Y] = 0.0;
205  ss.abs_inv_dir[Y] = ss.inv_dir[Y] = INFINITY;
206  ss.rstep[Y] = 0;
207  }
208  if (ap->a_ray.r_dir[Z] < -SQRT_SMALL_FASTF) {
209  ss.abs_inv_dir[Z] = -(ss.inv_dir[Z]=1.0/ap->a_ray.r_dir[Z]);
210  ss.rstep[Z] = -1;
211  } else if (ap->a_ray.r_dir[Z] > SQRT_SMALL_FASTF) {
212  ss.abs_inv_dir[Z] = (ss.inv_dir[Z]=1.0/ap->a_ray.r_dir[Z]);
213  ss.rstep[Z] = 1;
214  } else {
215  ap->a_ray.r_dir[Z] = 0.0;
216  ss.abs_inv_dir[Z] = ss.inv_dir[Z] = INFINITY;
217  ss.rstep[Z] = 0;
218  }
219 
220  /*
221  * If ray does not enter the model RPP, skip on.
222  * If ray ends exactly at the model RPP, trace it.
223  */
224  if (!rt_in_rpp(&ap->a_ray, ss.inv_dir, rtip->mdl_min, rtip->mdl_max) ||
225  ap->a_ray.r_max < 0.0) {
226  resp->re_nmiss_model++;
227  if (ap->a_miss)
228  ap->a_return = ap->a_miss(ap);
229  else
230  ap->a_return = 0;
231  status = "MISS model";
232  goto out;
233  }
234 
235  /*
236  * The interesting part of the ray starts at distance 0. If the
237  * ray enters the model at a negative distance, (i.e., the ray
238  * starts within the model RPP), we only look at little bit behind
239  * (BACKING_DIST) to see if we are just coming out of something,
240  * but never further back than the intersection with the model
241  * RPP. If the ray enters the model at a positive distance, we
242  * always start there. It is vital that we never pick a start
243  * point outside the model RPP, or the space partitioning tree
244  * will pick the wrong box and the ray will miss it.
245  *
246  * BACKING_DIST should probably be determined by floating point
247  * noise factor due to model RPP size -vs- number of bits of
248  * floating point mantissa significance, rather than a constant,
249  * but that is too hideous to think about here. Also note that
250  * applications that really depend on knowing what region they are
251  * leaving from should probably back their own start-point up,
252  * rather than depending on it here, but it isn't much trouble
253  * here.
254  */
255  ss.box_start = ss.model_start = ap->a_ray.r_min;
256  ss.box_end = ss.model_end = ap->a_ray.r_max;
257 
258  if (ss.box_start < BACKING_DIST)
259  ss.box_start = BACKING_DIST; /* Only look a little bit behind */
260 
261  ss.lastcut = CUTTER_NULL;
262  ss.old_status = (struct rt_shootray_status *)NULL;
263  ss.curcut = &ap->a_rt_i->rti_CutHead;
264  if (ss.curcut->cut_type == CUT_NUGRIDNODE) {
265  ss.lastcell = CUTTER_NULL;
266  VSET(ss.curmin, ss.curcut->nugn.nu_axis[X][0].nu_spos,
267  ss.curcut->nugn.nu_axis[Y][0].nu_spos,
268  ss.curcut->nugn.nu_axis[Z][0].nu_spos);
272  } else if (ss.curcut->cut_type == CUT_CUTNODE ||
273  ss.curcut->cut_type == CUT_BOXNODE) {
274  ss.lastcell = ss.curcut;
275  VMOVE(ss.curmin, rtip->mdl_min);
276  VMOVE(ss.curmax, rtip->mdl_max);
277  }
278 
279  last_bool_start = BACKING_DIST;
280  ss.newray = ap->a_ray; /* struct copy */
281  ss.odist_corr = ss.obox_start = ss.obox_end = -99;
282  ss.dist_corr = 0.0;
283 
284  /*
285  * While the ray remains inside model space, push from box to box
286  * until ray emerges from model space again (or first hit is
287  * found, if user is impatient). It is vitally important to
288  * always stay within the model RPP, or the space partitioning tree
289  * will pick wrong boxes & miss them.
290  */
291  while ((cutp = rt_advance_to_next_cell(&ss)) != CUTTER_NULL) {
292  if (debug_shoot) {
293  rt_pr_cut(cutp, 0);
294  }
295 
296  if (cutp->bn.bn_len <= 0) {
297  /* Push ray onwards to next box */
298  ss.box_start = ss.box_end;
299  resp->re_nempty_cells++;
300  continue;
301  }
302 
303  /* Consider all objects within the box */
304  stpp = &(cutp->bn.bn_list[cutp->bn.bn_len-1]);
305  for (; stpp >= cutp->bn.bn_list; stpp--) {
306  register struct soltab *stp = *stpp;
307  int ray;
308 
309  if (BU_BITTEST(solidbits, stp->st_bit)) {
310  resp->re_ndup++;
311  continue; /* already shot */
312  }
313 
314  /* Shoot all the rays in the bundle through this solid */
315  /* XXX open issue: entering neighboring cells too? */
316  BU_BITSET(solidbits, stp->st_bit);
317 
318  for (ray=0; ray < nrays; ray++) {
319  struct xray ss2_newray;
320  int ret;
321 
322  /* Be compatible with the ss backing distance stuff */
323  VMOVE(ss2_newray.r_dir, rays[ray].r_dir);
324  VJOIN1(ss2_newray.r_pt, rays[ray].r_pt, ss.dist_corr, ss2_newray.r_dir);
325 
326  /* Check against bounding RPP, if desired by solid */
327  if (OBJ[stp->st_id].ft_use_rpp) {
328  if (!rt_in_rpp(&ss2_newray, ss.inv_dir,
329  stp->st_min, stp->st_max)) {
330  if (debug_shoot)bu_log("rpp miss %s by ray %d\n", stp->st_name, ray);
331  resp->re_prune_solrpp++;
332  continue; /* MISS */
333  }
334  if (ss.dist_corr + ss2_newray.r_max < BACKING_DIST) {
335  if (debug_shoot)bu_log("rpp skip %s, dist_corr=%g, r_max=%g, by ray %d\n", stp->st_name, ss.dist_corr, ss2_newray.r_max, ray);
336  resp->re_prune_solrpp++;
337  continue; /* MISS */
338  }
339  }
340 
341  if (debug_shoot)bu_log("shooting %s with ray %d\n", stp->st_name, ray);
342  resp->re_shots++;
343 
344  BU_LIST_INIT(&(new_segs.l));
345 
346  ret = -1;
347  if (OBJ[stp->st_id].ft_shot) {
348  ret = OBJ[stp->st_id].ft_shot(stp, &ss2_newray, ap, &new_segs);
349  }
350  if (ret <= 0) {
351  resp->re_shot_miss++;
352  continue; /* MISS */
353  }
354 
355  /* Add seg chain to list awaiting rt_boolweave() */
356  {
357  register struct seg *s2;
358  while (BU_LIST_WHILE(s2, seg, &(new_segs.l))) {
359  BU_LIST_DEQUEUE(&(s2->l));
360  /* Restore to original distance */
361  s2->seg_in.hit_dist += ss.dist_corr;
362  s2->seg_out.hit_dist += ss.dist_corr;
363  s2->seg_in.hit_rayp = s2->seg_out.hit_rayp = &rays[ray];
364  BU_LIST_INSERT(&(waiting_segs.l), &(s2->l));
365  }
366  }
367  resp->re_shot_hit++;
368  break; /* HIT */
369  }
370  }
372  rt_plot_cell(cutp, &ss, &(waiting_segs.l), rtip);
373 
374  /*
375  * If a_onehit == 0 and a_ray_length <= 0, then the ray
376  * is traced to +infinity.
377  *
378  * If a_onehit != 0, then it indicates how many hit points
379  * (which are greater than the ray start point of 0.0) the
380  * application requires, i.e., partitions with inhit >= 0. (If
381  * negative, indicates number of non-air hits needed).
382  *
383  * If this box yielded additional segments, immediately weave
384  * them into the partition list, and perform final boolean
385  * evaluation.
386  *
387  * If this results in the required number of final partitions,
388  * then cease ray-tracing and hand the partitions over to the
389  * application.
390  *
391  * All partitions will have valid in and out distances.
392  * a_ray_length is treated similarly to a_onehit.
393  */
394  if (ap->a_onehit != 0 && BU_LIST_NON_EMPTY(&(waiting_segs.l))) {
395  int done;
396 
397  /* Weave these segments into partition list */
398  rt_boolweave(&finished_segs, &waiting_segs, &InitialPart, ap);
399 
400  /* Evaluate regions upto box_end */
401  done = rt_boolfinal(&InitialPart, &FinalPart,
402  last_bool_start, ss.box_end, regionbits, ap, solidbits);
403  last_bool_start = ss.box_end;
404 
405  /* See if enough partitions have been acquired */
406  if (done > 0) goto hitit;
407  }
408 
409  if (ap->a_ray_length > 0.0 && ss.box_end >= ap->a_ray_length)
410  goto weave;
411 
412  /* Push ray onwards to next box */
413  ss.box_start = ss.box_end;
414  }
415 
416  /*
417  * Ray has finally left known space -- Weave any remaining
418  * segments into the partition list.
419  */
420 weave:
422  bu_log("rt_shootray_bundle: ray has left known space\n");
423 
424  if (BU_LIST_NON_EMPTY(&(waiting_segs.l))) {
425  rt_boolweave(&finished_segs, &waiting_segs, &InitialPart, ap);
426  }
427 
428  /* finished_segs chain now has all segments hit by this ray */
429  if (BU_LIST_IS_EMPTY(&(finished_segs.l))) {
430  if (ap->a_miss)
431  ap->a_return = ap->a_miss(ap);
432  else
433  ap->a_return = 0;
434  status = "MISS primitives";
435  goto out;
436  }
437 
438  /*
439  * All intersections of the ray with the model have been computed.
440  * Evaluate the boolean trees over each partition.
441  */
442  (void)rt_boolfinal(&InitialPart, &FinalPart, BACKING_DIST,
443  INFINITY,
444  regionbits, ap, solidbits);
445 
446  if (FinalPart.pt_forw == &FinalPart) {
447  if (ap->a_miss)
448  ap->a_return = ap->a_miss(ap);
449  else
450  ap->a_return = 0;
451  status = "MISS bool";
452  RT_FREE_PT_LIST(&InitialPart, resp);
453  RT_FREE_SEG_LIST(&finished_segs, resp);
454  goto out;
455  }
456 
457  /*
458  * Ray/model intersections exist. Pass the list to the user's
459  * a_hit() routine. Note that only the hit_dist elements of
460  * pt_inhit and pt_outhit have been computed yet. To compute both
461  * hit_point and hit_normal, use the
462  *
463  * RT_HIT_NORMAL(NULL, hitp, stp, rayp, 0)
464  *
465  * macro. To compute just hit_point, use
466  *
467  * VJOIN1(hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir);
468  */
469 hitit:
470  if (debug_shoot) rt_pr_partitions(rtip, &FinalPart, "a_hit()");
471 
472  /*
473  * Before recursing, release storage for unused Initial
474  * partitions. finished_segs can not be released yet, because
475  * FinalPart partitions will point to hits in those segments.
476  */
477  RT_FREE_PT_LIST(&InitialPart, resp);
478 
479  /*
480  * finished_segs is only used by special hit routines which don't
481  * follow the traditional solid modeling paradigm.
482  */
483  if (RT_G_DEBUG&DEBUG_ALLHITS) rt_pr_partitions(rtip, &FinalPart, "Partition list passed to a_hit() routine");
484  if (ap->a_hit)
485  ap->a_return = ap->a_hit(ap, &FinalPart, &finished_segs);
486  else
487  ap->a_return = 0;
488  status = "HIT";
489 
490  RT_FREE_SEG_LIST(&finished_segs, resp);
491  RT_FREE_PT_LIST(&FinalPart, resp);
492 
493  /*
494  * Processing of this ray is complete.
495  */
496 out:
497  /* Return dynamic resources to their freelists. */
498  BU_CK_BITV(solidbits);
499  BU_LIST_APPEND(&resp->re_solid_bitv, &solidbits->l);
500  BU_CK_PTBL(regionbits);
501  BU_LIST_APPEND(&resp->re_region_ptbl, &regionbits->l);
502 
503  /*
504  * Record essential statistics in per-processor data structure.
505  */
506  resp->re_nshootray++;
507 
508  /* Terminate any logging */
509  if (RT_G_DEBUG&(DEBUG_ALLRAYS|DEBUG_SHOOT|DEBUG_PARTITION|DEBUG_ALLHITS)) {
511  bu_log("----------shootray_bundle cpu=%d %d, %d lvl=%d (%s) %s ret=%d\n",
512  resp->re_cpu,
513  ap->a_x, ap->a_y,
514  ap->a_level,
515  ap->a_purpose != (char *)0 ? ap->a_purpose : "?",
516  status, ap->a_return);
517  }
518  return ap->a_return;
519 }
520 
521 
522 /*
523  * 'static' local hit function that simply adds hit partition to a ray
524  * bundle structure passed in through ap->a_uptr and updates hit/miss
525  * stats.
526  */
527 static int
528 bundle_hit(register struct application *ap, struct partition *PartHeadp, struct seg *segp)
529 {
530  register struct partition *pp;
531  struct partition_bundle *bundle = (struct partition_bundle *)ap->a_uptr;
532  struct partition_list *new_shotline;
533 
534  if ((pp=PartHeadp->pt_forw) == PartHeadp) {
535  bundle->misses++;
536  return 0; /* Nothing hit?? */
537  }
538 
539  bundle->hits++;
540 
541  if (bundle->list == NULL) {
542  /*
543  * setup partition collection
544  */
545  BU_ALLOC(bundle->list, struct partition_list);
546  BU_LIST_INIT(&(bundle->list->l));
547  }
548 
549  /* add a new partition to list */
550  BU_ALLOC(new_shotline, struct partition_list);
551 
552  /* steal partition list */
553  BU_LIST_INIT_MAGIC((struct bu_list *)&new_shotline->PartHeadp, PT_HD_MAGIC);
554  BU_LIST_APPEND_LIST((struct bu_list *)&new_shotline->PartHeadp, (struct bu_list *)PartHeadp);
555 
556  BU_LIST_INIT_MAGIC(&new_shotline->segHeadp.l, RT_SEG_MAGIC);
557  BU_LIST_APPEND_LIST(&new_shotline->segHeadp.l, &segp->l);
558 
559  new_shotline->ap = ap;
560  BU_LIST_PUSH(&(bundle->list->l), &(new_shotline->l));
561 
562  return 1;
563 
564 }
565 
566 
567 /*
568  * 'static' local hit function that simply miss stats for bundled rays.
569  */
570 static int
571 bundle_miss(register struct application *ap)
572 {
573  struct partition_bundle *bundle = (struct partition_bundle *)ap->a_uptr;
574 
575  bundle->misses++;
576 
577  return 0;
578 }
579 
580 
581 int
583 {
584  struct partition_bundle *pb = NULL;
585  void *a_uptr_backup = NULL;
586  struct xray a_ray;
587  int (*a_hit)(struct application *, struct partition *, struct seg *);
588  int (*a_miss)(struct application *);
589 
590  struct application *ray_ap = NULL;
591  int hit;
592  struct rt_i * rt_i = bundle->b_ap.a_rt_i; /**< @brief this librt instance */
593  struct resource * resource = bundle->b_ap.a_resource; /**< @brief dynamic memory resources */
594  struct xrays *r;
595  struct partition_list *pl;
596 
597  /*
598  * temporarily hijack ap->a_uptr, ap->a_ray, ap->a_hit(), ap->a_miss()
599  */
600  a_uptr_backup = bundle->b_ap.a_uptr;
601  a_ray = bundle->b_ap.a_ray;
602  a_hit = bundle->b_ap.a_hit;
603  a_miss = bundle->b_ap.a_miss;
604 
605  /*
606  * Along with updating some bundle hit/miss counters the default
607  * callback functions differ from their general user defined
608  * counterparts by detaching the ray hit partition list and
609  * segment list and attaching it to a partition bundle. Users can
610  * define their own functions but should remember to hi-jack the
611  * partition and segment list or the single ray handling function
612  * will return memory allocated to these list prior to the bundle
613  * b_hit() routine.
614  */
615 
616  /* Shoot bundle of Rays */
617  bundle->b_ap.a_purpose = "bundled ray";
618  if (!bundle->b_ap.a_hit)
619  bundle->b_ap.a_hit = bundle_hit;
620  if (!bundle->b_ap.a_miss)
621  bundle->b_ap.a_miss = bundle_miss;
622 
623  BU_ALLOC(pb, struct partition_bundle);
624  pb->ap = &bundle->b_ap;
625  pb->hits = pb->misses = 0;
626 
627  bundle->b_uptr = (void *)pb;
628 
629  for (BU_LIST_FOR (r, xrays, &bundle->b_rays.l)) {
630  BU_ALLOC(ray_ap, struct application);
631  *ray_ap = bundle->b_ap; /* structure copy */
632 
633  ray_ap->a_ray = r->ray;
634  ray_ap->a_ray.magic = RT_RAY_MAGIC;
635  ray_ap->a_uptr = (void *)pb;
636  ray_ap->a_rt_i = rt_i;
637  ray_ap->a_resource = resource;
638 
639  hit = rt_shootray(ray_ap);
640 
641  rt_i = ray_ap->a_rt_i;
642  resource = ray_ap->a_resource;
643 
644  if (hit == 0)
645  bu_free((void *)(ray_ap), "ray application structure");
646  }
647 
648  if ((bundle->b_hit) && (pb->hits > 0)) {
649  /* "HIT" */
650  bundle->b_return = bundle->b_hit(bundle, pb);
651  } else if (bundle->b_miss) {
652  /* "MISS" */
653  bundle->b_return = bundle->b_miss(bundle);
654  } else {
655  /* "MISS (unexpected)" */
656  bundle->b_return = 0;
657  }
658 
659  if (pb->list != NULL) {
660  while (BU_LIST_WHILE(pl, partition_list, &(pb->list->l))) {
661  BU_LIST_DEQUEUE(&(pl->l));
662  RT_FREE_SEG_LIST(&pl->segHeadp, resource);
663  RT_FREE_PT_LIST(&pl->PartHeadp, resource);
664  bu_free(pl->ap, "ray application structure");
665  bu_free(pl, "free partition_list pl");
666  }
667  bu_free(pb->list, "free partition_list header");
668  }
669  bu_free(pb, "partition bundle");
670  /*
671  * set back to original values before exiting
672  */
673  bundle->b_ap.a_uptr = a_uptr_backup;
674  bundle->b_ap.a_ray = a_ray;
675  bundle->b_ap.a_hit = a_hit;
676  bundle->b_ap.a_miss = a_miss;
677 
678  return bundle->b_return;
679 }
680 
681 
682 /*
683  * Local Variables:
684  * mode: C
685  * tab-width: 8
686  * indent-tabs-mode: t
687  * c-file-style: "stroustrup"
688  * End:
689  * ex: shiftwidth=4 tabstop=8
690  */
struct partition PartHeadp
Definition: raytrace.h:657
struct xray a_ray
Actual ray to be shot.
Definition: raytrace.h:1583
#define BU_LIST_FOR(p, structure, hp)
Definition: list.h:365
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
#define BU_LIST_INSERT(old, new)
Definition: list.h:183
struct seg * a_finished_segs_hdp
Definition: raytrace.h:1612
struct hit seg_in
IN information.
Definition: raytrace.h:370
#define DEBUG_ALLHITS
2 Print partitions passed to a_hit()
Definition: raytrace.h:83
uint32_t pt_magic
sanity check
Definition: raytrace.h:573
Definition: list.h:118
point_t mdl_min
min corner of model bounding RPP
Definition: raytrace.h:1769
struct soltab ** bn_list
bn_list[bn_len]
Definition: raytrace.h:696
#define RT_RAY_MAGIC
Definition: magic.h:165
#define RT_CK_RTI(_p)
Definition: raytrace.h:1833
int(* b_miss)(struct application_bundle *)
called when entire bundle misses
Definition: raytrace.h:1665
void bu_ptbl_init(struct bu_ptbl *b, size_t len, const char *str)
Definition: ptbl.c:32
#define CUT_CUTNODE
Definition: raytrace.h:718
#define VSET(a, b, c, d)
Definition: color.c:53
long re_nempty_cells
number of empty NUgrid cells passed through
Definition: raytrace.h:1468
struct bu_list l
Definition: raytrace.h:233
Definition: raytrace.h:215
#define BU_LIST_IS_EMPTY(hp)
Definition: list.h:295
Definition: raytrace.h:368
#define BU_LIST_IS_INITIALIZED(_hp)
Definition: list.h:175
long re_nmiss_model
Rays pruned by model RPP.
Definition: raytrace.h:1460
int ft_use_rpp
Definition: raytrace.h:2046
long re_nshootray
Calls to rt_shootray()
Definition: raytrace.h:1459
#define DEBUG_SHOOT
3 Info about rt_shootray() processing
Definition: raytrace.h:84
struct application b_ap
application setting to be applied to each ray
Definition: raytrace.h:1663
struct bu_list re_parthead
Head of freelist.
Definition: raytrace.h:1448
Header file for the BRL-CAD common definitions.
fastf_t odist_corr
Definition: raytrace.h:2250
struct xray newray
closer ray start
Definition: raytrace.h:2257
void rt_plot_cell(const union cutter *cutp, struct rt_shootray_status *ssp, struct bu_list *waiting_segs_hd, struct rt_i *rtip)
#define BU_CK_PTBL(_p)
Definition: ptbl.h:74
struct nu_axis * nu_axis[3]
Definition: raytrace.h:712
#define RT_CK_RAY(_p)
Definition: raytrace.h:224
#define BU_LIST_APPEND(old, new)
Definition: list.h:197
vect_t abs_inv_dir
absolute values of inv_dir
Definition: raytrace.h:2261
struct resource * a_resource
dynamic memory resources
Definition: raytrace.h:1591
fastf_t model_start
Definition: raytrace.h:2255
int rt_in_rpp(struct xray *rp, const fastf_t *invdir, const fastf_t *min, const fastf_t *max)
#define BU_LIST_NON_EMPTY(hp)
Definition: list.h:296
void bu_log_indent_delta(int delta)
Definition: log.c:54
int a_onehit
flag to stop on first hit
Definition: raytrace.h:1586
int(* a_hit)(struct application *, struct partition *, struct seg *)
called when shot hits model
Definition: raytrace.h:1584
fastf_t nu_spos
cell start position
Definition: raytrace.h:705
#define BU_BITSET(_bv, bit)
Definition: bitv.h:183
struct bu_list l
Definition: raytrace.h:369
const union cutter * rt_advance_to_next_cell(struct rt_shootray_status *ssp)
int rt_shootray_bundle(register struct application *ap, struct xray *rays, int nrays)
Definition: bundle.c:73
Definition: ptbl.h:62
void rt_init_resource(struct resource *resp, int cpu_num, struct rt_i *rtip)
Definition: prep.c:585
long st_bit
solids bit vector index (const)
Definition: raytrace.h:439
struct partition * a_Final_Part_hdp
Definition: raytrace.h:1613
if(share_geom)
Definition: nmg_mod.c:3829
#define RT_AP_CHECK(_ap)
Definition: raytrace.h:1685
long re_prune_solrpp
shot missed solid RPP, ft_shot skipped
Definition: raytrace.h:1466
const union cutter * curcut
Definition: raytrace.h:2264
Definition: color.c:49
uint32_t a_magic
Definition: raytrace.h:1581
struct rt_i * a_rt_i
this librt instance
Definition: raytrace.h:1588
#define RT_AP_MAGIC
Definition: magic.h:152
void * memset(void *s, int c, size_t n)
#define DEBUG_PARTITION
14 Info about bool_weave()
Definition: raytrace.h:99
struct resource rt_uniresource
default. Defined in librt/globals.c
Definition: globals.c:41
#define RT_G_DEBUG
Definition: raytrace.h:1718
vect_t inv_dir
inverses of ap->a_ray.r_dir
Definition: raytrace.h:2260
#define BU_BITTEST(_bv, bit)
Definition: bitv.h:168
size_t bn_len
of solids in list
Definition: raytrace.h:697
struct bu_list l
Definition: bitv.h:106
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
#define CUT_NUGRIDNODE
Definition: raytrace.h:720
union cutter rti_CutHead
Head of cut tree.
Definition: raytrace.h:1793
struct seg segHeadp
Definition: raytrace.h:658
#define BU_PTBL_GET(ptbl, i)
Definition: ptbl.h:108
struct application * ap
Definition: raytrace.h:656
int(* ft_shot)(struct soltab *stp, struct xray *rp, struct application *ap, struct seg *seghead)
Definition: raytrace.h:2052
#define RT_CK_AP(_p)
Definition: raytrace.h:1674
#define V3ARGS(a)
Definition: color.c:56
int a_x
Screen X of ray, if applicable.
Definition: raytrace.h:1596
#define NEAR_ZERO(val, epsilon)
Definition: color.c:55
point_t st_max
max X, Y, Z of bounding RPP
Definition: raytrace.h:438
#define SQRT_SMALL_FASTF
Definition: defines.h:346
const union cutter * lastcut
Definition: raytrace.h:2263
#define BU_LIST_INIT_MAGIC(_hp, _magic)
Definition: list.h:156
struct hit seg_out
OUT information.
Definition: raytrace.h:371
#define DEBUG_ADVANCE
24 Cell-to-cell space partitioning
Definition: raytrace.h:109
fastf_t r_max
exit dist from bounding sphere
Definition: raytrace.h:221
struct xray * hit_rayp
pointer to defining ray
Definition: raytrace.h:256
fastf_t dist_corr
correction distance
Definition: raytrace.h:2249
int a_level
recursion level (for printing)
Definition: raytrace.h:1595
struct bu_list l
Definition: ptbl.h:63
const char * a_purpose
Debug string: purpose of ray.
Definition: raytrace.h:1598
struct application * ap
Definition: raytrace.h:671
long re_shots
calls to ft_shot()
Definition: raytrace.h:1462
void rt_pr_partitions(const struct rt_i *rtip, const struct partition *phead, const char *title)
#define PT_HD_MAGIC
Definition: magic.h:208
goto out
Definition: nmg_mod.c:3846
struct partition * pt_back
backwards link
Definition: raytrace.h:575
fastf_t a_ray_length
distance from ray start to end intersections
Definition: raytrace.h:1587
fastf_t nu_epos
cell end position
Definition: raytrace.h:706
struct bu_list re_region_ptbl
head of freelist
Definition: raytrace.h:1453
#define BU_LIST_WHILE(p, structure, hp)
Definition: list.h:410
fastf_t obox_start
Definition: raytrace.h:2252
vect_t r_dir
Direction of ray (UNIT Length)
Definition: raytrace.h:219
void * b_uptr
application_bundle-specific pointer
Definition: raytrace.h:1667
#define BU_LIST_PUSH(hp, p)
Definition: list.h:246
int a_return
Return of a_hit()/a_miss()
Definition: raytrace.h:1601
fastf_t r_min
entry dist to bounding sphere
Definition: raytrace.h:220
struct bu_bitv * rt_get_solidbitv(size_t nbits, struct resource *resp)
Definition: prep.c:828
long re_ndup
ft_shot() calls skipped for already-ft_shot() solids
Definition: raytrace.h:1467
#define BU_LIST_INIT(_hp)
Definition: list.h:148
long re_shot_hit
ft_shot() returned a miss
Definition: raytrace.h:1463
point_t r_pt
Point at which ray starts.
Definition: raytrace.h:218
struct rt_shootray_status * old_status
Definition: raytrace.h:2269
int rstep[3]
-/0/+ dir of ray in axis
Definition: raytrace.h:2262
point_t st_min
min X, Y, Z of bounding RPP
Definition: raytrace.h:437
#define RT_SEG_MAGIC
Definition: magic.h:167
struct bu_list re_solid_bitv
head of freelist
Definition: raytrace.h:1452
void rt_boolweave(struct seg *out_hd, struct seg *in_hd, struct partition *PartHeadp, struct application *ap)
Definition: bool.c:145
const struct rt_functab OBJ[]
Definition: table.c:159
#define RT_CK_RESOURCE(_p)
Definition: raytrace.h:1490
#define BU_ASSERT_PTR(_lhs, _relation, _rhs)
Definition: defines.h:227
int hit(struct application *ap, struct partition *PartHeadp, struct seg *segs)
Definition: gqa.c:963
#define DEBUG_ALLRAYS
1 Print calls to rt_shootray()
Definition: raytrace.h:82
size_t nsolids
total # of solids participating
Definition: raytrace.h:1783
point_t mdl_max
max corner of model bounding RPP
Definition: raytrace.h:1770
int a_y
Screen Y of ray, if applicable.
Definition: raytrace.h:1597
struct partition_list * list
Definition: raytrace.h:670
void rt_prep(struct rt_i *rtip)
int cut_type
Definition: raytrace.h:723
long re_shot_miss
ft_shot() returned a hit
Definition: raytrace.h:1464
struct xray ray
Definition: raytrace.h:234
Definition: color.c:51
int rt_shootray(struct application *ap)
void * a_uptr
application-specific pointer
Definition: raytrace.h:1618
struct resource * resp
Definition: raytrace.h:2259
struct boxnode bn
Definition: raytrace.h:726
int re_cpu
processor number, for ID
Definition: raytrace.h:1442
struct nugridnode nugn
Definition: raytrace.h:727
const union cutter * lastcell
Definition: raytrace.h:2263
struct bu_list l
Definition: raytrace.h:655
#define CUTTER_NULL
Definition: raytrace.h:731
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
int(* a_miss)(struct application *)
called when shot misses
Definition: raytrace.h:1585
struct bu_ptbl rti_resources
list of 'struct resource's encountered
Definition: raytrace.h:1811
void rt_pr_cut(const union cutter *cutp, int lvl)
Definition: cut.c:1703
int rt_boolfinal(struct partition *InputHdp, struct partition *FinalHdp, fastf_t startdist, fastf_t enddist, struct bu_ptbl *regionbits, struct application *ap, const struct bu_bitv *solidbits)
Definition: bool.c:1490
struct xrays b_rays
Actual bundle of rays to be shot.
Definition: raytrace.h:1662
int rt_shootrays(struct application_bundle *bundle)
Definition: bundle.c:582
int nu_cells_per_axis[3]
number of slabs
Definition: raytrace.h:713
int st_id
Solid ident.
Definition: raytrace.h:431
#define BU_LIST_DEQUEUE(cur)
Definition: list.h:209
#define CUT_BOXNODE
Definition: raytrace.h:719
Definition: bitv.h:105
int(* b_hit)(struct application_bundle *, struct partition_bundle *)
called when bundle hits model
Definition: raytrace.h:1664
struct partition * pt_forw
forwards link
Definition: raytrace.h:574
fastf_t hit_dist
dist from r_pt to hit_point
Definition: raytrace.h:250
#define RT_FREE_PT_LIST(_headp, _res)
Definition: raytrace.h:630
void bu_bomb(const char *str) _BU_ATTR_NORETURN
Definition: bomb.c:91
double fastf_t
Definition: defines.h:300
#define BU_CK_BITV(_bp)
Definition: bitv.h:116
#define VPRINT(a, b)
Definition: raytrace.h:1881
struct application * ap
Definition: raytrace.h:2258
int needprep
needs rt_prep
Definition: raytrace.h:1776
Definition: color.c:50
#define BU_LIST_APPEND_LIST(dest_hp, src_hp)
Definition: list.h:281
uint32_t magic
Definition: raytrace.h:216
#define BU_LIST_FIRST(structure, hp)
Definition: list.h:312
#define RT_FREE_SEG_LIST(_segheadp, _res)
Definition: raytrace.h:401
#define BACKING_DIST
mm to look behind start point
Definition: raytrace.h:2290