BRL-CAD
display_list.c
Go to the documentation of this file.
1 /* D I S P L A Y _ L I S T . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2008-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 /** @file libged/display_list.c
21  *
22  * Collect display list manipulation logic here as it is refactored.
23  *
24  */
25 
26 #include "common.h"
27 
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include "plot3.h"
32 
33 #include "solid.h"
34 #include "./ged_private.h"
35 
36 
37 
38 /* defined in draw_calc.cpp */
39 extern fastf_t brep_est_avg_curve_len(struct rt_brep_internal *bi);
40 
41 struct display_list *
42 dl_addToDisplay(struct bu_list *hdlp, struct db_i *dbip,
43  const char *name)
44 {
45  struct directory *dp = NULL;
46  struct display_list *gdlp = NULL;
47  char *cp = NULL;
48  int found_namepath = 0;
49  struct db_full_path namepath;
50 
51  cp = strrchr(name, '/');
52  if (!cp)
53  cp = (char *)name;
54  else
55  ++cp;
56 
57  if ((dp = db_lookup(dbip, cp, LOOKUP_NOISY)) == RT_DIR_NULL) {
58  gdlp = GED_DISPLAY_LIST_NULL;
59  goto end;
60  }
61 
62  if (db_string_to_path(&namepath, dbip, name) == 0)
63  found_namepath = 1;
64 
65  /* Make sure name is not already in the list */
66  gdlp = BU_LIST_NEXT(display_list, hdlp);
67  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
68  if (BU_STR_EQUAL(name, bu_vls_addr(&gdlp->dl_path)))
69  goto end;
70 
71  if (found_namepath) {
72  struct db_full_path gdlpath;
73 
74  if (db_string_to_path(&gdlpath, dbip, bu_vls_addr(&gdlp->dl_path)) == 0) {
75  if (db_full_path_match_top(&gdlpath, &namepath)) {
76  db_free_full_path(&gdlpath);
77  goto end;
78  }
79 
80  db_free_full_path(&gdlpath);
81  }
82  }
83 
84  gdlp = BU_LIST_PNEXT(display_list, gdlp);
85  }
86 
87  BU_ALLOC(gdlp, struct display_list);
88  BU_LIST_INIT(&gdlp->l);
89  BU_LIST_INSERT(hdlp, &gdlp->l);
90  BU_LIST_INIT(&gdlp->dl_headSolid);
91  gdlp->dl_dp = (void *)dp;
92  bu_vls_init(&gdlp->dl_path);
93  bu_vls_printf(&gdlp->dl_path, "%s", name);
94 
95 end:
96  if (found_namepath)
97  db_free_full_path(&namepath);
98 
99  return gdlp;
100 }
101 
102 
103 void
104 headsolid_split(struct bu_list *hdlp, struct db_i *dbip, struct solid *sp, int newlen)
105 {
106  int savelen;
107  struct display_list *new_gdlp;
108  char *pathname;
109 
110  savelen = sp->s_fullpath.fp_len;
111  sp->s_fullpath.fp_len = newlen;
112  pathname = db_path_to_string(&sp->s_fullpath);
113  sp->s_fullpath.fp_len = savelen;
114 
115  new_gdlp = dl_addToDisplay(hdlp, dbip, pathname);
116  bu_free((void *)pathname, "headsolid_split pathname");
117 
118  BU_LIST_DEQUEUE(&sp->l);
119  BU_LIST_INSERT(&new_gdlp->dl_headSolid, &sp->l);
120 }
121 
122 
123 
124 int
125 headsolid_splitGDL(struct bu_list *hdlp, struct db_i *dbip, struct display_list *gdlp, struct db_full_path *path)
126 {
127  struct solid *sp;
128  struct solid *nsp;
129  int newlen = path->fp_len + 1;
130 
131  if (BU_LIST_IS_EMPTY(&gdlp->dl_headSolid)) return 0;
132 
133  if (newlen < 3) {
134  while (BU_LIST_WHILE(sp, solid, &gdlp->dl_headSolid)) {
135  headsolid_split(hdlp, dbip, sp, newlen);
136  }
137  } else {
138  sp = BU_LIST_NEXT(solid, &gdlp->dl_headSolid);
139  while (BU_LIST_NOT_HEAD(sp, &gdlp->dl_headSolid)) {
140  nsp = BU_LIST_PNEXT(solid, sp);
141  if (db_full_path_match_top(path, &sp->s_fullpath)) {
142  headsolid_split(hdlp, dbip, sp, newlen);
143  }
144  sp = nsp;
145  }
146 
147  --path->fp_len;
148  headsolid_splitGDL(hdlp, dbip, gdlp, path);
149  ++path->fp_len;
150  }
151 
152  return 1;
153 }
154 
155 
156 int
157 dl_bounding_sph(struct bu_list *hdlp, vect_t *min, vect_t *max, int pflag)
158 {
159  struct display_list *gdlp;
160  struct display_list *next_gdlp;
161  struct solid *sp;
162  vect_t minus, plus;
163  int is_empty = 1;
164 
165  VSETALL((*min), INFINITY);
166  VSETALL((*max), -INFINITY);
167 
168  /* calculate the bounding for of all solids being displayed */
169  gdlp = BU_LIST_NEXT(display_list, hdlp);
170  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
171  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
172 
173  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
174  /* Skip pseudo-solids unless pflag is set */
175  if (!pflag &&
176  sp->s_fullpath.fp_names != (struct directory **)0 &&
177  sp->s_fullpath.fp_names[0] != (struct directory *)0 &&
178  sp->s_fullpath.fp_names[0]->d_addr == RT_DIR_PHONY_ADDR)
179  continue;
180 
181  minus[X] = sp->s_center[X] - sp->s_size;
182  minus[Y] = sp->s_center[Y] - sp->s_size;
183  minus[Z] = sp->s_center[Z] - sp->s_size;
184  VMIN((*min), minus);
185  plus[X] = sp->s_center[X] + sp->s_size;
186  plus[Y] = sp->s_center[Y] + sp->s_size;
187  plus[Z] = sp->s_center[Z] + sp->s_size;
188  VMAX((*max), plus);
189 
190  is_empty = 0;
191  }
192 
193  gdlp = next_gdlp;
194  }
195 
196  return is_empty;
197 }
198 
199 /*
200  * Erase/remove the display list item from headDisplay if path matches the list item's path.
201  *
202  */
203 void
205  struct db_i *dbip, void (*callback)(unsigned int, int),
206  const char *path, int allow_split, struct solid *freesolid)
207 {
208  struct display_list *gdlp;
209  struct display_list *next_gdlp;
210  struct display_list *last_gdlp;
211  struct solid *sp;
212  struct directory *dp;
213  struct db_full_path subpath;
214  int found_subpath;
215 
216  if (db_string_to_path(&subpath, dbip, path) == 0)
217  found_subpath = 1;
218  else
219  found_subpath = 0;
220 
221  gdlp = BU_LIST_NEXT(display_list, hdlp);
222  last_gdlp = BU_LIST_LAST(display_list, hdlp);
223  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
224  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
225 
226  if (BU_STR_EQUAL(path, bu_vls_addr(&gdlp->dl_path))) {
227  if (callback != GED_FREE_VLIST_CALLBACK_PTR_NULL) {
228 
229  /* We can't assume the display lists are contiguous */
230  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
231  (*callback)(BU_LIST_FIRST(solid, &gdlp->dl_headSolid)->s_dlist, 1);
232  }
233  }
234 
235  /* Free up the solids list associated with this display list */
236  while (BU_LIST_WHILE(sp, solid, &gdlp->dl_headSolid)) {
237  dp = FIRST_SOLID(sp);
238  RT_CK_DIR(dp);
239  if (dp->d_addr == RT_DIR_PHONY_ADDR) {
240  (void)db_dirdelete(dbip, dp);
241  }
242 
243  BU_LIST_DEQUEUE(&sp->l);
244  FREE_SOLID(sp, &freesolid->l);
245  }
246 
247  BU_LIST_DEQUEUE(&gdlp->l);
248  bu_vls_free(&gdlp->dl_path);
249  free((void *)gdlp);
250 
251  break;
252  } else if (found_subpath) {
253  int need_split = 0;
254  struct solid *nsp;
255 
256  sp = BU_LIST_NEXT(solid, &gdlp->dl_headSolid);
257  while (BU_LIST_NOT_HEAD(sp, &gdlp->dl_headSolid)) {
258  nsp = BU_LIST_PNEXT(solid, sp);
259 
260  if (db_full_path_match_top(&subpath, &sp->s_fullpath)) {
261  if (callback != GED_FREE_VLIST_CALLBACK_PTR_NULL)
262  (*callback)(sp->s_dlist, 1);
263 
264  BU_LIST_DEQUEUE(&sp->l);
265  FREE_SOLID(sp, &freesolid->l);
266  need_split = 1;
267  }
268 
269  sp = nsp;
270  }
271 
272  if (BU_LIST_IS_EMPTY(&gdlp->dl_headSolid)) {
273  BU_LIST_DEQUEUE(&gdlp->l);
274  bu_vls_free(&gdlp->dl_path);
275  free((void *)gdlp);
276  } else if (allow_split && need_split) {
277  BU_LIST_DEQUEUE(&gdlp->l);
278 
279  --subpath.fp_len;
280  (void)headsolid_splitGDL(hdlp, dbip, gdlp, &subpath);
281  ++subpath.fp_len;
282 
283  /* Free up the display list */
284  bu_vls_free(&gdlp->dl_path);
285  free((void *)gdlp);
286  }
287  }
288 
289  if (gdlp == last_gdlp)
290  gdlp = (struct display_list *)hdlp;
291  else
292  gdlp = next_gdlp;
293  }
294 
295  if (found_subpath)
296  db_free_full_path(&subpath);
297 }
298 
299 
300 HIDDEN void
302  struct db_full_path *subpath,
303  void (*callback)(unsigned int, int),
304  const int skip_first, struct solid *freesolid)
305 {
306  struct solid *sp;
307  struct solid *nsp;
308 
309  sp = BU_LIST_NEXT(solid, &gdlp->dl_headSolid);
310  while (BU_LIST_NOT_HEAD(sp, &gdlp->dl_headSolid)) {
311  nsp = BU_LIST_PNEXT(solid, sp);
312  if (db_full_path_subset(&sp->s_fullpath, subpath, skip_first)) {
313  if (callback != GED_FREE_VLIST_CALLBACK_PTR_NULL)
314  (*callback)(sp->s_dlist, 1);
315 
316  BU_LIST_DEQUEUE(&sp->l);
317  FREE_SOLID(sp, &freesolid->l);
318  }
319  sp = nsp;
320  }
321 }
322 
323 
324 /*
325  * Erase/remove display list item from headDisplay if name is found anywhere along item's path with
326  * the exception that the first path element is skipped if skip_first is true.
327  *
328  * Note - name is not expected to contain path separators.
329  *
330  */
331 void
332 _dl_eraseAllNamesFromDisplay(struct bu_list *hdlp, struct db_i *dbip,
333  void (*callback)(unsigned int, int), const char *name, const int skip_first, struct solid *freesolid)
334 {
335  struct display_list *gdlp;
336  struct display_list *next_gdlp;
337 
338  gdlp = BU_LIST_NEXT(display_list, hdlp);
339  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
340  char *dup_path;
341  char *tok;
342  int first = 1;
343  int found = 0;
344 
345  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
346 
347  dup_path = strdup(bu_vls_addr(&gdlp->dl_path));
348  tok = strtok(dup_path, "/");
349  while (tok) {
350  if (first) {
351  first = 0;
352 
353  if (skip_first) {
354  tok = strtok((char *)NULL, "/");
355  continue;
356  }
357  }
358 
359  if (BU_STR_EQUAL(tok, name)) {
360  _dl_freeDisplayListItem(dbip, callback, gdlp, freesolid);
361  found = 1;
362 
363  break;
364  }
365 
366  tok = strtok((char *)NULL, "/");
367  }
368 
369  /* Look for name in solids list */
370  if (!found) {
371  struct db_full_path subpath;
372 
373  if (db_string_to_path(&subpath, dbip, name) == 0) {
374  eraseAllSubpathsFromSolidList(gdlp, &subpath, callback, skip_first, freesolid);
375  db_free_full_path(&subpath);
376  }
377  }
378 
379  free((void *)dup_path);
380  gdlp = next_gdlp;
381  }
382 }
383 
384 
385 int
386 _dl_eraseFirstSubpath(struct bu_list *hdlp, struct db_i *dbip,
387  void (*callback)(unsigned int, int),
388  struct display_list *gdlp,
389  struct db_full_path *subpath,
390  const int skip_first, struct solid *freesolid)
391 {
392  struct solid *sp;
393  struct solid *nsp;
394  struct db_full_path dup_path;
395 
396  db_full_path_init(&dup_path);
397 
398  sp = BU_LIST_NEXT(solid, &gdlp->dl_headSolid);
399  while (BU_LIST_NOT_HEAD(sp, &gdlp->dl_headSolid)) {
400  nsp = BU_LIST_PNEXT(solid, sp);
401  if (db_full_path_subset(&sp->s_fullpath, subpath, skip_first)) {
402  int ret;
403  int full_len = sp->s_fullpath.fp_len;
404 
405  if (callback != GED_FREE_VLIST_CALLBACK_PTR_NULL)
406  (*callback)(sp->s_dlist, 1);
407 
408  sp->s_fullpath.fp_len = full_len - 1;
409  db_dup_full_path(&dup_path, &sp->s_fullpath);
410  sp->s_fullpath.fp_len = full_len;
411  BU_LIST_DEQUEUE(&sp->l);
412  FREE_SOLID(sp, &freesolid->l);
413 
414  BU_LIST_DEQUEUE(&gdlp->l);
415 
416  ret = headsolid_splitGDL(hdlp, dbip, gdlp, &dup_path);
417 
418  db_free_full_path(&dup_path);
419 
420  /* Free up the display list */
421  bu_vls_free(&gdlp->dl_path);
422  free((void *)gdlp);
423 
424  return ret;
425  }
426  sp = nsp;
427  }
428 
429  return 0;
430 }
431 
432 
433 /*
434  * Erase/remove display list item from headDisplay if path is a subset of item's path.
435  */
436 void
437 _dl_eraseAllPathsFromDisplay(struct bu_list *hdlp, struct db_i *dbip,
438  void (*callback)(unsigned int, int),
439  const char *path,
440  const int skip_first,
441  struct solid *freesolid)
442 {
443  struct display_list *gdlp;
444  struct display_list *next_gdlp;
445  struct db_full_path fullpath, subpath;
446 
447  if (db_string_to_path(&subpath, dbip, path) == 0) {
448  gdlp = BU_LIST_NEXT(display_list, hdlp);
449  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
450  gdlp->dl_wflag = 0;
451  gdlp = BU_LIST_PNEXT(display_list, gdlp);
452  }
453 
454  gdlp = BU_LIST_NEXT(display_list, hdlp);
455  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
456  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
457 
458  /* This display list has already been visited. */
459  if (gdlp->dl_wflag) {
460  gdlp = next_gdlp;
461  continue;
462  }
463 
464  /* Mark as being visited. */
465  gdlp->dl_wflag = 1;
466 
467  if (db_string_to_path(&fullpath, dbip, bu_vls_addr(&gdlp->dl_path)) == 0) {
468  if (db_full_path_subset(&fullpath, &subpath, skip_first)) {
469  _dl_freeDisplayListItem(dbip, callback, gdlp, freesolid);
470  } else if (_dl_eraseFirstSubpath(hdlp, dbip, callback, gdlp, &subpath, skip_first, freesolid)) {
471  gdlp = BU_LIST_NEXT(display_list, hdlp);
472  db_free_full_path(&fullpath);
473  continue;
474  }
475 
476  db_free_full_path(&fullpath);
477  }
478 
479  gdlp = next_gdlp;
480  }
481 
482  db_free_full_path(&subpath);
483  }
484 }
485 
486 
487 void
489  void (*callback)(unsigned int, int),
490  struct display_list *gdlp, struct solid *freesolid)
491 {
492  struct solid *sp;
493  struct directory *dp;
494 
495  if (callback != GED_FREE_VLIST_CALLBACK_PTR_NULL) {
496 
497  /* We can't assume the display lists are contiguous */
498  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
499  (*callback)(BU_LIST_FIRST(solid, &gdlp->dl_headSolid)->s_dlist, 1);
500  }
501  }
502 
503  /* Free up the solids list associated with this display list */
504  while (BU_LIST_WHILE(sp, solid, &gdlp->dl_headSolid)) {
505  dp = FIRST_SOLID(sp);
506  RT_CK_DIR(dp);
507  if (dp->d_addr == RT_DIR_PHONY_ADDR) {
508  (void)db_dirdelete(dbip, dp);
509  }
510 
511  BU_LIST_DEQUEUE(&sp->l);
512  FREE_SOLID(sp, &freesolid->l);
513  }
514 
515  /* Free up the display list */
516  BU_LIST_DEQUEUE(&gdlp->l);
517  bu_vls_free(&gdlp->dl_path);
518  free((void *)gdlp);
519 }
520 
521 
522 static void
523 color_soltab(struct solid *sp)
524 {
525  const struct mater *mp;
526 
527  sp->s_cflag = 0;
528 
529  /* the user specified the color, so use it */
530  if (sp->s_uflag) {
531  sp->s_color[0] = sp->s_basecolor[0];
532  sp->s_color[1] = sp->s_basecolor[1];
533  sp->s_color[2] = sp->s_basecolor[2];
534 
535  return;
536  }
537 
538  for (mp = rt_material_head(); mp != MATER_NULL; mp = mp->mt_forw) {
539  if (sp->s_regionid <= mp->mt_high &&
540  sp->s_regionid >= mp->mt_low) {
541  sp->s_color[0] = mp->mt_r;
542  sp->s_color[1] = mp->mt_g;
543  sp->s_color[2] = mp->mt_b;
544 
545  return;
546  }
547  }
548 
549  /*
550  * There is no region-id-based coloring entry in the
551  * table, so use the combination-record ("mater"
552  * command) based color if one was provided. Otherwise,
553  * use the default wireframe color.
554  * This is the "new way" of coloring things.
555  */
556 
557  /* use wireframe_default_color */
558  if (sp->s_dflag)
559  sp->s_cflag = 1;
560 
561  /* Be conservative and copy color anyway, to avoid black */
562  sp->s_color[0] = sp->s_basecolor[0];
563  sp->s_color[1] = sp->s_basecolor[1];
564  sp->s_color[2] = sp->s_basecolor[2];
565 }
566 
567 
568 /*
569  * Pass through the solid table and set pointer to appropriate
570  * mater structure.
571  */
572 void
574 {
575  struct display_list *gdlp;
576  struct display_list *next_gdlp;
577  struct solid *sp;
578 
579  gdlp = BU_LIST_NEXT(display_list, hdlp);
580  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
581  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
582 
583  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
584  color_soltab(sp);
585  }
586 
587  gdlp = next_gdlp;
588  }
589 }
590 
591 
592 /* Set solid's basecolor, color, and color flags based on client data and tree
593  * * state. If user color isn't set in client data, the solid's region id must be
594  * * set for proper material lookup.
595  * */
596 static void
597 solid_set_color_info(
598  struct solid *sp,
599  unsigned char *wireframe_color_override,
600  struct db_tree_state *tsp)
601 {
602  unsigned char bcolor[3] = {255, 0, 0}; /* default */
603 
604  sp->s_uflag = 0;
605  sp->s_dflag = 0;
606  if (wireframe_color_override) {
607  sp->s_uflag = 1;
608 
609  bcolor[RED] = wireframe_color_override[RED];
610  bcolor[GRN] = wireframe_color_override[GRN];
611  bcolor[BLU] = wireframe_color_override[BLU];
612  } else if (tsp) {
613  if (tsp->ts_mater.ma_color_valid) {
614  bcolor[RED] = tsp->ts_mater.ma_color[RED] * 255.0;
615  bcolor[GRN] = tsp->ts_mater.ma_color[GRN] * 255.0;
616  bcolor[BLU] = tsp->ts_mater.ma_color[BLU] * 255.0;
617  } else {
618  sp->s_dflag = 1;
619  }
620  }
621 
622  sp->s_basecolor[RED] = bcolor[RED];
623  sp->s_basecolor[GRN] = bcolor[GRN];
624  sp->s_basecolor[BLU] = bcolor[BLU];
625 
626  color_soltab(sp);
627 }
628 
629 /**
630  * * Compute the min, max, and center points of the solid.
631  * */
632 static void
633 bound_solid(struct solid *sp)
634 {
635  struct bn_vlist *vp;
636  point_t bmin, bmax;
637  int cmd;
638  VSET(bmin, INFINITY, INFINITY, INFINITY);
639  VSET(bmax, -INFINITY, -INFINITY, -INFINITY);
640 
641  for (BU_LIST_FOR(vp, bn_vlist, &(sp->s_vlist))) {
642  cmd = bn_vlist_bbox(vp, &bmin, &bmax);
643  if (cmd) {
644  bu_log("unknown vlist op %d\n", cmd);
645  }
646  }
647 
648  sp->s_center[X] = (bmin[X] + bmax[X]) * 0.5;
649  sp->s_center[Y] = (bmin[Y] + bmax[Y]) * 0.5;
650  sp->s_center[Z] = (bmin[Z] + bmax[Z]) * 0.5;
651 
652  sp->s_size = bmax[X] - bmin[X];
653  V_MAX(sp->s_size, bmax[Y] - bmin[Y]);
654  V_MAX(sp->s_size, bmax[Z] - bmin[Z]);
655 }
656 
657 
658 static void
659 solid_append_vlist(struct solid *sp, struct bn_vlist *vlist)
660 {
661  if (BU_LIST_IS_EMPTY(&(sp->s_vlist))) {
662  sp->s_vlen = 0;
663  }
664 
665  sp->s_vlen += bn_vlist_cmd_cnt(vlist);
666  BU_LIST_APPEND_LIST(&(sp->s_vlist), &(vlist->l));
667 }
668 
669 void
670 dl_add_path(struct display_list *gdlp, int dashflag, int transparency, int dmode, int hiddenLine, struct bu_list *vhead, const struct db_full_path *pathp, struct db_tree_state *tsp, unsigned char *wireframe_color_override, void (*callback)(struct display_list *), struct solid *freesolid)
671 {
672  struct solid *sp;
673  GET_SOLID(sp, &freesolid->l);
674 
675  solid_append_vlist(sp, (struct bn_vlist *)vhead);
676 
677  bound_solid(sp);
678 
679  db_dup_full_path(&sp->s_fullpath, pathp);
680 
681  sp->s_flag = DOWN;
682  sp->s_iflag = DOWN;
683  sp->s_soldash = dashflag;
684  sp->s_Eflag = 0;
685 
686  if (tsp) {
687  sp->s_regionid = tsp->ts_regionid;
688  }
689 
690  solid_set_color_info(sp, wireframe_color_override, tsp);
691 
692  sp->s_dlist = 0;
693  sp->s_transparency = transparency;
694  sp->s_dmode = dmode;
695  sp->s_hiddenLine = hiddenLine;
696 
697  /* append solid to display list */
699  BU_LIST_APPEND(gdlp->dl_headSolid.back, &sp->l);
701 
702  if (callback != GED_CREATE_VLIST_CALLBACK_PTR_NULL) {
703  (*callback)(gdlp);
704  }
705 
706 }
707 
708 
709 
710 static fastf_t
711 view_avg_size(struct bview *gvp)
712 {
713  fastf_t view_aspect, x_size, y_size;
714 
715  view_aspect = (fastf_t)gvp->gv_x_samples / gvp->gv_y_samples;
716  x_size = gvp->gv_size;
717  y_size = x_size / view_aspect;
718 
719  return (x_size + y_size) / 2.0;
720 }
721 
722 static fastf_t
723 view_avg_sample_spacing(struct bview *gvp)
724 {
725  fastf_t avg_view_size, avg_view_samples;
726 
727  avg_view_size = view_avg_size(gvp);
728  avg_view_samples = (gvp->gv_x_samples + gvp->gv_y_samples) / 2.0;
729 
730  return avg_view_size / avg_view_samples;
731 }
732 
733 static fastf_t
734 solid_point_spacing(struct bview *gvp, fastf_t solid_width)
735 {
736  fastf_t radius, avg_view_size, avg_sample_spacing;
737  point2d_t p1, p2;
738 
739  if (solid_width < SQRT_SMALL_FASTF)
740  solid_width = SQRT_SMALL_FASTF;
741 
742  avg_view_size = view_avg_size(gvp);
743 
744  /* Now, for the sake of simplicity we're going to make
745  * several assumptions:
746  * - our samples represent a grid of square pixels
747  * - a circle with a diameter half the width of the solid is a
748  * good proxy for the kind of curve that will be plotted
749  */
750  radius = solid_width / 4.0;
751  if (avg_view_size < solid_width) {
752  /* If the solid is larger than the view, it is
753  * probably only partly visible and likely isn't the
754  * primary focus of the user. We'll cap the point
755  * spacing and avoid wasting effort.
756  */
757  radius = avg_view_size / 4.0;
758  }
759 
760  /* We imagine our representative circular curve lying in
761  * the XY plane centered at the origin.
762  *
763  * Suppose we're viewing the circle head on, and that the
764  * apex of the curve (0, radius) lies just inside the
765  * top edge of a pixel. Here we place a plotted point p1.
766  *
767  * As we continue clockwise around the circle we pass
768  * through neighboring pixels in the same row, until we
769  * vertically drop a distance equal to the pixel spacing,
770  * in which case we just barely enter a pixel in the next
771  * row. Here we place a plotted point p2 (y = radius -
772  * avg_sample_spacing).
773  *
774  * In theory, the line segment between p1 and p2 passes
775  * through all the same pixels that the actual curve does,
776  * and thus produces the exact same rasterization as if
777  * the curve between p1 and p2 was approximated with an
778  * infinite number of line segments.
779  *
780  * We assume that the distance between p1 and p2 is the
781  * maximum point sampling distance we can use for the
782  * curve which will give a perfect rasterization, i.e.
783  * the same rasterization as if we chose a point distance
784  * of 0.
785  */
786  p1[Y] = radius;
787  p1[X] = 0.0;
788 
789  avg_sample_spacing = view_avg_sample_spacing(gvp);
790  if (avg_sample_spacing < radius) {
791  p2[Y] = radius - (avg_sample_spacing);
792  } else {
793  /* no particular reason other than symmetry, just need
794  * to prevent sqrt(negative).
795  */
796  p2[Y] = radius;
797  }
798  p2[X] = sqrt((radius * radius) - (p2[Y] * p2[Y]));
799 
800  return DIST_PT2_PT2(p1, p2);
801 }
802 
803 
804 /* Choose a point spacing for the given solid (sp, ip) s.t. solid
805  * curves plotted with that spacing will look smooth when rasterized
806  * in the given view (gvp).
807  *
808  * TODO: view_avg_sample_spacing() might be sufficient if we can
809  * develop a general decimation routine for the resulting plots, in
810  * which case, this function could be removed.
811  */
812 static fastf_t
813 solid_point_spacing_for_view(
814  struct solid *sp,
815  struct rt_db_internal *ip,
816  struct bview *gvp)
817 {
818  fastf_t point_spacing = 0.0;
819 
820  if (ip->idb_major_type == DB5_MAJORTYPE_BRLCAD) {
821  switch (ip->idb_minor_type) {
822  case DB5_MINORTYPE_BRLCAD_TGC: {
823  struct rt_tgc_internal *tgc;
824  fastf_t avg_diameter;
825  fastf_t tgc_mag_a, tgc_mag_b, tgc_mag_c, tgc_mag_d;
826 
827  RT_CK_DB_INTERNAL(ip);
828  tgc = (struct rt_tgc_internal *)ip->idb_ptr;
829  RT_TGC_CK_MAGIC(tgc);
830 
831  tgc_mag_a = MAGNITUDE(tgc->a);
832  tgc_mag_b = MAGNITUDE(tgc->b);
833  tgc_mag_c = MAGNITUDE(tgc->c);
834  tgc_mag_d = MAGNITUDE(tgc->d);
835 
836  avg_diameter = tgc_mag_a + tgc_mag_b + tgc_mag_c + tgc_mag_d;
837  avg_diameter /= 2.0;
838  point_spacing = solid_point_spacing(gvp, avg_diameter);
839  }
840  break;
841  case DB5_MINORTYPE_BRLCAD_BOT:
842  point_spacing = view_avg_sample_spacing(gvp);
843  break;
844  case DB5_MINORTYPE_BRLCAD_BREP: {
845  struct rt_brep_internal *bi;
846 
847  RT_CK_DB_INTERNAL(ip);
848  bi = (struct rt_brep_internal *)ip->idb_ptr;
849  RT_BREP_CK_MAGIC(bi);
850 
851  point_spacing = solid_point_spacing(gvp,
852  brep_est_avg_curve_len(bi) * M_2_PI * 2.0);
853  }
854  break;
855  default:
856  point_spacing = solid_point_spacing(gvp, sp->s_size);
857  }
858  } else {
859  point_spacing = solid_point_spacing(gvp, sp->s_size);
860  }
861 
862  return point_spacing;
863 }
864 
865 
866 static fastf_t
867 draw_solid_wireframe(struct solid *sp, struct db_i *dbip, struct db_tree_state *tsp, struct bview *gvp)
868 {
869  int ret;
870  struct bu_list vhead;
871  struct rt_db_internal dbintern;
872  struct rt_db_internal *ip = &dbintern;
873 
874  BU_LIST_INIT(&vhead);
875  ret = -1;
876 
877  ret = rt_db_get_internal(ip, DB_FULL_PATH_CUR_DIR(&sp->s_fullpath),
878  dbip, sp->s_mat, &rt_uniresource);
879 
880  if (ret < 0) {
881  return -1;
882  }
883 
884  if (gvp && gvp->gv_adaptive_plot && ip->idb_meth->ft_adaptive_plot) {
885  struct rt_view_info info;
886 
887  info.vhead = &vhead;
888  info.tol = tsp->ts_tol;
889 
890  info.point_spacing = solid_point_spacing_for_view(sp, ip, gvp);
891 
892  info.curve_spacing = sp->s_size / 2.0;
893 
894  info.point_spacing /= gvp->gv_point_scale;
895  info.curve_spacing /= gvp->gv_curve_scale;
896 
897  ret = ip->idb_meth->ft_adaptive_plot(ip, &info);
898  } else if (ip->idb_meth->ft_plot) {
899  ret = ip->idb_meth->ft_plot(&vhead, ip, tsp->ts_ttol,
900  tsp->ts_tol, NULL);
901  }
902 
904 
905  if (ret < 0) {
906  bu_log("%s: plot failure\n", DB_FULL_PATH_CUR_DIR(&sp->s_fullpath)->d_namep);
907 
908  return -1;
909  }
910 
911  /* add plot to solid */
912  solid_append_vlist(sp, (struct bn_vlist *)&vhead);
913 
914  return 0;
915 }
916 
917 
918 int
919 redraw_solid(struct solid *sp, struct db_i *dbip, struct db_tree_state *tsp, struct bview *gvp)
920 {
921  if (sp->s_dmode == _GED_WIREFRAME) {
922  /* replot wireframe */
923  if (BU_LIST_NON_EMPTY(&sp->s_vlist)) {
924  RT_FREE_VLIST(&sp->s_vlist);
925  }
926  return draw_solid_wireframe(sp, dbip, tsp, gvp);
927  }
928  return 0;
929 }
930 
931 
932 int
933 dl_redraw(struct display_list *gdlp, struct db_i *dbip, struct db_tree_state *tsp, struct bview *gvp, void (*callback)(struct display_list *))
934 {
935  int ret = 0;
936  struct solid *sp;
937  for (BU_LIST_FOR(sp, solid, &gdlp->dl_headSolid)) {
938  ret += redraw_solid(sp, dbip, tsp, gvp);
939  }
940  if (callback != GED_CREATE_VLIST_CALLBACK_PTR_NULL)
941  (*callback)(gdlp);
942  return ret;
943 }
944 
945 union tree *
947  struct db_tree_state *tsp,
948  const struct db_full_path *pathp,
949  struct rt_db_internal *ip,
950  void *client_data)
951 {
952  point_t min, max;
953  struct solid *sp;
954  union tree *curtree;
955  struct bview_client_data *bview_data = (struct bview_client_data *)client_data;
956 
957  RT_CK_DB_INTERNAL(ip);
958  RT_CK_TESS_TOL(tsp->ts_ttol);
959  BN_CK_TOL(tsp->ts_tol);
960  RT_CK_RESOURCE(tsp->ts_resp);
961 
962  VSETALL(min, INFINITY);
963  VSETALL(max, -INFINITY);
964 
965  if (!bview_data) {
966  return TREE_NULL;
967  }
968 
969  if (RT_G_DEBUG & DEBUG_TREEWALK) {
970  char *sofar = db_path_to_string(pathp);
971 
972  bu_log("append_solid_to_display_list(%s) path='%s'\n", ip->idb_meth->ft_name, sofar);
973 
974  bu_free((void *)sofar, "path string");
975  }
976 
977  /* create solid */
978  GET_SOLID(sp, &(((struct solid *)bview_data->freesolid)->l));
979 
980  sp->s_size = 0;
981  VSETALL(sp->s_center, 0.0);
982 
983  if (ip->idb_meth->ft_bbox) {
984  if (ip->idb_meth->ft_bbox(ip, &min, &max, tsp->ts_tol) < 0) {
985  bu_log("%s: plot failure\n", DB_FULL_PATH_CUR_DIR(pathp)->d_namep);
986 
987  return TREE_NULL;
988  }
989 
990  sp->s_center[X] = (min[X] + max[X]) * 0.5;
991  sp->s_center[Y] = (min[Y] + max[Y]) * 0.5;
992  sp->s_center[Z] = (min[Z] + max[Z]) * 0.5;
993 
994  sp->s_size = max[X] - min[X];
995  V_MAX(sp->s_size, max[Y] - min[Y]);
996  V_MAX(sp->s_size, max[Z] - min[Z]);
997  } else if (ip->idb_meth->ft_plot) {
998  /* As a fallback for primitives that don't have a bbox function, use
999  * the old bounding method of calculating a plot for the primitive and
1000  * using the extent of the plotted segments as the bounds.
1001  */
1002  int plot_status;
1003  struct bu_list vhead;
1004  struct bn_vlist *vp;
1005 
1006  BU_LIST_INIT(&vhead);
1007 
1008  plot_status = ip->idb_meth->ft_plot(&vhead, ip, tsp->ts_ttol,
1009  tsp->ts_tol, NULL);
1010 
1011  if (plot_status < 0) {
1012  bu_log("%s: plot failure\n", DB_FULL_PATH_CUR_DIR(pathp)->d_namep);
1013 
1014  return TREE_NULL;
1015  }
1016 
1017  solid_append_vlist(sp, (struct bn_vlist *)&vhead);
1018 
1019  bound_solid(sp);
1020 
1021  while (BU_LIST_WHILE(vp, bn_vlist, &(sp->s_vlist))) {
1022  BU_LIST_DEQUEUE(&vp->l);
1023  bu_free(vp, "solid vp");
1024  }
1025  }
1026 
1027  sp->s_vlen = 0;
1028  db_dup_full_path(&sp->s_fullpath, pathp);
1029  sp->s_flag = DOWN;
1030  sp->s_iflag = DOWN;
1031 
1032  if (bview_data->draw_solid_lines_only) {
1033  sp->s_soldash = 0;
1034  } else {
1035  sp->s_soldash = (tsp->ts_sofar & (TS_SOFAR_MINUS|TS_SOFAR_INTER));
1036  }
1037 
1038  sp->s_Eflag = 0;
1039  sp->s_regionid = tsp->ts_regionid;
1040 
1041  if (ip->idb_type == ID_GRIP) {
1042  float mater_color[3];
1043 
1044  /* Temporarily change mater color for pseudo solid to get the desired
1045  * default color.
1046  */
1047  mater_color[RED] = tsp->ts_mater.ma_color[RED];
1048  mater_color[GRN] = tsp->ts_mater.ma_color[GRN];
1049  mater_color[BLU] = tsp->ts_mater.ma_color[BLU];
1050 
1051  tsp->ts_mater.ma_color[RED] = 0;
1052  tsp->ts_mater.ma_color[GRN] = 128;
1053  tsp->ts_mater.ma_color[BLU] = 128;
1054 
1055  if (bview_data->wireframe_color_override) {
1056  solid_set_color_info(sp, (unsigned char *)&(bview_data->wireframe_color), tsp);
1057  } else {
1058  solid_set_color_info(sp, NULL, tsp);
1059  }
1060 
1061  tsp->ts_mater.ma_color[RED] = mater_color[RED];
1062  tsp->ts_mater.ma_color[GRN] = mater_color[GRN];
1063  tsp->ts_mater.ma_color[BLU] = mater_color[BLU];
1064 
1065  } else {
1066  if (bview_data->wireframe_color_override) {
1067  unsigned char wire_color[3];
1068  wire_color[RED] = (unsigned char)bview_data->wireframe_color[RED];
1069  wire_color[GRN] = (unsigned char)bview_data->wireframe_color[GRN];
1070  wire_color[BLU] = (unsigned char)bview_data->wireframe_color[BLU];
1071  solid_set_color_info(sp, wire_color, tsp);
1072  } else {
1073  solid_set_color_info(sp, NULL, tsp);
1074  }
1075  }
1076 
1077  sp->s_dlist = 0;
1078  sp->s_transparency = bview_data->transparency;
1079  sp->s_dmode = bview_data->dmode;
1080  sp->s_hiddenLine = bview_data->hiddenLine;
1081  MAT_COPY(sp->s_mat, tsp->ts_mat);
1082 
1083  /* append solid to display list */
1085  BU_LIST_APPEND(bview_data->gdlp->dl_headSolid.back, &sp->l);
1087 
1088  /* indicate success by returning something other than TREE_NULL */
1089  RT_GET_TREE(curtree, tsp->ts_resp);
1090  curtree->tr_op = OP_NOP;
1091 
1092  return curtree;
1093 }
1094 
1095 static void
1096 solid_copy_vlist(struct solid *sp, struct bn_vlist *vlist)
1097 {
1098  BU_LIST_INIT(&(sp->s_vlist));
1099  rt_vlist_copy(&(sp->s_vlist), (struct bu_list *)vlist);
1100  sp->s_vlen = bn_vlist_cmd_cnt((struct bn_vlist *)(&(sp->s_vlist)));
1101 }
1102 
1103 int invent_solid(struct bu_list *hdlp, struct db_i *dbip,
1104  void (*callback_create)(struct display_list *), void (*callback_free)(unsigned int, int),
1105  char *name, struct bu_list *vhead, long int rgb, int copy, fastf_t transparency, int dmode,
1106  struct solid *freesolid, int csoltab)
1107 {
1108  struct directory *dp;
1109  struct solid *sp;
1110  struct display_list *gdlp;
1111  unsigned char type='0';
1112 
1113  if (dbip == DBI_NULL)
1114  return 0;
1115 
1116  if ((dp = db_lookup(dbip, name, LOOKUP_QUIET)) != RT_DIR_NULL) {
1117  if (dp->d_addr != RT_DIR_PHONY_ADDR) {
1118  bu_log("invent_solid(%s) would clobber existing database entry, ignored\n", name);
1119  return -1;
1120  }
1121 
1122  /*
1123  * Name exists from some other overlay,
1124  * zap any associated solids
1125  */
1126  dl_erasePathFromDisplay(hdlp, dbip, callback_free, name, 0, freesolid);
1127  }
1128  /* Need to enter phony name in directory structure */
1129  dp = db_diradd(dbip, name, RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&type);
1130 
1131  /* Obtain a fresh solid structure, and fill it in */
1132  GET_SOLID(sp, &freesolid->l);
1133 
1134  if (copy) {
1135  solid_copy_vlist(sp, (struct bn_vlist *)vhead);
1136  } else {
1137  solid_append_vlist(sp, (struct bn_vlist *)vhead);
1138  BU_LIST_INIT(vhead);
1139  }
1140  bound_solid(sp);
1141 
1142  /* set path information -- this is a top level node */
1143  db_add_node_to_full_path(&sp->s_fullpath, dp);
1144 
1145  gdlp = dl_addToDisplay(hdlp, dbip, name);
1146 
1147  sp->s_iflag = DOWN;
1148  sp->s_soldash = 0;
1149  sp->s_Eflag = 1; /* Can't be solid edited! */
1150  sp->s_color[0] = sp->s_basecolor[0] = (rgb>>16) & 0xFF;
1151  sp->s_color[1] = sp->s_basecolor[1] = (rgb>> 8) & 0xFF;
1152  sp->s_color[2] = sp->s_basecolor[2] = (rgb) & 0xFF;
1153  sp->s_regionid = 0;
1154  sp->s_dlist = 0;
1155 
1156  sp->s_uflag = 0;
1157  sp->s_dflag = 0;
1158  sp->s_cflag = 0;
1159  sp->s_wflag = 0;
1160 
1161  sp->s_transparency = transparency;
1162  sp->s_dmode = dmode;
1163 
1164  /* Solid successfully drawn, add to linked list of solid structs */
1165  BU_LIST_APPEND(gdlp->dl_headSolid.back, &sp->l);
1166 
1167  if (csoltab)
1168  color_soltab(sp);
1169 
1170  if (callback_create != GED_CREATE_VLIST_CALLBACK_PTR_NULL)
1171  (*callback_create)(gdlp);
1172 
1173  return 0; /* OK */
1174 
1175 }
1176 
1177 int
1178 dl_set_illum(struct display_list *gdlp, const char *obj, int illum)
1179 {
1180  int found = 0;
1181  struct solid *sp;
1182 
1183  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
1184  size_t i;
1185 
1186  for (i = 0; i < sp->s_fullpath.fp_len; ++i) {
1187  if (*obj == *DB_FULL_PATH_GET(&sp->s_fullpath, i)->d_namep &&
1188  BU_STR_EQUAL(obj, DB_FULL_PATH_GET(&sp->s_fullpath, i)->d_namep)) {
1189  found = 1;
1190  if (illum)
1191  sp->s_iflag = UP;
1192  else
1193  sp->s_iflag = DOWN;
1194  }
1195  }
1196  }
1197  return found;
1198 }
1199 
1200 void
1201 dl_set_iflag(struct bu_list *hdlp, int iflag)
1202 {
1203  struct display_list *gdlp;
1204  struct display_list *next_gdlp;
1205  struct solid *sp;
1206  /* calculate the bounding for of all solids being displayed */
1207  gdlp = BU_LIST_NEXT(display_list, hdlp);
1208  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
1209  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
1210 
1211  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
1212  sp->s_iflag = iflag;
1213  }
1214 
1215  gdlp = next_gdlp;
1216  }
1217 }
1218 
1219 void
1220 dl_set_flag(struct bu_list *hdlp, int flag)
1221 {
1222  struct display_list *gdlp;
1223  struct display_list *next_gdlp;
1224  struct solid *sp;
1225  /* calculate the bounding for of all solids being displayed */
1226  gdlp = BU_LIST_NEXT(display_list, hdlp);
1227  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
1228  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
1229 
1230  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
1231  sp->s_flag = flag;
1232  }
1233 
1234  gdlp = next_gdlp;
1235  }
1236 }
1237 
1238 void
1239 dl_set_wflag(struct bu_list *hdlp, int wflag)
1240 {
1241  struct display_list *gdlp;
1242  struct display_list *next_gdlp;
1243  struct solid *sp;
1244  /* calculate the bounding for of all solids being displayed */
1245  gdlp = BU_LIST_NEXT(display_list, hdlp);
1246  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
1247  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
1248 
1249  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
1250  sp->s_wflag = wflag;
1251  }
1252 
1253  gdlp = next_gdlp;
1254  }
1255 }
1256 
1257 void
1258 dl_zap(struct bu_list *hdlp, struct db_i *dbip, void (*callback)(unsigned int, int), struct solid *freesolid)
1259 {
1260  struct solid *sp;
1261  struct display_list *gdlp;
1262  struct directory *dp;
1263 
1264  while (BU_LIST_WHILE(gdlp, display_list, hdlp)) {
1266  (*callback)(BU_LIST_FIRST(solid, &gdlp->dl_headSolid)->s_dlist,
1267  BU_LIST_LAST(solid, &gdlp->dl_headSolid)->s_dlist -
1268  BU_LIST_FIRST(solid, &gdlp->dl_headSolid)->s_dlist + 1);
1269 
1270  while (BU_LIST_WHILE(sp, solid, &gdlp->dl_headSolid)) {
1271  dp = FIRST_SOLID(sp);
1272  RT_CK_DIR(dp);
1273  if (dp->d_addr == RT_DIR_PHONY_ADDR) {
1274  if (db_dirdelete(dbip, dp) < 0) {
1275  bu_log("ged_zap: db_dirdelete failed\n");
1276  }
1277  }
1278 
1279  BU_LIST_DEQUEUE(&sp->l);
1280  FREE_SOLID(sp, &freesolid->l);
1281  }
1282 
1283  BU_LIST_DEQUEUE(&gdlp->l);
1284  bu_vls_free(&gdlp->dl_path);
1285  free((void *)gdlp);
1286  }
1287 }
1288 
1289 int
1290 dl_how(struct bu_list *hdlp, struct bu_vls *vls, struct directory **dpp, int both)
1291 {
1292  size_t i;
1293  struct display_list *gdlp;
1294  struct display_list *next_gdlp;
1295  struct solid *sp;
1296  struct directory **tmp_dpp;
1297 
1298  gdlp = BU_LIST_NEXT(display_list, hdlp);
1299  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
1300  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
1301 
1302  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
1303  for (i = 0, tmp_dpp = dpp;
1304  i < sp->s_fullpath.fp_len && *tmp_dpp != RT_DIR_NULL;
1305  ++i, ++tmp_dpp) {
1306  if (sp->s_fullpath.fp_names[i] != *tmp_dpp)
1307  break;
1308  }
1309 
1310  if (*tmp_dpp != RT_DIR_NULL)
1311  continue;
1312 
1313 
1314  /* found a match */
1315  if (sp->s_hiddenLine) {
1316  if (both)
1317  bu_vls_printf(vls, "%d 1", _GED_HIDDEN_LINE);
1318  else
1319  bu_vls_printf(vls, "%d", _GED_HIDDEN_LINE);
1320  } else {
1321  if (both)
1322  bu_vls_printf(vls, "%d %g", sp->s_dmode, sp->s_transparency);
1323  else
1324  bu_vls_printf(vls, "%d", sp->s_dmode);
1325  }
1326 
1327  return 1;
1328  }
1329 
1330  gdlp = next_gdlp;
1331  }
1332 
1333  return 0;
1334 }
1335 
1336 
1337 void
1338 dl_plot(struct bu_list *hdlp, FILE *fp, mat_t model2view, int floating, mat_t center, fastf_t scale, int Three_D, int Z_clip)
1339 {
1340  struct display_list *gdlp;
1341  struct display_list *next_gdlp;
1342  struct solid *sp;
1343  struct bn_vlist *vp;
1344  static vect_t clipmin, clipmax;
1345  static vect_t last; /* last drawn point */
1346  static vect_t fin;
1347  static vect_t start;
1348  int Dashing; /* linetype is dashed */
1349 
1350  if (floating) {
1351  pd_3space(fp,
1352  -center[MDX] - scale,
1353  -center[MDY] - scale,
1354  -center[MDZ] - scale,
1355  -center[MDX] + scale,
1356  -center[MDY] + scale,
1357  -center[MDZ] + scale);
1358  Dashing = 0;
1359  pl_linmod(fp, "solid");
1360 
1361  gdlp = BU_LIST_NEXT(display_list, hdlp);
1362  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
1363  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
1364 
1365  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
1366  /* Could check for differences from last color */
1367  pl_color(fp,
1368  sp->s_color[0],
1369  sp->s_color[1],
1370  sp->s_color[2]);
1371  if (Dashing != sp->s_soldash) {
1372  if (sp->s_soldash)
1373  pl_linmod(fp, "dotdashed");
1374  else
1375  pl_linmod(fp, "solid");
1376  Dashing = sp->s_soldash;
1377  }
1378  rt_vlist_to_uplot(fp, &(sp->s_vlist));
1379  }
1380 
1381  gdlp = next_gdlp;
1382  }
1383 
1384  return;
1385  }
1386  /*
1387  * Integer output version, either 2-D or 3-D.
1388  * Viewing region is from -1.0 to +1.0
1389  * which is mapped to integer space -2048 to +2048 for plotting.
1390  * Compute the clipping bounds of the screen in view space.
1391  */
1392  clipmin[X] = -1.0;
1393  clipmax[X] = 1.0;
1394  clipmin[Y] = -1.0;
1395  clipmax[Y] = 1.0;
1396  if (Z_clip) {
1397  clipmin[Z] = -1.0;
1398  clipmax[Z] = 1.0;
1399  } else {
1400  clipmin[Z] = -1.0e20;
1401  clipmax[Z] = 1.0e20;
1402  }
1403 
1404  if (Three_D)
1405  pl_3space(fp, (int)DG_GED_MIN, (int)DG_GED_MIN, (int)DG_GED_MIN, (int)DG_GED_MAX, (int)DG_GED_MAX, (int)DG_GED_MAX);
1406  else
1407  pl_space(fp, (int)DG_GED_MIN, (int)DG_GED_MIN, (int)DG_GED_MAX, (int)DG_GED_MAX);
1408  pl_erase(fp);
1409  Dashing = 0;
1410  pl_linmod(fp, "solid");
1411 
1412  gdlp = BU_LIST_NEXT(display_list, hdlp);
1413  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
1414  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
1415 
1416  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
1417  if (Dashing != sp->s_soldash) {
1418  if (sp->s_soldash)
1419  pl_linmod(fp, "dotdashed");
1420  else
1421  pl_linmod(fp, "solid");
1422  Dashing = sp->s_soldash;
1423  }
1424  for (BU_LIST_FOR(vp, bn_vlist, &(sp->s_vlist))) {
1425  int i;
1426  int nused = vp->nused;
1427  int *cmd = vp->cmd;
1428  point_t *pt = vp->pt;
1429  for (i = 0; i < nused; i++, cmd++, pt++) {
1430  switch (*cmd) {
1431  case BN_VLIST_POLY_START:
1433  case BN_VLIST_TRI_START:
1434  case BN_VLIST_TRI_VERTNORM:
1435  continue;
1436  case BN_VLIST_POLY_MOVE:
1437  case BN_VLIST_LINE_MOVE:
1438  case BN_VLIST_TRI_MOVE:
1439  /* Move, not draw */
1440  MAT4X3PNT(last, model2view, *pt);
1441  continue;
1442  case BN_VLIST_LINE_DRAW:
1443  case BN_VLIST_POLY_DRAW:
1444  case BN_VLIST_POLY_END:
1445  case BN_VLIST_TRI_DRAW:
1446  case BN_VLIST_TRI_END:
1447  /* draw */
1448  MAT4X3PNT(fin, model2view, *pt);
1449  VMOVE(start, last);
1450  VMOVE(last, fin);
1451  break;
1452  }
1453  if (bn_ray_vclip(start, fin, clipmin, clipmax) == 0)
1454  continue;
1455 
1456  if (Three_D) {
1457  /* Could check for differences from last color */
1458  /* Could check for differences from last color */
1459  pl_color(fp,
1460  sp->s_color[0],
1461  sp->s_color[1],
1462  sp->s_color[2]);
1463  pl_3line(fp,
1464  (int)(start[X] * DG_GED_MAX),
1465  (int)(start[Y] * DG_GED_MAX),
1466  (int)(start[Z] * DG_GED_MAX),
1467  (int)(fin[X] * DG_GED_MAX),
1468  (int)(fin[Y] * DG_GED_MAX),
1469  (int)(fin[Z] * DG_GED_MAX));
1470  } else {
1471  pl_line(fp,
1472  (int)(start[0] * DG_GED_MAX),
1473  (int)(start[1] * DG_GED_MAX),
1474  (int)(fin[0] * DG_GED_MAX),
1475  (int)(fin[1] * DG_GED_MAX));
1476  }
1477  }
1478  }
1479  }
1480 
1481  gdlp = next_gdlp;
1482  }
1483 }
1484 
1485 
1486 struct coord {
1487  short x;
1488  short y;
1489 };
1490 
1491 struct stroke {
1492  struct coord pixel; /* starting scan, nib */
1493  short xsign; /* 0 or +1 */
1494  short ysign; /* -1, 0, or +1 */
1495  int ymajor; /* true if Y is major dir. */
1496  short major; /* major dir delta (nonneg) */
1497  short minor; /* minor dir delta (nonneg) */
1498  short e; /* DDA error accumulator */
1499  short de; /* increment for `e' */
1500 };
1501 
1502 /*
1503  * Method:
1504  * Modified Bresenham algorithm. Guaranteed to mark a dot for
1505  * a zero-length stroke.
1506  */
1507 static void
1508 raster(unsigned char **image, struct stroke *vp, unsigned char *color, size_t size)
1509 {
1510  size_t dy; /* raster within active band */
1511 
1512  /*
1513  * Write the color of this vector on all pixels.
1514  */
1515  for (dy = vp->pixel.y; dy <= size;) {
1516 
1517  /* set the appropriate pixel in the buffer to color */
1518  image[size-dy][vp->pixel.x*3] = color[0];
1519  image[size-dy][vp->pixel.x*3+1] = color[1];
1520  image[size-dy][vp->pixel.x*3+2] = color[2];
1521 
1522  if (vp->major-- == 0)
1523  return; /* Done */
1524 
1525  if (vp->e < 0) {
1526  /* advance major & minor */
1527  dy += vp->ysign;
1528  vp->pixel.x += vp->xsign;
1529  vp->e += vp->de;
1530  } else {
1531  /* advance major only */
1532  if (vp->ymajor) /* Y is major dir */
1533  ++dy;
1534  else /* X is major dir */
1535  vp->pixel.x += vp->xsign;
1536  vp->e -= vp->minor;
1537  }
1538  }
1539 }
1540 
1541 static void
1542 draw_stroke(unsigned char **image, struct coord *coord1, struct coord *coord2, unsigned char *color, size_t size)
1543 {
1544  struct stroke cur_stroke;
1545  struct stroke *vp = &cur_stroke;
1546 
1547  /* arrange for pt1 to have the smaller Y-coordinate: */
1548  if (coord1->y > coord2->y) {
1549  struct coord *temp; /* temporary for swap */
1550 
1551  temp = coord1; /* swap pointers */
1552  coord1 = coord2;
1553  coord2 = temp;
1554  }
1555 
1556  /* set up DDA parameters for stroke */
1557  vp->pixel = *coord1; /* initial pixel */
1558  vp->major = coord2->y - vp->pixel.y; /* always nonnegative */
1559  vp->ysign = vp->major ? 1 : 0;
1560  vp->minor = coord2->x - vp->pixel.x;
1561  vp->xsign = vp->minor ? (vp->minor > 0 ? 1 : -1) : 0;
1562  if (vp->xsign < 0)
1563  vp->minor = -vp->minor;
1564 
1565  /* if Y is not really major, correct the assignments */
1566  vp->ymajor = vp->minor <= vp->major;
1567  if (!vp->ymajor) {
1568  short temp; /* temporary for swap */
1569 
1570  temp = vp->minor;
1571  vp->minor = vp->major;
1572  vp->major = temp;
1573  }
1574 
1575  vp->e = vp->major / 2 - vp->minor; /* initial DDA error */
1576  vp->de = vp->major - vp->minor;
1577 
1578  raster(image, vp, color, size);
1579 }
1580 
1581 
1582 static void
1583 draw_png_solid(fastf_t perspective, unsigned char **image, struct solid *sp, matp_t psmat, size_t size, size_t half_size)
1584 {
1585  static vect_t last;
1586  point_t clipmin = {-1.0, -1.0, -MAX_FASTF};
1587  point_t clipmax = {1.0, 1.0, MAX_FASTF};
1588  struct bn_vlist *tvp;
1589  point_t *pt_prev=NULL;
1590  fastf_t dist_prev=1.0;
1591  fastf_t dist;
1592  struct bn_vlist *vp = (struct bn_vlist *)&sp->s_vlist;
1593  fastf_t delta;
1594  struct coord coord1;
1595  struct coord coord2;
1596 
1597  /* delta is used in clipping to insure clipped endpoint is slightly
1598  * in front of eye plane (perspective mode only).
1599  * This value is a SWAG that seems to work OK.
1600  */
1601  delta = psmat[15]*0.0001;
1602  if (delta < 0.0)
1603  delta = -delta;
1604  if (delta < SQRT_SMALL_FASTF)
1606 
1607  for (BU_LIST_FOR(tvp, bn_vlist, &vp->l)) {
1608  int i;
1609  int nused = tvp->nused;
1610  int *cmd = tvp->cmd;
1611  point_t *pt = tvp->pt;
1612  for (i = 0; i < nused; i++, cmd++, pt++) {
1613  static vect_t start, fin;
1614  switch (*cmd) {
1615  case BN_VLIST_POLY_START:
1617  case BN_VLIST_TRI_START:
1618  case BN_VLIST_TRI_VERTNORM:
1619  continue;
1620  case BN_VLIST_POLY_MOVE:
1621  case BN_VLIST_LINE_MOVE:
1622  case BN_VLIST_TRI_MOVE:
1623  /* Move, not draw */
1624  if (perspective > 0) {
1625  /* cannot apply perspective transformation to
1626  * points behind eye plane!!!!
1627  */
1628  dist = VDOT(*pt, &psmat[12]) + psmat[15];
1629  if (dist <= 0.0) {
1630  pt_prev = pt;
1631  dist_prev = dist;
1632  continue;
1633  } else {
1634  MAT4X3PNT(last, psmat, *pt);
1635  dist_prev = dist;
1636  pt_prev = pt;
1637  }
1638  } else
1639  MAT4X3PNT(last, psmat, *pt);
1640  continue;
1641  case BN_VLIST_POLY_DRAW:
1642  case BN_VLIST_POLY_END:
1643  case BN_VLIST_LINE_DRAW:
1644  case BN_VLIST_TRI_DRAW:
1645  case BN_VLIST_TRI_END:
1646  /* draw */
1647  if (perspective > 0) {
1648  /* cannot apply perspective transformation to
1649  * points behind eye plane!!!!
1650  */
1651  dist = VDOT(*pt, &psmat[12]) + psmat[15];
1652  if (dist <= 0.0) {
1653  if (dist_prev <= 0.0) {
1654  /* nothing to plot */
1655  dist_prev = dist;
1656  pt_prev = pt;
1657  continue;
1658  } else {
1659  if (pt_prev) {
1660  fastf_t alpha;
1661  vect_t diff;
1662  point_t tmp_pt;
1663 
1664  /* clip this end */
1665  VSUB2(diff, *pt, *pt_prev);
1666  alpha = (dist_prev - delta) / (dist_prev - dist);
1667  VJOIN1(tmp_pt, *pt_prev, alpha, diff);
1668  MAT4X3PNT(fin, psmat, tmp_pt);
1669  }
1670  }
1671  } else {
1672  if (dist_prev <= 0.0) {
1673  if (pt_prev) {
1674  fastf_t alpha;
1675  vect_t diff;
1676  point_t tmp_pt;
1677 
1678  /* clip other end */
1679  VSUB2(diff, *pt, *pt_prev);
1680  alpha = (-dist_prev + delta) / (dist - dist_prev);
1681  VJOIN1(tmp_pt, *pt_prev, alpha, diff);
1682  MAT4X3PNT(last, psmat, tmp_pt);
1683  MAT4X3PNT(fin, psmat, *pt);
1684  }
1685  } else {
1686  MAT4X3PNT(fin, psmat, *pt);
1687  }
1688  }
1689  } else
1690  MAT4X3PNT(fin, psmat, *pt);
1691  VMOVE(start, last);
1692  VMOVE(last, fin);
1693  break;
1694  }
1695 
1696  if (bn_ray_vclip(start, fin, clipmin, clipmax) == 0)
1697  continue;
1698 
1699  coord1.x = start[0] * half_size + half_size;
1700  coord1.y = start[1] * half_size + half_size;
1701  coord2.x = fin[0] * half_size + half_size;
1702  coord2.y = fin[1] * half_size + half_size;
1703  draw_stroke(image, &coord1, &coord2, sp->s_color, size);
1704  }
1705  }
1706 }
1707 
1708 
1709 void
1710 dl_png(struct bu_list *hdlp, mat_t model2view, fastf_t perspective, vect_t eye_pos, size_t size, size_t half_size, unsigned char **image)
1711 {
1712  struct display_list *gdlp;
1713  struct display_list *next_gdlp;
1714  mat_t newmat;
1715  matp_t mat;
1716  mat_t perspective_mat;
1717  struct solid *sp;
1718 
1719  mat = model2view;
1720 
1721  if (0 < perspective) {
1722  point_t l, h;
1723 
1724  VSET(l, -1.0, -1.0, -1.0);
1725  VSET(h, 1.0, 1.0, 200.0);
1726 
1727  if (ZERO(eye_pos[Z] - 1.0)) {
1728  /* This way works, with reasonable Z-clipping */
1729  persp_mat(perspective_mat, perspective,
1730  (fastf_t)1.0f, (fastf_t)0.01f, (fastf_t)1.0e10f, (fastf_t)1.0f);
1731  } else {
1732  /* This way does not have reasonable Z-clipping,
1733  * but includes shear, for GDurf's testing.
1734  */
1735  deering_persp_mat(perspective_mat, l, h, eye_pos);
1736  }
1737 
1738  bn_mat_mul(newmat, perspective_mat, mat);
1739  mat = newmat;
1740  }
1741 
1742  gdlp = BU_LIST_NEXT(display_list, hdlp);
1743  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
1744  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
1745 
1746  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
1747  draw_png_solid(perspective, image, sp, mat, size, half_size);
1748  }
1749 
1750  gdlp = next_gdlp;
1751  }
1752 }
1753 
1754 static struct bu_structparse polygon_desc[] = {
1755  {"%d", 1, "magic", bu_offsetof(struct polygon_header, magic), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
1756  {"%d", 1, "ident", bu_offsetof(struct polygon_header, ident), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
1757  {"%d", 1, "interior", bu_offsetof(struct polygon_header, interior), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
1758  {"%f", 3, "normal", bu_offsetof(struct polygon_header, normal), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
1759  {"%c", 3, "color", bu_offsetof(struct polygon_header, color), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
1760  {"%d", 1, "npts", bu_offsetof(struct polygon_header, npts), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
1761  {"", 0, NULL, 0, BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }
1762 };
1763 
1764 static struct bu_structparse vertex_desc[] = {
1765  {"%f", 3, "vertex", 0, BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
1766  {"", 0, (char *)0, 0, BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }
1767 };
1768 
1769 void
1770 dl_polybinout(struct bu_list *hdlp, struct polygon_header *ph, FILE *fp)
1771 {
1772  int pno = 1;
1773 
1774  struct display_list *gdlp;
1775  struct display_list *next_gdlp;
1776  struct solid *sp;
1777  struct bn_vlist *vp;
1778 #define MAX_VERTS 10000
1779  vect_t verts[MAX_VERTS];
1780  struct bu_external obuf;
1781 
1782  gdlp = BU_LIST_NEXT(display_list, hdlp);
1783  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
1784  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
1785 
1786  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
1787  for (BU_LIST_FOR(vp, bn_vlist, &(sp->s_vlist))) {
1788  int i;
1789  int nused = vp->nused;
1790  int *cmd = vp->cmd;
1791  point_t *pt = vp->pt;
1792  for (i = 0; i < nused; i++, cmd++, pt++) {
1793  /* For each polygon, spit it out. Ignore vectors */
1794  switch (*cmd) {
1795  case BN_VLIST_LINE_MOVE:
1796  /* Move, start line */
1797  break;
1798  case BN_VLIST_LINE_DRAW:
1799  /* Draw line */
1800  break;
1802  case BN_VLIST_TRI_VERTNORM:
1803  /* Ignore per-vertex normal */
1804  break;
1805  case BN_VLIST_POLY_START:
1806  case BN_VLIST_TRI_START:
1807  /* Start poly marker & normal, followed by POLY_MOVE */
1809  ph->ident = pno++;
1810  ph->interior = 0;
1811  memcpy(ph->color, sp->s_basecolor, 3);
1812  ph->npts = 0;
1813  /* Set surface normal (vl_pnt points outward) */
1814  VMOVE(ph->normal, *pt);
1815  break;
1816  case BN_VLIST_POLY_MOVE:
1817  case BN_VLIST_TRI_MOVE:
1818  /* Start of polygon, has first point */
1819  /* fall through to... */
1820  case BN_VLIST_POLY_DRAW:
1821  case BN_VLIST_TRI_DRAW:
1822  /* Polygon Draw */
1823  if (ph->npts >= MAX_VERTS) {
1824  bu_log("excess vertex skipped\n");
1825  break;
1826  }
1827  VMOVE(verts[ph->npts], *pt);
1828  ph->npts++;
1829  break;
1830  case BN_VLIST_POLY_END:
1831  case BN_VLIST_TRI_END:
1832  /*
1833  * End Polygon. Point given is repeat of
1834  * first one, ignore it.
1835  * XXX note: if poly_markers was not set,
1836  * XXX poly will end with next POLY_MOVE.
1837  */
1838  if (ph->npts < 3) {
1839  bu_log("polygon with %d points discarded\n", ph->npts);
1840  break;
1841  }
1842  if (bu_struct_export(&obuf, (void *)&ph, polygon_desc) < 0) {
1843  bu_log("header export error\n");
1844  break;
1845  }
1846  if (bu_struct_put(fp, &obuf) != obuf.ext_nbytes) {
1847  perror("bu_struct_put");
1848  break;
1849  }
1850  bu_free_external(&obuf);
1851  /* Now export the vertices */
1852  vertex_desc[0].sp_count = ph->npts * 3;
1853  if (bu_struct_export(&obuf, (void *)verts, vertex_desc) < 0) {
1854  bu_log("vertex export error\n");
1855  break;
1856  }
1857  if (bu_struct_put(fp, &obuf) != obuf.ext_nbytes) {
1858  perror("bu_struct_wrap_buf");
1859  break;
1860  }
1861  bu_free_external(&obuf);
1862  ph->npts = 0; /* sanity */
1863  break;
1864  }
1865  }
1866  }
1867  }
1868 
1869  gdlp = next_gdlp;
1870  }
1871 }
1872 
1873 static void
1874 ps_draw_header(FILE *fp, char *font, char *title, char *creator, int linewidth, fastf_t scale, int xoffset, int yoffset)
1875 {
1876  fprintf(fp, "%%!PS-Adobe-1.0\n\
1877 %%begin(plot)\n\
1878 %%%%DocumentFonts: %s\n",
1879  font);
1880 
1881  fprintf(fp, "%%%%Title: %s\n", title);
1882 
1883  fprintf(fp, "\
1884 %%%%Creator: %s\n\
1885 %%%%BoundingBox: 0 0 324 324 %% 4.5in square, for TeX\n\
1886 %%%%EndComments\n\
1887 \n",
1888  creator);
1889 
1890  fprintf(fp, "\
1891 %d setlinewidth\n\
1892 \n", linewidth);
1893 
1894  fprintf(fp, "\
1895 %% Sizes, made functions to avoid scaling if not needed\n\
1896 /FntH /%s findfont 80 scalefont def\n\
1897 /DFntL { /FntL /%s findfont 73.4 scalefont def } def\n\
1898 /DFntM { /FntM /%s findfont 50.2 scalefont def } def\n\
1899 /DFntS { /FntS /%s findfont 44 scalefont def } def\n\
1900 \n", font, font, font, font);
1901 
1902  fprintf(fp, "\
1903 %% line styles\n\
1904 /NV { [] 0 setdash } def %% normal vectors\n\
1905 /DV { [8] 0 setdash } def %% dotted vectors\n\
1906 /DDV { [8 8 32 8] 0 setdash } def %% dot-dash vectors\n\
1907 /SDV { [32 8] 0 setdash } def %% short-dash vectors\n\
1908 /LDV { [64 8] 0 setdash } def %% long-dash vectors\n\
1909 \n\
1910 /NEWPG {\n\
1911  %d %d translate\n\
1912  %f %f scale %% 0-4096 to 324 units (4.5 inches)\n\
1913 } def\n\
1914 \n\
1915 FntH setfont\n\
1916 NEWPG\n\
1917 ",
1918  xoffset, yoffset, scale, scale);
1919 }
1920 
1921 static void
1922 ps_draw_solid(fastf_t perspective, FILE *fp, struct solid *sp, matp_t psmat)
1923 {
1924  static vect_t last;
1925  point_t clipmin = {-1.0, -1.0, -MAX_FASTF};
1926  point_t clipmax = {1.0, 1.0, MAX_FASTF};
1927  struct bn_vlist *tvp;
1928  point_t *pt_prev=NULL;
1929  fastf_t dist_prev=1.0;
1930  fastf_t dist;
1931  struct bn_vlist *vp = (struct bn_vlist *)&sp->s_vlist;
1932  fastf_t delta;
1933 
1934  fprintf(fp, "%f %f %f setrgbcolor\n",
1935  PS_COLOR(sp->s_color[0]),
1936  PS_COLOR(sp->s_color[1]),
1937  PS_COLOR(sp->s_color[2]));
1938 
1939  /* delta is used in clipping to insure clipped endpoint is slightly
1940  * in front of eye plane (perspective mode only).
1941  * This value is a SWAG that seems to work OK.
1942  */
1943  delta = psmat[15]*0.0001;
1944  if (delta < 0.0)
1945  delta = -delta;
1946  if (delta < SQRT_SMALL_FASTF)
1948 
1949  for (BU_LIST_FOR(tvp, bn_vlist, &vp->l)) {
1950  int i;
1951  int nused = tvp->nused;
1952  int *cmd = tvp->cmd;
1953  point_t *pt = tvp->pt;
1954  for (i = 0; i < nused; i++, cmd++, pt++) {
1955  static vect_t start, fin;
1956  switch (*cmd) {
1957  case BN_VLIST_POLY_START:
1959  case BN_VLIST_TRI_START:
1960  case BN_VLIST_TRI_VERTNORM:
1961  continue;
1962  case BN_VLIST_POLY_MOVE:
1963  case BN_VLIST_LINE_MOVE:
1964  case BN_VLIST_TRI_MOVE:
1965  /* Move, not draw */
1966  if (perspective > 0) {
1967  /* cannot apply perspective transformation to
1968  * points behind eye plane!!!!
1969  */
1970  dist = VDOT(*pt, &psmat[12]) + psmat[15];
1971  if (dist <= 0.0) {
1972  pt_prev = pt;
1973  dist_prev = dist;
1974  continue;
1975  } else {
1976  MAT4X3PNT(last, psmat, *pt);
1977  dist_prev = dist;
1978  pt_prev = pt;
1979  }
1980  } else
1981  MAT4X3PNT(last, psmat, *pt);
1982  continue;
1983  case BN_VLIST_POLY_DRAW:
1984  case BN_VLIST_POLY_END:
1985  case BN_VLIST_LINE_DRAW:
1986  case BN_VLIST_TRI_DRAW:
1987  case BN_VLIST_TRI_END:
1988  /* draw */
1989  if (perspective > 0) {
1990  /* cannot apply perspective transformation to
1991  * points behind eye plane!!!!
1992  */
1993  dist = VDOT(*pt, &psmat[12]) + psmat[15];
1994  if (dist <= 0.0) {
1995  if (dist_prev <= 0.0) {
1996  /* nothing to plot */
1997  dist_prev = dist;
1998  pt_prev = pt;
1999  continue;
2000  } else {
2001  if (pt_prev) {
2002  fastf_t alpha;
2003  vect_t diff;
2004  point_t tmp_pt;
2005 
2006  /* clip this end */
2007  VSUB2(diff, *pt, *pt_prev);
2008  alpha = (dist_prev - delta) / (dist_prev - dist);
2009  VJOIN1(tmp_pt, *pt_prev, alpha, diff);
2010  MAT4X3PNT(fin, psmat, tmp_pt);
2011  }
2012  }
2013  } else {
2014  if (dist_prev <= 0.0) {
2015  if (pt_prev) {
2016  fastf_t alpha;
2017  vect_t diff;
2018  point_t tmp_pt;
2019 
2020  /* clip other end */
2021  VSUB2(diff, *pt, *pt_prev);
2022  alpha = (-dist_prev + delta) / (dist - dist_prev);
2023  VJOIN1(tmp_pt, *pt_prev, alpha, diff);
2024  MAT4X3PNT(last, psmat, tmp_pt);
2025  MAT4X3PNT(fin, psmat, *pt);
2026  }
2027  } else {
2028  MAT4X3PNT(fin, psmat, *pt);
2029  }
2030  }
2031  } else
2032  MAT4X3PNT(fin, psmat, *pt);
2033  VMOVE(start, last);
2034  VMOVE(last, fin);
2035  break;
2036  }
2037 
2038  if (bn_ray_vclip(start, fin, clipmin, clipmax) == 0)
2039  continue;
2040 
2041  fprintf(fp,
2042  "newpath %d %d moveto %d %d lineto stroke\n",
2043  PS_COORD(start[0] * 2047),
2044  PS_COORD(start[1] * 2047),
2045  PS_COORD(fin[0] * 2047),
2046  PS_COORD(fin[1] * 2047));
2047  }
2048  }
2049 }
2050 
2051 static void
2052 ps_draw_body(struct bu_list *hdlp, FILE *fp, mat_t model2view, fastf_t perspective, vect_t eye_pos)
2053 {
2054  struct display_list *gdlp;
2055  struct display_list *next_gdlp;
2056  mat_t newmat;
2057  matp_t mat;
2058  mat_t perspective_mat;
2059  struct solid *sp;
2060 
2061  mat = model2view;
2062 
2063  if (0 < perspective) {
2064  point_t l, h;
2065 
2066  VSET(l, -1.0, -1.0, -1.0);
2067  VSET(h, 1.0, 1.0, 200.0);
2068 
2069  if (ZERO(eye_pos[Z] - 1.0)) {
2070  /* This way works, with reasonable Z-clipping */
2071  persp_mat(perspective_mat, perspective,
2072  (fastf_t)1.0f, (fastf_t)0.01f, (fastf_t)1.0e10f, (fastf_t)1.0f);
2073  } else {
2074  /* This way does not have reasonable Z-clipping,
2075  * but includes shear, for GDurf's testing.
2076  */
2077  deering_persp_mat(perspective_mat, l, h, eye_pos);
2078  }
2079 
2080  bn_mat_mul(newmat, perspective_mat, mat);
2081  mat = newmat;
2082  }
2083 
2084  gdlp = BU_LIST_NEXT(display_list, hdlp);
2085  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
2086  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
2087 
2088  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
2089  ps_draw_solid(perspective, fp, sp, mat);
2090  }
2091 
2092  gdlp = next_gdlp;
2093  }
2094 }
2095 
2096 
2097 static void
2098 ps_draw_border(FILE *fp, float red, float green, float blue)
2099 {
2100  fprintf(fp, "%f %f %f setrgbcolor\n", red, green, blue);
2101  fprintf(fp, "newpath 0 0 moveto 4096 0 lineto stroke\n");
2102  fprintf(fp, "newpath 4096 0 moveto 4096 4096 lineto stroke\n");
2103  fprintf(fp, "newpath 4096 4096 moveto 0 4096 lineto stroke\n");
2104  fprintf(fp, "newpath 0 4096 moveto 0 0 lineto stroke\n");
2105 }
2106 
2107 
2108 static void
2109 ps_draw_footer(FILE *fp)
2110 {
2111  fputs("% showpage % uncomment to use raw file\n", fp);
2112  fputs("%end(plot)\n", fp);
2113 }
2114 
2115 void
2116 dl_ps(struct bu_list *hdlp, FILE *fp, int border, char *font, char *title, char *creator, int linewidth, fastf_t scale, int xoffset, int yoffset, mat_t model2view, fastf_t perspective, vect_t eye_pos, float red, float green, float blue)
2117 {
2118  ps_draw_header(fp, font, title, creator, linewidth, scale, xoffset, yoffset);
2119  if (border)
2120  ps_draw_border(fp, red, green, blue);
2121  ps_draw_body(hdlp, fp, model2view, perspective, eye_pos);
2122  ps_draw_footer(fp);
2123 
2124 }
2125 
2126 
2127 void
2128 dl_print_schain(struct bu_list *hdlp, struct db_i *dbip, int lvl, int vlcmds, struct bu_vls *vls)
2129 {
2130  struct display_list *gdlp;
2131  struct display_list *next_gdlp;
2132  struct solid *sp;
2133  struct bn_vlist *vp;
2134 
2135  if (!vlcmds) {
2136  /*
2137  * Given a pointer to a member of the circularly linked list of solids
2138  * (typically the head), chase the list and print out the information
2139  * about each solid structure.
2140  */
2141  int nvlist;
2142  int npts;
2143 
2144  if (dbip == DBI_NULL) return;
2145 
2146  gdlp = BU_LIST_NEXT(display_list, hdlp);
2147  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
2148  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
2149 
2150  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
2151  if (lvl <= -2) {
2152  /* print only leaves */
2153  bu_vls_printf(vls, "%s ", LAST_SOLID(sp)->d_namep);
2154  continue;
2155  }
2156 
2157  db_path_to_vls(vls, &sp->s_fullpath);
2158 
2159  if ((lvl != -1) && (sp->s_iflag == UP))
2160  bu_vls_printf(vls, " ILLUM");
2161 
2162  bu_vls_printf(vls, "\n");
2163 
2164  if (lvl <= 0)
2165  continue;
2166 
2167  /* convert to the local unit for printing */
2168  bu_vls_printf(vls, " cent=(%.3f, %.3f, %.3f) sz=%g ",
2169  sp->s_center[X]*dbip->dbi_base2local,
2170  sp->s_center[Y]*dbip->dbi_base2local,
2171  sp->s_center[Z]*dbip->dbi_base2local,
2172  sp->s_size*dbip->dbi_base2local);
2173  bu_vls_printf(vls, "reg=%d\n", sp->s_regionid);
2174  bu_vls_printf(vls, " basecolor=(%d, %d, %d) color=(%d, %d, %d)%s%s%s\n",
2175  sp->s_basecolor[0],
2176  sp->s_basecolor[1],
2177  sp->s_basecolor[2],
2178  sp->s_color[0],
2179  sp->s_color[1],
2180  sp->s_color[2],
2181  sp->s_uflag?" U":"",
2182  sp->s_dflag?" D":"",
2183  sp->s_cflag?" C":"");
2184 
2185  if (lvl <= 1)
2186  continue;
2187 
2188  /* Print the actual vector list */
2189  nvlist = 0;
2190  npts = 0;
2191  for (BU_LIST_FOR(vp, bn_vlist, &(sp->s_vlist))) {
2192  int i;
2193  int nused = vp->nused;
2194  int *cmd = vp->cmd;
2195  point_t *pt = vp->pt;
2196 
2197  BN_CK_VLIST(vp);
2198  nvlist++;
2199  npts += nused;
2200 
2201  if (lvl <= 2)
2202  continue;
2203 
2204  for (i = 0; i < nused; i++, cmd++, pt++) {
2205  bu_vls_printf(vls, " %s (%g, %g, %g)\n",
2207  V3ARGS(*pt));
2208  }
2209  }
2210 
2211  bu_vls_printf(vls, " %d vlist structures, %d pts\n", nvlist, npts);
2212  bu_vls_printf(vls, " %d pts (via rt_ck_vlist)\n", rt_ck_vlist(&(sp->s_vlist)));
2213  }
2214 
2215  gdlp = next_gdlp;
2216  }
2217 
2218  } else {
2219  /*
2220  * Given a pointer to a member of the circularly linked list of solids
2221  * (typically the head), chase the list and print out the vlist cmds
2222  * for each structure.
2223  */
2224 
2225  if (dbip == DBI_NULL) return;
2226 
2227  gdlp = BU_LIST_NEXT(display_list, hdlp);
2228  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
2229  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
2230 
2231  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
2232  bu_vls_printf(vls, "-1 %d %d %d\n",
2233  sp->s_color[0],
2234  sp->s_color[1],
2235  sp->s_color[2]);
2236 
2237  /* Print the actual vector list */
2238  for (BU_LIST_FOR(vp, bn_vlist, &(sp->s_vlist))) {
2239  int i;
2240  int nused = vp->nused;
2241  int *cmd = vp->cmd;
2242  point_t *pt = vp->pt;
2243 
2244  BN_CK_VLIST(vp);
2245 
2246  for (i = 0; i < nused; i++, cmd++, pt++)
2247  bu_vls_printf(vls, "%d %g %g %g\n", *cmd, V3ARGS(*pt));
2248  }
2249  }
2250 
2251  gdlp = next_gdlp;
2252  }
2253 
2254  }
2255 }
2256 
2257 void
2258 dl_bitwise_and_fullpath(struct bu_list *hdlp, int flag_val)
2259 {
2260  struct display_list *gdlp;
2261  struct display_list *next_gdlp;
2262  size_t i;
2263  struct solid *sp;
2264 
2265  gdlp = BU_LIST_NEXT(display_list, hdlp);
2266  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
2267  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
2268 
2269  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
2270  for (i = 0; i < sp->s_fullpath.fp_len; i++) {
2271  DB_FULL_PATH_GET(&sp->s_fullpath, i)->d_flags &= flag_val;
2272  }
2273  }
2274 
2275  gdlp = next_gdlp;
2276  }
2277 }
2278 
2279 void
2280 dl_write_animate(struct bu_list *hdlp, FILE *fp)
2281 {
2282  struct display_list *gdlp;
2283  struct display_list *next_gdlp;
2284  size_t i;
2285  struct solid *sp;
2286 
2287  gdlp = BU_LIST_NEXT(display_list, hdlp);
2288  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
2289  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
2290 
2291  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
2292  for (i = 0; i < sp->s_fullpath.fp_len; i++) {
2293  if (!(DB_FULL_PATH_GET(&sp->s_fullpath, i)->d_flags & RT_DIR_USED)) {
2294  struct animate *anp;
2295  for (anp = DB_FULL_PATH_GET(&sp->s_fullpath, i)->d_animate; anp;
2296  anp=anp->an_forw) {
2297  db_write_anim(fp, anp);
2298  }
2299  DB_FULL_PATH_GET(&sp->s_fullpath, i)->d_flags |= RT_DIR_USED;
2300  }
2301  }
2302  }
2303 
2304  gdlp = next_gdlp;
2305  }
2306 }
2307 
2308 
2309 
2310 int
2311 dl_select(struct bu_list *hdlp, mat_t model2view, struct bu_vls *vls, double vx, double vy, double vwidth, double vheight, int rflag)
2312 {
2313  struct display_list *gdlp = NULL;
2314  struct display_list *next_gdlp = NULL;
2315  struct solid *sp = NULL;
2316  fastf_t vr = 0.0;
2317  fastf_t vmin_x = 0.0;
2318  fastf_t vmin_y = 0.0;
2319  fastf_t vmax_x = 0.0;
2320  fastf_t vmax_y = 0.0;
2321 
2322  if (rflag) {
2323  vr = vwidth;
2324  } else {
2325  vmin_x = vx;
2326  vmin_y = vy;
2327 
2328  if (vwidth > 0)
2329  vmax_x = vx + vwidth;
2330  else {
2331  vmin_x = vx + vwidth;
2332  vmax_x = vx;
2333  }
2334 
2335  if (vheight > 0)
2336  vmax_y = vy + vheight;
2337  else {
2338  vmin_y = vy + vheight;
2339  vmax_y = vy;
2340  }
2341  }
2342 
2343  gdlp = BU_LIST_NEXT(display_list, hdlp);
2344  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
2345  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
2346 
2347  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
2348  point_t vmin, vmax;
2349  struct bn_vlist *vp;
2350 
2351  vmax[X] = vmax[Y] = vmax[Z] = -INFINITY;
2352  vmin[X] = vmin[Y] = vmin[Z] = INFINITY;
2353 
2354  for (BU_LIST_FOR(vp, bn_vlist, &(sp->s_vlist))) {
2355  int j;
2356  int nused = vp->nused;
2357  int *cmd = vp->cmd;
2358  point_t *pt = vp->pt;
2359  point_t vpt;
2360  for (j = 0; j < nused; j++, cmd++, pt++) {
2361  switch (*cmd) {
2362  case BN_VLIST_POLY_START:
2364  case BN_VLIST_TRI_START:
2365  case BN_VLIST_TRI_VERTNORM:
2366  case BN_VLIST_POINT_SIZE:
2367  case BN_VLIST_LINE_WIDTH:
2368  /* attribute, not location */
2369  break;
2370  case BN_VLIST_LINE_MOVE:
2371  case BN_VLIST_LINE_DRAW:
2372  case BN_VLIST_POLY_MOVE:
2373  case BN_VLIST_POLY_DRAW:
2374  case BN_VLIST_POLY_END:
2375  case BN_VLIST_TRI_MOVE:
2376  case BN_VLIST_TRI_DRAW:
2377  case BN_VLIST_TRI_END:
2378  MAT4X3PNT(vpt, model2view, *pt);
2379  V_MIN(vmin[X], vpt[X]);
2380  V_MAX(vmax[X], vpt[X]);
2381  V_MIN(vmin[Y], vpt[Y]);
2382  V_MAX(vmax[Y], vpt[Y]);
2383  V_MIN(vmin[Z], vpt[Z]);
2384  V_MAX(vmax[Z], vpt[Z]);
2385  break;
2386  default: {
2387  bu_vls_printf(vls, "unknown vlist op %d\n", *cmd);
2388  }
2389  }
2390  }
2391  }
2392 
2393  if (rflag) {
2394  point_t vloc;
2395  vect_t diff;
2396  fastf_t mag;
2397 
2398  VSET(vloc, vx, vy, vmin[Z]);
2399  VSUB2(diff, vmin, vloc);
2400  mag = MAGNITUDE(diff);
2401 
2402  if (mag > vr)
2403  continue;
2404 
2405  VSET(vloc, vx, vy, vmax[Z]);
2406  VSUB2(diff, vmax, vloc);
2407  mag = MAGNITUDE(diff);
2408 
2409  if (mag > vr)
2410  continue;
2411 
2412  db_path_to_vls(vls, &sp->s_fullpath);
2413  bu_vls_printf(vls, "\n");
2414  } else {
2415  if (vmin_x <= vmin[X] && vmax[X] <= vmax_x &&
2416  vmin_y <= vmin[Y] && vmax[Y] <= vmax_y) {
2417  db_path_to_vls(vls, &sp->s_fullpath);
2418  bu_vls_printf(vls, "\n");
2419  }
2420  }
2421  }
2422 
2423  gdlp = next_gdlp;
2424  }
2425 
2426  return GED_OK;
2427 }
2428 
2429 int
2430 dl_select_partial(struct bu_list *hdlp, mat_t model2view, struct bu_vls *vls, double vx, double vy, double vwidth, double vheight, int rflag)
2431 {
2432  struct display_list *gdlp = NULL;
2433  struct display_list *next_gdlp = NULL;
2434  struct solid *sp = NULL;
2435  fastf_t vr = 0.0;
2436  fastf_t vmin_x = 0.0;
2437  fastf_t vmin_y = 0.0;
2438  fastf_t vmax_x = 0.0;
2439  fastf_t vmax_y = 0.0;
2440 
2441  if (rflag) {
2442  vr = vwidth;
2443  } else {
2444  vmin_x = vx;
2445  vmin_y = vy;
2446 
2447  if (vwidth > 0)
2448  vmax_x = vx + vwidth;
2449  else {
2450  vmin_x = vx + vwidth;
2451  vmax_x = vx;
2452  }
2453 
2454  if (vheight > 0)
2455  vmax_y = vy + vheight;
2456  else {
2457  vmin_y = vy + vheight;
2458  vmax_y = vy;
2459  }
2460  }
2461 
2462  gdlp = BU_LIST_NEXT(display_list, hdlp);
2463  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
2464  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
2465 
2466  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
2467  struct bn_vlist *vp;
2468 
2469  for (BU_LIST_FOR(vp, bn_vlist, &(sp->s_vlist))) {
2470  int j;
2471  int nused = vp->nused;
2472  int *cmd = vp->cmd;
2473  point_t *pt = vp->pt;
2474  point_t vpt;
2475  for (j = 0; j < nused; j++, cmd++, pt++) {
2476  switch (*cmd) {
2477  case BN_VLIST_POLY_START:
2479  case BN_VLIST_TRI_START:
2480  case BN_VLIST_TRI_VERTNORM:
2481  /* Has normal vector, not location */
2482  break;
2483  case BN_VLIST_LINE_MOVE:
2484  case BN_VLIST_LINE_DRAW:
2485  case BN_VLIST_POLY_MOVE:
2486  case BN_VLIST_POLY_DRAW:
2487  case BN_VLIST_POLY_END:
2488  case BN_VLIST_TRI_MOVE:
2489  case BN_VLIST_TRI_DRAW:
2490  case BN_VLIST_TRI_END:
2491  MAT4X3PNT(vpt, model2view, *pt);
2492 
2493  if (rflag) {
2494  point_t vloc;
2495  vect_t diff;
2496  fastf_t mag;
2497 
2498  VSET(vloc, vx, vy, vpt[Z]);
2499  VSUB2(diff, vpt, vloc);
2500  mag = MAGNITUDE(diff);
2501 
2502  if (mag > vr)
2503  continue;
2504 
2505  db_path_to_vls(vls, &sp->s_fullpath);
2506  bu_vls_printf(vls, "\n");
2507 
2508  goto solid_done;
2509  } else {
2510  if (vmin_x <= vpt[X] && vpt[X] <= vmax_x &&
2511  vmin_y <= vpt[Y] && vpt[Y] <= vmax_y) {
2512  db_path_to_vls(vls, &sp->s_fullpath);
2513  bu_vls_printf(vls, "\n");
2514 
2515  goto solid_done;
2516  }
2517  }
2518 
2519  break;
2520  default: {
2521  bu_vls_printf(vls, "unknown vlist op %d\n", *cmd);
2522  }
2523  }
2524  }
2525  }
2526 
2527  solid_done:
2528  ;
2529  }
2530 
2531  gdlp = next_gdlp;
2532  }
2533 
2534  return GED_OK;
2535 }
2536 
2537 
2538 void
2539 dl_set_transparency(struct bu_list *hdlp, struct directory **dpp, double transparency, void (*callback)(struct display_list *))
2540 {
2541  struct display_list *gdlp;
2542  struct display_list *next_gdlp;
2543  struct solid *sp;
2544  size_t i;
2545  struct directory **tmp_dpp;
2546 
2547  gdlp = BU_LIST_NEXT(display_list, hdlp);
2548  while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
2549  next_gdlp = BU_LIST_PNEXT(display_list, gdlp);
2550 
2551  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
2552  for (i = 0, tmp_dpp = dpp;
2553  i < sp->s_fullpath.fp_len && *tmp_dpp != RT_DIR_NULL;
2554  ++i, ++tmp_dpp) {
2555  if (sp->s_fullpath.fp_names[i] != *tmp_dpp)
2556  break;
2557  }
2558 
2559  if (*tmp_dpp != RT_DIR_NULL)
2560  continue;
2561 
2562  /* found a match */
2563  sp->s_transparency = transparency;
2564 
2565  }
2566 
2567  if (callback != GED_CREATE_VLIST_CALLBACK_PTR_NULL)
2568  (*callback)(gdlp);
2569 
2570  gdlp = next_gdlp;
2571  }
2572 
2573 }
2574 
2575 void
2576 dl_botdump(struct bu_list *hdlp, struct db_i *dbip, FILE *fp, int fd, char *file_ext, int output_type, int *red, int *green, int *blue, fastf_t *alpha)
2577 {
2578  int ret;
2579  mat_t mat;
2580  struct display_list *gdlp;
2581 
2582  MAT_IDN(mat);
2583 
2584  for (BU_LIST_FOR(gdlp, display_list, hdlp)) {
2585  struct solid *sp;
2586 
2587  FOR_ALL_SOLIDS(sp, &gdlp->dl_headSolid) {
2588  struct directory *dp;
2589  struct rt_db_internal intern;
2590  struct rt_bot_internal *bot;
2591 
2592  dp = sp->s_fullpath.fp_names[sp->s_fullpath.fp_len-1];
2593 
2594  /* get the internal form */
2595  ret=rt_db_get_internal(&intern, dp, dbip, mat, &rt_uniresource);
2596 
2597  if (ret < 0) {
2598  bu_log("rt_get_internal failure %d on %s\n", ret, dp->d_namep);
2599  continue;
2600  }
2601 
2602  if (ret != ID_BOT) {
2603  bu_log("%s is not a bot (ignored)\n", dp->d_namep);
2604  rt_db_free_internal(&intern);
2605  continue;
2606  }
2607 
2608  /* Write out object color */
2609  if (output_type == OTYPE_OBJ) {
2610  (*red) = sp->s_color[0];
2611  (*green) = sp->s_color[1];
2612  (*blue) = sp->s_color[2];
2613  (*alpha) = sp->s_transparency;
2614  }
2615 
2616  bot = (struct rt_bot_internal *)intern.idb_ptr;
2617  _ged_bot_dump(dp, bot, fp, fd, file_ext, dbip->dbi_filename);
2618  rt_db_free_internal(&intern);
2619  }
2620  }
2621 
2622 }
2623 
2624 
2625 /*
2626  * Local Variables:
2627  * tab-width: 8
2628  * mode: C
2629  * indent-tabs-mode: t
2630  * c-file-style: "stroustrup"
2631  * End:
2632  * ex: shiftwidth=4 tabstop=8
2633  */
void bu_vls_init(struct bu_vls *vp)
Definition: vls.c:56
#define GED_OK
Definition: ged.h:55
struct bu_list l
Definition: bview.h:46
char * d_namep
pointer to name string
Definition: raytrace.h:859
#define BU_LIST_FOR(p, structure, hp)
Definition: list.h:365
Definition: raytrace.h:800
size_t nused
elements 0..nused active
Definition: vlist.h:73
void db_add_node_to_full_path(struct db_full_path *pp, struct directory *dp)
Definition: db_fullpath.c:54
int db_dirdelete(struct db_i *, struct directory *dp)
Definition: db_lookup.c:262
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
#define BU_LIST_INSERT(old, new)
Definition: list.h:183
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
void dl_write_animate(struct bu_list *hdlp, FILE *fp)
struct bu_list l
magic, forw, back
Definition: vlist.h:72
struct bu_list dl_headSolid
head of solid list for this object
Definition: bview.h:49
char * UP
#define MAX_VERTS
short y
int(* ft_bbox)(struct rt_db_internal *, point_t *, point_t *, const struct bn_tol *)
Definition: raytrace.h:2196
fastf_t gv_curve_scale
Definition: bview.h:260
int interior
Definition: ged.h:459
void dl_ps(struct bu_list *hdlp, FILE *fp, int border, char *font, char *title, char *creator, int linewidth, fastf_t scale, int xoffset, int yoffset, mat_t model2view, fastf_t perspective, vect_t eye_pos, float red, float green, float blue)
struct mater_info ts_mater
material properties
Definition: raytrace.h:1047
void dl_erasePathFromDisplay(struct bu_list *hdlp, struct db_i *dbip, void(*callback)(unsigned int, int), const char *path, int allow_split, struct solid *freesolid)
Definition: display_list.c:204
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
void _dl_eraseAllPathsFromDisplay(struct bu_list *hdlp, struct db_i *dbip, void(*callback)(unsigned int, int), const char *path, const int skip_first, struct solid *freesolid)
Definition: display_list.c:437
#define BU_LIST_LAST(structure, hp)
Definition: list.h:306
struct display_list * gdlp
Definition: bview.h:266
size_t fp_len
Definition: db_fullpath.h:44
void db_dup_full_path(struct db_full_path *newp, const struct db_full_path *oldp)
Definition: db_fullpath.c:87
#define OP_NOP
Leaf with no effect.
Definition: raytrace.h:1132
int cmd[BN_VLIST_CHUNK]
VL_CMD_*.
Definition: vlist.h:74
int bn_vlist_cmd_cnt(struct bn_vlist *vlist)
Definition: vlist.c:34
Definition: clone.c:90
void _dl_freeDisplayListItem(struct db_i *dbip, void(*callback)(unsigned int, int), struct display_list *gdlp, struct solid *freesolid)
Definition: display_list.c:488
#define DG_GED_MAX
Definition: ged_private.h:74
void dl_plot(struct bu_list *hdlp, FILE *fp, mat_t model2view, int floating, mat_t center, fastf_t scale, int Three_D, int Z_clip)
#define ID_GRIP
Pseudo Solid Grip.
Definition: raytrace.h:480
#define VSET(a, b, c, d)
Definition: color.c:53
#define VSETALL(a, s)
Definition: color.c:54
void * freesolid
Definition: bview.h:273
void bu_semaphore_acquire(unsigned int i)
Definition: semaphore.c:180
#define RED
Definition: color.h:39
#define ID_BOT
Bag o' triangles.
Definition: raytrace.h:488
#define BU_LIST_IS_EMPTY(hp)
Definition: list.h:295
vect_t normal
Definition: ged.h:460
struct directory * db_lookup(const struct db_i *, const char *name, int noisy)
Definition: db_lookup.c:153
int ident
Definition: ged.h:458
int draw_solid_lines_only
Definition: bview.h:267
int headsolid_splitGDL(struct bu_list *hdlp, struct db_i *dbip, struct display_list *gdlp, struct db_full_path *path)
Definition: display_list.c:125
void rt_vlist_to_uplot(FILE *fp, const struct bu_list *vhead)
Definition: vlist.c:446
short ysign
void bu_free_external(struct bu_external *ep)
void pl_line(register FILE *plotfp, int px1, int py1, int px2, int py2)
Definition: plot3.c:193
Definition: bview.h:209
void rt_vlist_copy(struct bu_list *dest, const struct bu_list *src)
Definition: vlist.c:237
Header file for the BRL-CAD common definitions.
void dl_set_transparency(struct bu_list *hdlp, struct directory **dpp, double transparency, void(*callback)(struct display_list *))
short xsign
void * dl_dp
Definition: bview.h:47
#define DB_FULL_PATH_CUR_DIR(_pp)
Definition: db_fullpath.h:51
const char * rt_vlist_get_cmd_description(int cmd)
Definition: vlist.c:163
#define RT_FREE_VLIST(hd)
Definition: raytrace.h:1863
#define BU_LIST_APPEND(old, new)
Definition: list.h:197
char ma_color_valid
non-0 ==> ma_color is non-default
Definition: raytrace.h:524
void dl_botdump(struct bu_list *hdlp, struct db_i *dbip, FILE *fp, int fd, char *file_ext, int output_type, int *red, int *green, int *blue, fastf_t *alpha)
#define _GED_WIREFRAME
Definition: ged_private.h:58
#define BU_LIST_NON_EMPTY(hp)
Definition: list.h:296
void db_full_path_init(struct db_full_path *pathp)
Definition: db_fullpath.c:40
#define MAX_FASTF
Definition: defines.h:340
#define BLU
Definition: color.h:41
int wireframe_color_override
Definition: bview.h:268
short major
void pl_erase(register FILE *plotfp)
Definition: plot3.c:271
#define HIDDEN
Definition: common.h:86
#define BN_VLIST_POLY_MOVE
move to first poly vertex
Definition: vlist.h:85
#define BN_VLIST_TRI_VERTNORM
per-vertex normal, for interpolation
Definition: vlist.h:93
void pl_space(register FILE *plotfp, int px1, int py1, int px2, int py2)
Definition: plot3.c:257
int db_full_path_match_top(const struct db_full_path *a, const struct db_full_path *b)
Definition: db_fullpath.c:559
if(share_geom)
Definition: nmg_mod.c:3829
int idb_major_type
Definition: raytrace.h:192
uint32_t magic
Definition: ged.h:457
#define DB_FULL_PATH_GET(_pp, _i)
Definition: db_fullpath.h:55
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
int db_full_path_subset(const struct db_full_path *a, const struct db_full_path *b, const int skip_first)
Definition: db_fullpath.c:515
Definition: color.c:49
#define POLYGON_HEADER_MAGIC
Definition: ged.h:464
int gv_y_samples
Definition: bview.h:258
void deering_persp_mat(fastf_t *m, const fastf_t *l, const fastf_t *h, const fastf_t *eye)
Definition: mat.c:1312
struct resource rt_uniresource
default. Defined in librt/globals.c
Definition: globals.c:41
void dl_zap(struct bu_list *hdlp, struct db_i *dbip, void(*callback)(unsigned int, int), struct solid *freesolid)
#define RT_G_DEBUG
Definition: raytrace.h:1718
void pd_3space(register FILE *plotfp, double px1, double py1, double pz1, double px2, double py2, double pz2)
Definition: plot3.c:580
struct bu_list * vhead
Definition: raytrace.h:1926
#define GED_CREATE_VLIST_CALLBACK_PTR_NULL
Definition: ged.h:82
struct animate * an_forw
forward link
Definition: raytrace.h:1338
#define RT_CK_DB_INTERNAL(_p)
Definition: raytrace.h:207
void _dl_eraseAllNamesFromDisplay(struct bu_list *hdlp, struct db_i *dbip, void(*callback)(unsigned int, int), const char *name, const int skip_first, struct solid *freesolid)
Definition: display_list.c:332
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
#define RT_CK_DIR(_dp)
Definition: raytrace.h:876
void _ged_bot_dump(struct directory *dp, struct rt_bot_internal *bot, FILE *fp, int fd, const char *file_ext, const char *db_name)
Definition: bot_dump.c:598
#define RT_DIR_SOLID
this name is a solid
Definition: raytrace.h:883
int db_string_to_path(struct db_full_path *pp, const struct db_i *dbip, const char *str)
Definition: db_fullpath.c:361
int wireframe_color[3]
Definition: bview.h:269
int bu_struct_export(struct bu_external *ext, const void *base, const struct bu_structparse *imp)
Definition: parse.c:120
#define TS_SOFAR_INTER
Intersection encountered above.
Definition: raytrace.h:1081
#define LOOKUP_QUIET
Definition: raytrace.h:893
#define BN_VLIST_POLY_START
pt[] has surface normal
Definition: vlist.h:84
#define BN_VLIST_LINE_MOVE
Definition: vlist.h:82
const struct rt_functab * idb_meth
for ft_ifree(), etc.
Definition: raytrace.h:194
#define V3ARGS(a)
Definition: color.c:56
#define TREE_NULL
Definition: raytrace.h:1181
void db_free_full_path(struct db_full_path *pp)
Definition: db_fullpath.c:473
fastf_t gv_size
2.0 * scale
Definition: bview.h:212
#define RT_CK_TESS_TOL(_p)
Definition: raytrace.h:184
mat_t ts_mat
transform matrix
Definition: raytrace.h:1050
char * strtok(char *s, const char *delim)
struct bu_list * back
"back", "last"
Definition: list.h:121
void dl_set_wflag(struct bu_list *hdlp, int wflag)
#define SQRT_SMALL_FASTF
Definition: defines.h:346
#define BN_VLIST_LINE_DRAW
Definition: vlist.h:83
#define RT_DIR_PHONY_ADDR
Special marker for d_addr field.
Definition: raytrace.h:879
void persp_mat(mat_t m, fastf_t fovy, fastf_t aspect, fastf_t near1, fastf_t far1, fastf_t backoff)
Definition: mat.c:1209
void dl_add_path(struct display_list *gdlp, int dashflag, int transparency, int dmode, int hiddenLine, struct bu_list *vhead, const struct db_full_path *pathp, struct db_tree_state *tsp, unsigned char *wireframe_color_override, void(*callback)(struct display_list *), struct solid *freesolid)
Definition: display_list.c:670
int dl_wflag
Definition: bview.h:50
#define PS_COORD(_x)
Definition: ged_private.h:199
int gv_adaptive_plot
Definition: bview.h:255
#define BU_LIST_PNEXT(structure, p)
Definition: list.h:422
short x
char ft_name[17]
Definition: raytrace.h:2043
oldeumate l2 magic
Definition: nmg_mod.c:3843
int dl_bounding_sph(struct bu_list *hdlp, vect_t *min, vect_t *max, int pflag)
Definition: display_list.c:157
short de
int dl_select(struct bu_list *hdlp, mat_t model2view, struct bu_vls *vls, double vx, double vy, double vwidth, double vheight, int rflag)
#define BN_VLIST_POLY_DRAW
subsequent poly vertex
Definition: vlist.h:86
struct bu_vls dl_path
Definition: bview.h:48
int(* ft_adaptive_plot)(struct rt_db_internal *, const struct rt_view_info *)
Definition: raytrace.h:2103
void bn_mat_mul(mat_t o, const mat_t a, const mat_t b)
int dl_how(struct bu_list *hdlp, struct bu_vls *vls, struct directory **dpp, int both)
#define BN_CK_TOL(_p)
Definition: tol.h:82
char * db_path_to_string(const struct db_full_path *pp)
Definition: db_fullpath.c:191
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
void dl_color_soltab(struct bu_list *hdlp)
Definition: display_list.c:573
void pl_linmod(register FILE *plotfp, const char *s)
Definition: plot3.c:207
struct resource * ts_resp
Per-CPU data.
Definition: raytrace.h:1074
#define BN_VLIST_TRI_END
last vert (repeats 1st), draw poly
Definition: vlist.h:92
#define BU_LIST_WHILE(p, structure, hp)
Definition: list.h:410
double dbi_base2local
unit conversion factors
Definition: raytrace.h:808
#define DG_GED_MIN
Definition: ged_private.h:75
#define BU_STRUCTPARSE_FUNC_NULL
Definition: parse.h:153
void bu_semaphore_release(unsigned int i)
Definition: semaphore.c:218
ustring alpha
void pl_color(register FILE *plotfp, int r, int g, int b)
Definition: plot3.c:325
int bn_ray_vclip(vect_t a, vect_t b, fastf_t *min, fastf_t *max)
Clip a ray against a rectangular parallelepiped (RPP) that has faces parallel to the coordinate plane...
Definition: clip.c:127
int gv_x_samples
Definition: bview.h:257
void db_path_to_vls(struct bu_vls *str, const struct db_full_path *pp)
Definition: db_fullpath.c:233
struct mater * rt_material_head(void)
Definition: mater.c:243
union tree * append_solid_to_display_list(struct db_tree_state *tsp, const struct db_full_path *pathp, struct rt_db_internal *ip, void *client_data)
Definition: display_list.c:946
float ma_color[3]
explicit color: 0..1
Definition: raytrace.h:522
#define bu_offsetof(_t, _m)
Definition: parse.h:64
#define BN_VLIST_TRI_START
pt[] has surface normal
Definition: vlist.h:89
int invent_solid(struct bu_list *hdlp, struct db_i *dbip, void(*callback_create)(struct display_list *), void(*callback_free)(unsigned int, int), char *name, struct bu_list *vhead, long int rgb, int copy, fastf_t transparency, int dmode, struct solid *freesolid, int csoltab)
void pl_3space(register FILE *plotfp, int px1, int py1, int pz1, int px2, int py2, int pz2)
Definition: plot3.c:350
#define BN_VLIST_POINT_SIZE
specify point pixel size
Definition: vlist.h:95
int redraw_solid(struct solid *sp, struct db_i *dbip, struct db_tree_state *tsp, struct bview *gvp)
Definition: display_list.c:919
struct directory * db_diradd(struct db_i *, const char *name, off_t laddr, size_t len, int flags, void *ptr)
Definition: db_lookup.c:190
int _dl_eraseFirstSubpath(struct bu_list *hdlp, struct db_i *dbip, void(*callback)(unsigned int, int), struct display_list *gdlp, struct db_full_path *subpath, const int skip_first, struct solid *freesolid)
Definition: display_list.c:386
void dl_print_schain(struct bu_list *hdlp, struct db_i *dbip, int lvl, int vlcmds, struct bu_vls *vls)
#define ZERO(val)
Definition: units.c:38
void pl_3line(register FILE *plotfp, int px1, int py1, int pz1, int px2, int py2, int pz2)
Definition: plot3.c:384
#define BU_LIST_INIT(_hp)
Definition: list.h:148
void * idb_ptr
Definition: raytrace.h:195
#define BN_CK_VLIST(_p)
Definition: vlist.h:78
int dl_set_illum(struct display_list *gdlp, const char *obj, int illum)
#define RT_CK_RESOURCE(_p)
Definition: raytrace.h:1490
Definition: vlist.h:71
const struct rt_tess_tol * ts_ttol
Tessellation tolerance.
Definition: raytrace.h:1070
short minor
unsigned char color[3]
Definition: ged.h:461
#define DBI_NULL
Definition: raytrace.h:827
int ymajor
size_t sp_count
Definition: parse.h:139
#define RT_GET_TREE(_tp, _res)
Definition: raytrace.h:1210
#define BN_VLIST_POLY_VERTNORM
per-vertex normal, for interpolation
Definition: vlist.h:88
int npts
Definition: ged.h:462
#define GED_FREE_VLIST_CALLBACK_PTR_NULL
Definition: ged.h:83
#define BN_VLIST_POLY_END
last vert (repeats 1st), draw poly
Definition: vlist.h:87
HIDDEN void eraseAllSubpathsFromSolidList(struct display_list *gdlp, struct db_full_path *subpath, void(*callback)(unsigned int, int), const int skip_first, struct solid *freesolid)
Definition: display_list.c:301
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
#define RT_DIR_NULL
Definition: raytrace.h:875
#define LOOKUP_NOISY
Definition: raytrace.h:892
void dl_polybinout(struct bu_list *hdlp, struct polygon_header *ph, FILE *fp)
void dl_png(struct bu_list *hdlp, mat_t model2view, fastf_t perspective, vect_t eye_pos, size_t size, size_t half_size, unsigned char **image)
#define BN_VLIST_TRI_DRAW
subsequent triangle vertex
Definition: vlist.h:91
int idb_minor_type
ID_xxx.
Definition: raytrace.h:193
char * strdup(const char *cp)
Definition: color.c:51
int dl_select_partial(struct bu_list *hdlp, mat_t model2view, struct bu_vls *vls, double vx, double vy, double vwidth, double vheight, int rflag)
#define RT_SEM_MODEL
Definition: raytrace.h:1733
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
ustring both
#define TS_SOFAR_MINUS
Subtraction encountered above.
Definition: raytrace.h:1080
int ts_regionid
GIFT compat region ID code.
Definition: raytrace.h:1043
short e
size_t bu_struct_put(FILE *fp, const struct bu_external *ext)
Definition: parse.c:457
#define PS_COLOR(_c)
Definition: ged_private.h:200
int transparency
Definition: bview.h:270
void dl_set_flag(struct bu_list *hdlp, int flag)
#define RT_DIR_USED
One bit, used similar to d_nref.
Definition: raytrace.h:888
#define GED_DISPLAY_LIST_NULL
Definition: ged.h:73
int dl_redraw(struct display_list *gdlp, struct db_i *dbip, struct db_tree_state *tsp, struct bview *gvp, void(*callback)(struct display_list *))
Definition: display_list.c:933
#define BU_LIST_DEQUEUE(cur)
Definition: list.h:209
size_t ext_nbytes
Definition: parse.h:210
#define DOWN
Definition: bview.h:42
#define _GED_HIDDEN_LINE
Definition: ged_private.h:62
#define DEBUG_TREEWALK
22 Database tree traversal
Definition: raytrace.h:107
void db_write_anim(FILE *fop, struct animate *anp)
Definition: db_anim.c:447
point_t pt[BN_VLIST_CHUNK]
associated 3-point/vect
Definition: vlist.h:75
struct coord pixel
#define GRN
Definition: color.h:40
#define BN_VLIST_LINE_WIDTH
specify line pixel width
Definition: vlist.h:96
Definition: vls.h:56
int ts_sofar
Flag bits.
Definition: raytrace.h:1041
HIDDEN const point_t delta
Definition: sh_prj.c:618
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 BU_LIST_NEXT(structure, hp)
Definition: list.h:316
#define BU_LIST_NOT_HEAD(p, hp)
Definition: list.h:324
void dl_set_iflag(struct bu_list *hdlp, int iflag)
void headsolid_split(struct bu_list *hdlp, struct db_i *dbip, struct solid *sp, int newlen)
Definition: display_list.c:104
struct display_list * dl_addToDisplay(struct bu_list *hdlp, struct db_i *dbip, const char *name)
Definition: display_list.c:42
void rt_db_free_internal(struct rt_db_internal *ip)
Definition: dir.c:216
int rt_ck_vlist(const struct bu_list *vhead)
Definition: vlist.c:192
void dl_bitwise_and_fullpath(struct bu_list *hdlp, int flag_val)
fastf_t brep_est_avg_curve_len(struct rt_brep_internal *bi)
Definition: draw_calc.cpp:62
Definition: color.c:50
#define BU_LIST_APPEND_LIST(dest_hp, src_hp)
Definition: list.h:281
#define BU_LIST_FIRST(structure, hp)
Definition: list.h:312
fastf_t gv_point_scale
Definition: bview.h:259
int bn_vlist_bbox(struct bn_vlist *vp, point_t *bmin, point_t *bmax)
Definition: vlist.c:52
#define BU_STR_EQUAL(s1, s2)
Definition: str.h:126
#define BN_VLIST_TRI_MOVE
move to first triangle vertex
Definition: vlist.h:90