BRL-CAD
osg-test.cpp
Go to the documentation of this file.
1 /* O S G - T E S T . C P P
2  * BRL-CAD
3  *
4  * Copyright (c) 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 osg-test.cpp
21  *
22  * BRL-CAD test application for OpenSceneGraph integration, based off of
23  * osghud example from OpenSceneGraph, which has the following license:
24  *
25  * Permission is hereby granted, free of charge, to any person obtaining a copy
26  * of this software and associated documentation files (the "Software"), to deal
27  * in the Software without restriction, including without limitation the rights
28  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
29  * copies of the Software, and to permit persons to whom the Software is
30  * furnished to do so, subject to the following conditions:
31  *
32  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
38  * THE SOFTWARE.
39  */
40 
41 extern "C" {
42 #include "common.h"
43 #include "bu/log.h"
44 #include "bu/list.h"
45 #include "mater.h"
46 #include "raytrace.h"
47 #include "rtfunc.h"
48 }
49 
50 #include <map>
51 
52 #include <osgUtil/Optimizer>
53 #include <osgDB/ReadFile>
54 
55 #include <osgViewer/Viewer>
56 #include <osgViewer/CompositeViewer>
57 #include <osgViewer/ViewerEventHandlers>
58 
59 #include <osgGA/TrackballManipulator>
60 #include <osgGA/StateSetManipulator>
61 
62 
63 #include <osg/Material>
64 #include <osg/Geode>
65 #include <osg/BlendFunc>
66 #include <osg/Depth>
67 #include <osg/PolygonOffset>
68 #include <osg/MatrixTransform>
69 #include <osg/Camera>
70 #include <osg/RenderInfo>
71 #include <osg/LineStipple>
72 
73 #include <osgDB/WriteFile>
74 
75 #include <osgText/Text>
76 
77 struct bu_list *
78 obj_vlist(const struct directory *dp, const struct db_i *dbip, mat_t mat)
79 {
80  struct bu_list *plot_segments;
81  struct rt_db_internal intern;
82  const struct bn_tol tol = {BN_TOL_MAGIC, 0.0005, 0.0005 * 0.0005, 1e-6, 1 - 1e-6};
83  const struct rt_tess_tol rttol = {RT_TESS_TOL_MAGIC, 0.0, 0.01, 0};
84  RT_DB_INTERNAL_INIT(&intern);
85  if (rt_db_get_internal(&intern, dp, dbip, mat, &rt_uniresource) < 0) {
86  bu_exit(1, "ERROR: Unable to get internal representation of %s\n", dp->d_namep);
87  }
88  BU_GET(plot_segments, struct bu_list);
89  BU_LIST_INIT(plot_segments);
90 
91  if (rt_obj_plot(plot_segments, &intern, &rttol, &tol) < 0) {
92  bu_exit(1, "ERROR: Unable to get plot segment list from %s\n", dp->d_namep);
93  }
94  rt_db_free_internal(&intern);
95  return plot_segments;
96 }
97 
98 void
99 add_vlist_to_geom(osg::Geometry *geom, struct bu_list *plot_segments)
100 {
101  std::vector<int>startIndexes;
102  std::vector<int>stopIndexes;
103  osg::Vec3Array *vertArray = (osg::Vec3Array *)geom->getVertexArray();
104  struct bn_vlist *vp;
105 
106  if (!vertArray) {
107  osg::ref_ptr<osg::Vec3Array> new_vertArray = new osg::Vec3Array();
108  geom->setVertexArray(new_vertArray);
109  vertArray = (osg::Vec3Array *)geom->getVertexArray();
110  }
111  int currentVertex = vertArray->getNumElements();
112 
113  geom->setUseDisplayList(true);
114 
115  for (BU_LIST_FOR(vp, bn_vlist, plot_segments))
116  {
117  int j;
118  int nused = vp->nused;
119  const int *cmd = vp->cmd;
120  point_t *pt = vp->pt;
121 
122  for (j=0 ; j < nused ; j++, cmd++, pt++, currentVertex++)
123  {
124  switch (*cmd)
125  {
126  case BN_VLIST_POLY_START:
127  break;
128  case BN_VLIST_POLY_MOVE: // fallthrough
129  case BN_VLIST_LINE_MOVE:
130  if (startIndexes.size() > 0)
131  {
132  // finish off the last linestrip
133  stopIndexes.push_back(currentVertex-1);
134  }
135  // remember where the new linestrip begins
136  startIndexes.push_back(currentVertex);
137 
138  // start a new linestrip
139  vertArray->push_back(osg::Vec3((float)((*pt)[X]), (float)((*pt)[Y]),(float)(*pt)[Z]));
140 
141  break;
142  case BN_VLIST_POLY_DRAW: // fallthrough
143  case BN_VLIST_POLY_END: // fallthrough
144  case BN_VLIST_LINE_DRAW:
145  // continue existing linestrip
146  vertArray->push_back(osg::Vec3((float)((*pt)[X]), (float)((*pt)[Y]),(float)(*pt)[Z]));
147  break;
148  case BN_VLIST_POINT_DRAW:
149  break;
150  }
151  }
152  }
153 
154  if (startIndexes.size() > 0)
155  stopIndexes.push_back(--currentVertex);
156 
157 
158  for (unsigned j=0 ; j < startIndexes.size() ; j++) {
159  geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, startIndexes[j], (stopIndexes[j]-startIndexes[j])+1 ));
160  }
161 
162 }
163 
164 osg::ref_ptr<osg::Group>
166  std::map<const struct directory *, osg::ref_ptr<osg::Group> > *osg_nodes,
167  const struct directory *dp, const struct db_i *dbip)
168 {
169  osg::ref_ptr<osg::Group> wrapper;
170  if ((*osg_nodes).find(dp) == (*osg_nodes).end()) {
171  wrapper = new osg::Group;
172  (*osg_nodes)[dp] = wrapper.get();
173  } else {
174  wrapper = (*osg_nodes)[dp];
175  }
176 
177  /* Clear the children from the wrapper, if it has any */
178  unsigned int children_cnt = wrapper->getNumChildren();
179  wrapper->removeChildren(0, children_cnt);
180 
181  /* Set up the OSG superstructure for the solid geometry node */
182  osg::ref_ptr<osg::Geode> geode = new osg::Geode;
183  osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
184  wrapper->setName(dp->d_namep);
185  geode->setName(dp->d_namep);
186  geom->setName(dp->d_namep); // set drawable to same name as region
187  geode->addDrawable(geom);
188  osg::StateSet* state = geode->getOrCreateStateSet();
189  state->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
190  wrapper->addChild(geode);
191 
192  /* Actually add the geometry from the vlist */
193  mat_t mat;
194  MAT_IDN(mat);
195  struct bu_list *plot_segments = obj_vlist(dp, dbip, mat);
196  add_vlist_to_geom(geom, plot_segments);
197 
198  /* Cleanup */
199  RT_FREE_VLIST(plot_segments);
200  BU_PUT(plot_segments, struct bu_list);
201 
202  return wrapper;
203 }
204 
205 void
206 create_solid_nodes(std::map<const struct directory *, osg::ref_ptr<osg::Group> > *osg_nodes,
207  struct directory *dp, struct db_i *dbip)
208 {
209  const char *solid_search = "! -type comb";
210  struct bu_ptbl solids = BU_PTBL_INIT_ZERO;
211  (void)db_search(&solids, DB_SEARCH_RETURN_UNIQ_DP, solid_search, 1, &dp, dbip);
212 
213  for (int i = (int)BU_PTBL_LEN(&solids) - 1; i >= 0; i--) {
214  /* Get the vlist associated with this particular object */
215  struct directory *curr_dp = (struct directory *)BU_PTBL_GET(&solids, i);
216  if ((*osg_nodes).find(curr_dp) == (*osg_nodes).end()) {
217  osg::ref_ptr<osg::Group> node = solid_node(osg_nodes, curr_dp, dbip);
218  (*osg_nodes)[curr_dp] = node.get();
219  }
220  }
221  db_search_free(&solids);
222 
223 }
224 
225 osg::ref_ptr<osg::Group>
227  std::map<const struct directory *, osg::ref_ptr<osg::Group> > *osg_nodes,
228  const struct directory *dp, const struct db_i *dbip)
229 {
230  osg::ref_ptr<osg::Group> comb;
231  if ((*osg_nodes).find(dp) == (*osg_nodes).end()) {
232  comb = new osg::Group;
233  (*osg_nodes)[dp] = comb.get();
234  } else {
235  comb = (*osg_nodes)[dp];
236  }
237 
238  comb->setName(dp->d_namep);
239 
240  struct rt_db_internal intern;
241  (void)rt_db_get_internal(&intern, dp, dbip, (fastf_t *)NULL, &rt_uniresource);
242  struct rt_comb_internal *comb_internal= (struct rt_comb_internal *)intern.idb_ptr;
243  /* Set color for this comb */
244  float color[3] = {-1.0, -1.0, -1.0};
245  if (comb_internal->rgb_valid) {
246  VSCALE(color, comb_internal->rgb, (1.0/255.0) );
247  } else {
248  struct mater *mp = MATER_NULL;
249  for (mp = rt_material_head(); mp != MATER_NULL; mp = mp->mt_forw) {
250  if (comb_internal->region_id <= mp->mt_high && comb_internal->region_id >= mp->mt_low) {
251  color[0] = mp->mt_r/255.0;
252  color[1] = mp->mt_g/255.0;
253  color[2] = mp->mt_b/255.0;
254  break;
255  }
256  }
257  }
258  if (color[0] > -1) {
259  osg::ref_ptr<osg::Material> mtl = new osg::Material;
260  mtl->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(color[0], color[1], color[2], 1.0f));
261  osg::StateSet* state = comb->getOrCreateStateSet();
262  if (comb_internal->inherit || comb_internal->region_flag) {
263  state->setAttributeAndModes(mtl.get(), osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
264  } else {
265  state->setAttributeAndModes(mtl.get(), osg::StateAttribute::ON);
266  }
267  }
268  rt_db_free_internal(&intern);
269 
270  return comb;
271 }
272 
273 int
275 {
276  int ret = 0;
277  for (unsigned int i = 0; i < path->fp_len; i++) {
278  if(path->fp_bool[i] == 4) ret = 1;
279  }
280  return ret;
281 }
282 
283 void
284 add_comb_child(osg::Group *comb, osg::Group *child, struct db_full_path *child_path, struct db_i *dbip)
285 {
286  mat_t m = MAT_INIT_IDN;
287  mat_t m_idn = MAT_INIT_IDN;
288  const struct bn_tol tol = {BN_TOL_MAGIC, 0.0005, 0.0005 * 0.0005, 1e-6, 1 - 1e-6};
289  (void)db_path_to_mat(dbip, child_path, (matp_t)(&m), child_path->fp_len, &rt_uniresource);
290  if (!bn_mat_is_equal(m, m_idn, &tol)) {
291  mat_t mt = MAT_INIT_IDN;
292  MAT_TRANSPOSE(mt, m);
293  osg::Matrixd osgMat(mt);
294  osg::ref_ptr<osg::MatrixTransform> osgmt = new osg::MatrixTransform(osgMat);
295  osgmt->addChild(child);
296  comb->addChild(osgmt);
297 
298  /* If this child_path is subtracted in this comb, stipple the line drawings */
299  if (child_path->fp_bool[child_path->fp_len - 1] == 4) {
300  osg::StateSet* state = osgmt->getOrCreateStateSet();
301  osg::ref_ptr<osg::LineStipple> ls = new osg::LineStipple();
302  ls->setPattern(0xCF33);
303  ls->setFactor(1);
304  state->setAttributeAndModes(ls.get());
305  }
306  } else {
307  if (child_path->fp_bool[child_path->fp_len - 1] == 4) {
308  osg::ref_ptr<osg::Group> property_wrapper = new osg::Group;
309  property_wrapper->setName(DB_FULL_PATH_CUR_DIR(child_path)->d_namep);
310  osg::StateSet* state = property_wrapper->getOrCreateStateSet();
311  osg::ref_ptr<osg::LineStipple> ls = new osg::LineStipple();
312  ls->setPattern(0xCF33);
313  ls->setFactor(1);
314  state->setAttributeAndModes(ls.get());
315  property_wrapper->addChild(child);
316  comb->addChild(property_wrapper);
317  } else {
318  comb->addChild(child);
319  }
320  }
321 }
322 
323 /* In the case of regions, we need to be able to remove and restore the individual
324  * comb children, because for normal display (as opposed to editing mode) we need to
325  * use a single composite wireframe for regions */
326 osg::ref_ptr<osg::Group>
328  std::map<const struct directory *, osg::ref_ptr<osg::Group> > *osg_nodes,
329  struct directory *dp, struct db_i *dbip)
330 {
331  osg::ref_ptr<osg::Group> comb = bare_comb_node(osg_nodes, dp, dbip);
332 
333  /* Clear the immediate children from this node, if it has any */
334  unsigned int children_cnt = comb->getNumChildren();
335  comb->removeChildren(0, children_cnt);
336 
337  const char *comb_search = "-type comb";
338  struct bu_ptbl combs = BU_PTBL_INIT_ZERO;
339  (void)db_search(&combs, DB_SEARCH_RETURN_UNIQ_DP, comb_search, 1, &dp, dbip);
340  for (int i = (int)BU_PTBL_LEN(&combs) - 1; i >= 0; i--) {
341  struct directory *curr_dp = (struct directory *)BU_PTBL_GET(&combs, i);
342  osg::ref_ptr<osg::Group> sub_comb = bare_comb_node(osg_nodes, curr_dp, dbip);
343  const char *comb_children_search = "-mindepth 1 -maxdepth 1";
344  struct bu_ptbl comb_children = BU_PTBL_INIT_ZERO;
345  (void)db_search(&comb_children, DB_SEARCH_TREE, comb_children_search, 1, &curr_dp, dbip);
346  for (int j = (int)BU_PTBL_LEN(&comb_children) - 1; j >= 0; j--) {
347  struct db_full_path *curr_path = (struct db_full_path *)BU_PTBL_GET(&comb_children, j);
348  struct directory *curr_child_dp = DB_FULL_PATH_CUR_DIR(curr_path);
349  if (curr_child_dp->d_flags & RT_DIR_COMB) {
350  osg::ref_ptr<osg::Group> new_node = bare_comb_node(osg_nodes, curr_child_dp, dbip);
351  (*osg_nodes)[curr_child_dp] = new_node.get();
352  }
353  if (curr_child_dp->d_flags & RT_DIR_SOLID) {
354  osg::ref_ptr<osg::Group> new_node = solid_node(osg_nodes, curr_child_dp, dbip);
355  (*osg_nodes)[curr_child_dp] = new_node.get();
356  }
357  add_comb_child(sub_comb, (*osg_nodes)[curr_child_dp], curr_path, dbip);
358  }
359  db_search_free(&comb_children);
360  }
361  db_search_free(&combs);
362 
363  return comb;
364 }
365 
366 osg::ref_ptr<osg::Group>
368  std::map<const struct directory *, osg::ref_ptr<osg::Group> > *osg_nodes,
369  struct directory *dp, struct db_i *dbip)
370 {
371  osg::ref_ptr<osg::Group> region = bare_comb_node(osg_nodes, dp, dbip);
372 
373  /* Clear the immediate children from this node, if it has any */
374  unsigned int children_cnt = region->getNumChildren();
375  region->removeChildren(0, children_cnt);
376 
377  /* We now create up to two pseudo-solid nodes holding the full region drawable info - one for non-subtracted
378  * elements (no stipple) and one (if needed) for subtracted elements (stipple)*/
379  osg::ref_ptr<osg::Geode> geode = new osg::Geode;
380  osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
381  geode->setName(dp->d_namep);
382  geom->setName(dp->d_namep); // set drawable to same name as region
383  geode->addDrawable(geom);
384  osg::StateSet* state = geode->getOrCreateStateSet();
385  state->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
386  region->addChild(geode);
387 
388  /* Define the subtraction container, but don't add it as a child of the region unless we actually need it.*/
389  osg::ref_ptr<osg::Group> subtraction_wrapper = new osg::Group;
390  osg::ref_ptr<osg::Geode> subtraction_geode = new osg::Geode;
391  osg::ref_ptr<osg::Geometry> subtraction_geom = new osg::Geometry;
392  subtraction_wrapper->setName(dp->d_namep);
393  subtraction_geode->setName(dp->d_namep);
394  subtraction_geom->setName(dp->d_namep);
395  osg::StateSet* subtraction_geode_state = subtraction_geode->getOrCreateStateSet();
396  subtraction_geode_state->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
397  osg::StateSet* subtraction_state = subtraction_wrapper->getOrCreateStateSet();
398  osg::ref_ptr<osg::LineStipple> ls = new osg::LineStipple();
399  ls->setPattern(0xCF33);
400  ls->setFactor(1);
401  subtraction_state->setAttributeAndModes(ls.get());
402  subtraction_geode->addDrawable(subtraction_geom);
403  subtraction_wrapper->addChild(subtraction_geode);
404 
405  /*Search for all the solids (using full paths) below the region - that's the list of vlists we need for this particular region,
406  *using the full paths below the current region to place them in their final relative positions.
407  */
408  const char *region_vlist_search = "! -type comb";
409  struct bu_ptbl region_vlist_contributors = BU_PTBL_INIT_ZERO;
410  (void)db_search(&region_vlist_contributors, DB_SEARCH_TREE, region_vlist_search, 1, &dp, dbip);
411  int have_subtraction = 0;
412  for (int j = (int)BU_PTBL_LEN(&region_vlist_contributors) - 1; j >= 0; j--) {
413  struct db_full_path *curr_path = (struct db_full_path *)BU_PTBL_GET(&region_vlist_contributors, j);
414 
415  /* Find out how to draw this particular wireframe */
416  int subtraction_path = subtracted_solid(curr_path);
417 
418  /* Get the final matrix we will need for this vlist */
419  mat_t tm;
420  MAT_IDN(tm);
421  (void)db_path_to_mat(dbip, curr_path, tm, curr_path->fp_len-1, &rt_uniresource);
422 
423  /* Actually add the geometry from the vlist */
424  struct bu_list *plot_segments = obj_vlist(DB_FULL_PATH_CUR_DIR(curr_path), dbip, tm);
425  if (subtraction_path) {
426  have_subtraction++;
427  add_vlist_to_geom(subtraction_geom, plot_segments);
428  } else {
429  add_vlist_to_geom(geom, plot_segments);
430  }
431 
432  /* Cleanup */
433  RT_FREE_VLIST(plot_segments);
434  BU_PUT(plot_segments, struct bu_list);
435 
436  }
437  db_search_free(&region_vlist_contributors);
438  if (have_subtraction) {
439  region->addChild(subtraction_wrapper);
440  }
441 
442  return region;
443 }
444 
445 
446 /* In the case of regions, we need to be able to remove and restore the individual
447  * comb children, because for normal display (as opposed to editing mode) we need to
448  * use a single composite wireframe for regions */
449 osg::ref_ptr<osg::Group>
451  std::map<const struct directory *, osg::ref_ptr<osg::Group> > *osg_nodes,
452  struct directory *dp, struct db_i *dbip)
453 {
454  osg::ref_ptr<osg::Group> assembly = bare_comb_node(osg_nodes, dp, dbip);
455 
456  /* Clear the immediate children from this node, if it has any */
457  unsigned int children_cnt = assembly->getNumChildren();
458  assembly->removeChildren(0, children_cnt);
459 
460  const char *assembly_search = "-type comb ! -below -type region ! -type region";
461  struct bu_ptbl assemblies = BU_PTBL_INIT_ZERO;
462  (void)db_search(&assemblies, DB_SEARCH_RETURN_UNIQ_DP, assembly_search, 1, &dp, dbip);
463  for (int i = (int)BU_PTBL_LEN(&assemblies) - 1; i >= 0; i--) {
464  struct directory *curr_dp = (struct directory *)BU_PTBL_GET(&assemblies, i);
465  osg::ref_ptr<osg::Group> sub_comb = bare_comb_node(osg_nodes, curr_dp, dbip);
466  const char *comb_children_search = "-mindepth 1 -maxdepth 1";
467  struct bu_ptbl comb_children = BU_PTBL_INIT_ZERO;
468  (void)db_search(&comb_children, DB_SEARCH_TREE, comb_children_search, 1, &curr_dp, dbip);
469  for (int j = (int)BU_PTBL_LEN(&comb_children) - 1; j >= 0; j--) {
470  struct db_full_path *curr_path = (struct db_full_path *)BU_PTBL_GET(&comb_children, j);
471  struct directory *curr_child_dp = DB_FULL_PATH_CUR_DIR(curr_path);
472  if (curr_child_dp->d_flags & RT_DIR_COMB && !(curr_child_dp->d_flags & RT_DIR_REGION)) {
473  int is_assembly = 0;
474  for (int k = (int)BU_PTBL_LEN(&assemblies) - 1; k >= 0; k--) {
475  struct directory *assembly_dp = (struct directory *)BU_PTBL_GET(&assemblies, k);
476  if (assembly_dp == curr_child_dp) is_assembly = 1;
477  }
478  osg::ref_ptr<osg::Group> new_node;
479  if (is_assembly) {
480  new_node = bare_comb_node(osg_nodes, curr_child_dp, dbip);
481  } else {
482  new_node = full_comb_node(osg_nodes, curr_child_dp, dbip);
483  }
484  (*osg_nodes)[DB_FULL_PATH_CUR_DIR(curr_path)] = new_node.get();
485  }
486  if (curr_child_dp->d_flags & RT_DIR_REGION) {
487  osg::ref_ptr<osg::Group> new_node = full_region_node(osg_nodes, curr_child_dp, dbip);
488  (*osg_nodes)[curr_child_dp] = new_node.get();
489  }
490  if (curr_child_dp->d_flags & RT_DIR_SOLID) {
491  osg::ref_ptr<osg::Group> new_node = solid_node(osg_nodes, curr_child_dp, dbip);
492  (*osg_nodes)[curr_child_dp] = new_node.get();
493  }
494  add_comb_child(sub_comb, (*osg_nodes)[curr_child_dp], curr_path, dbip);
495  }
496  db_search_free(&comb_children);
497  }
498  db_search_free(&assemblies);
499 
500  return assembly;
501 }
502 
503 
504 /* Determine what type of dp we're dealing with:
505  *
506  * -1 - not drawable
507  * 0 - solid
508  * 1 - comb
509  * 2 - region
510  * 3 - assembly (comb with regions below it)
511  */
512 int
513 characterize_dp(struct directory *dp, struct db_i *dbip)
514 {
515  int ret = -1;
516  const char *is_assembly_search = "-type region";
517  if (dp->d_flags & RT_DIR_COMB) {
518  ret = 1;
519  if (dp->d_flags & RT_DIR_REGION) {
520  ret = 2;
521  } else {
522  /* TODO - db_search should let us know the results without needing the table,
523  * but that doesn't seem to be working... */
524  struct bu_ptbl search_results = BU_PTBL_INIT_ZERO;
525  (void)db_search(&search_results, DB_SEARCH_QUIET, is_assembly_search, 1, &dp, dbip);
526  if (BU_PTBL_LEN(&search_results) > 0) ret = 3;
527  db_search_free(&search_results);
528  }
529  } else {
530  if (dp->d_flags & RT_DIR_SOLID) ret = 0;
531  }
532 
533  return ret;
534 }
535 
536 void
538  std::map<const struct directory *, osg::ref_ptr<osg::Group> > *osg_nodes,
539  struct directory *dp, struct db_i *dbip)
540 {
541  int dp_type = characterize_dp(dp, dbip);
542  switch (dp_type) {
543  case 0:
544  (void)solid_node(osg_nodes, dp, dbip);
545  break;
546  case 1:
547  full_comb_node(osg_nodes, dp, dbip);
548  break;
549  case 2:
550  full_region_node(osg_nodes, dp, dbip);
551  break;
552  case 3:
553  full_assembly_node(osg_nodes, dp, dbip);
554  break;
555  }
556 }
557 
558 
559 int
561  std::map<const struct directory *, osg::ref_ptr<osg::Group> > *osg_nodes,
562  const struct db_full_path *path, struct db_i *dbip)
563 {
564  /* Whatever the path looks like, we're going to have to add the
565  * current directory */
566  struct db_full_path working_path;
567  db_full_path_init(&working_path);
568  db_dup_full_path(&working_path, path);
569 
570  add_dp_to_scene(osg_nodes, DB_FULL_PATH_CUR_DIR(&working_path), dbip);
571 
572  while (working_path.fp_len > 1) {
573  struct directory *curr_dp = DB_FULL_PATH_CUR_DIR(&working_path);
574  struct directory *parent_dp = working_path.fp_names[working_path.fp_len - 2];
575 
576  osg::ref_ptr<osg::Group> comb = bare_comb_node(osg_nodes, parent_dp, dbip);
577  osg::ref_ptr<osg::Group> child = (*osg_nodes)[curr_dp];
578 
579  add_comb_child(comb, child, &working_path, dbip);
580 
581  DB_FULL_PATH_POP(&working_path);
582  }
583 
584  db_free_full_path(&working_path);
585  return 0;
586 }
587 
588 int main( int argc, char **argv )
589 {
590  std::map<const struct directory *, osg::ref_ptr<osg::Group> > osg_nodes;
591  struct db_i *dbip = DBI_NULL;
592  struct directory *dp = RT_DIR_NULL;
593  struct db_full_path path;
594 
595  if (argc != 3 || !argv) {
596  bu_exit(1, "Error - please specify a .g file and an object\n");
597  }
598  if (!bu_file_exists(argv[1], NULL)) {
599  bu_exit(1, "Cannot stat file %s\n", argv[1]);
600  }
601 
602  if ((dbip = db_open(argv[1], DB_OPEN_READONLY)) == DBI_NULL) {
603  bu_exit(1, "Cannot open geometry database file %s\n", argv[1]);
604  }
605  RT_CK_DBI(dbip);
606  if (db_dirbuild(dbip) < 0) {
607  db_close(dbip);
608  bu_exit(1, "db_dirbuild failed on geometry database file %s\n", argv[1]);
609  }
610 
611  /* argv[2] may be a full path, not just an object name - handle it */
612  if (db_string_to_path(&path, dbip, argv[2])) {
613  bu_exit(1, "ERROR: Unable to find object %s in %s\n", argv[2], argv[1]);
614  }
615 
616  /* Need to initialize this for rt_obj_plot, which may call RT_ADD_VLIST */
618 
619  add_path_to_scene(&(osg_nodes), &path, dbip);
620 
621  // construct the viewer.
622  osgViewer::Viewer viewer;
623  viewer.setUpViewInWindow(0, 0, 640, 480);
624 
625  // add the state manipulator
626  viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
627 
628  // add the thread model handler
629  viewer.addEventHandler(new osgViewer::ThreadingHandler);
630 
631  // add the window size toggle handler
632  viewer.addEventHandler(new osgViewer::WindowSizeHandler);
633 
634  // add the stats handler
635  viewer.addEventHandler(new osgViewer::StatsHandler);
636 
637  // The settings below do not seem to improve FPS, and the latter results in no geometry being
638  // visible without improving the FPS.
639  //viewer.getCamera()->setCullingMode(osg::CullSettings::NO_CULLING);
640  //viewer.getCamera()->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
641 
642  osgUtil::Optimizer optimizer;
643  osg::ref_ptr<osg::Group> toplevel = new osg::Group;
644  toplevel->addChild(osg_nodes[DB_FULL_PATH_ROOT_DIR(&path)]);
645  optimizer.optimize(toplevel);
646  viewer.setSceneData(toplevel);
647 
648  viewer.realize();
649 
650  return viewer.run();
651 }
652 // Local Variables:
653 // tab-width: 8
654 // mode: C++
655 // c-basic-offset: 4
656 // indent-tabs-mode: t
657 // c-file-style: "stroustrup"
658 // End:
659 // ex: shiftwidth=4 tabstop=8
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
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 db_search_free(struct bu_ptbl *search_results)
Definition: search.c:2089
Definition: list.h:118
#define BU_PTBL_INIT_ZERO
Definition: ptbl.h:92
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
int cmd[BN_VLIST_CHUNK]
VL_CMD_*.
Definition: vlist.h:74
struct bu_list rtg_vlfree
head of bn_vlist freelist
Definition: raytrace.h:1698
#define BN_TOL_MAGIC
Definition: magic.h:74
#define DB_SEARCH_RETURN_UNIQ_DP
Return the set of unique directory pointers instead of full paths.
Definition: search.h:113
Header file for the BRL-CAD common definitions.
#define DB_FULL_PATH_CUR_DIR(_pp)
Definition: db_fullpath.h:51
#define RT_DIR_REGION
region
Definition: raytrace.h:885
#define RT_FREE_VLIST(hd)
Definition: raytrace.h:1863
osg::ref_ptr< osg::Group > full_region_node(std::map< const struct directory *, osg::ref_ptr< osg::Group > > *osg_nodes, struct directory *dp, struct db_i *dbip)
Definition: osg-test.cpp:367
void db_full_path_init(struct db_full_path *pathp)
Definition: db_fullpath.c:40
int subtracted_solid(struct db_full_path *path)
Definition: osg-test.cpp:274
#define DB_SEARCH_TREE
Do a hierarchy-aware search. This is the default.
Definition: search.h:110
#define BN_VLIST_POLY_MOVE
move to first poly vertex
Definition: vlist.h:85
Definition: ptbl.h:62
int rt_obj_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
Definition: obj_plot.c:29
int bn_mat_is_equal(const mat_t a, const mat_t b, const struct bn_tol *tol)
Definition: mat.c:925
Definition: color.c:49
struct bu_list * obj_vlist(const struct directory *dp, const struct db_i *dbip, mat_t mat)
Definition: osg-test.cpp:78
int * fp_bool
array of boolean flags
Definition: db_fullpath.h:47
struct resource rt_uniresource
default. Defined in librt/globals.c
Definition: globals.c:41
void bu_exit(int status, const char *fmt,...) _BU_ATTR_NORETURN _BU_ATTR_PRINTF23
Definition: bomb.c:195
void add_vlist_to_geom(osg::Geometry *geom, struct bu_list *plot_segments)
Definition: osg-test.cpp:99
#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
#define BU_PTBL_GET(ptbl, i)
Definition: ptbl.h:108
#define RT_DB_INTERNAL_INIT(_p)
Definition: raytrace.h:199
#define BN_VLIST_POLY_START
pt[] has surface normal
Definition: vlist.h:84
#define BN_VLIST_LINE_MOVE
Definition: vlist.h:82
void db_free_full_path(struct db_full_path *pp)
Definition: db_fullpath.c:473
#define BU_GET(_ptr, _type)
Definition: malloc.h:201
osg::ref_ptr< osg::Group > full_comb_node(std::map< const struct directory *, osg::ref_ptr< osg::Group > > *osg_nodes, struct directory *dp, struct db_i *dbip)
Definition: osg-test.cpp:327
#define BN_VLIST_LINE_DRAW
Definition: vlist.h:83
void db_close(struct db_i *dbip)
#define BN_VLIST_POLY_DRAW
subsequent poly vertex
Definition: vlist.h:86
#define BU_PUT(_ptr, _type)
Definition: malloc.h:215
Support for uniform tolerances.
Definition: tol.h:71
struct directory ** fp_names
array of dir pointers
Definition: db_fullpath.h:46
osg::ref_ptr< osg::Group > bare_comb_node(std::map< const struct directory *, osg::ref_ptr< osg::Group > > *osg_nodes, const struct directory *dp, const struct db_i *dbip)
Definition: osg-test.cpp:226
#define BU_PTBL_LEN(ptbl)
Definition: ptbl.h:107
struct mater * rt_material_head(void)
Definition: mater.c:243
#define RT_CK_DBI(_p)
Definition: raytrace.h:829
#define BU_LIST_INIT(_hp)
Definition: list.h:148
void * idb_ptr
Definition: raytrace.h:195
#define RT_DIR_COMB
combination
Definition: raytrace.h:884
#define DB_SEARCH_QUIET
Silence all warnings.
Definition: search.h:114
Definition: vlist.h:71
#define DBI_NULL
Definition: raytrace.h:827
osg::ref_ptr< osg::Group > solid_node(std::map< const struct directory *, osg::ref_ptr< osg::Group > > *osg_nodes, const struct directory *dp, const struct db_i *dbip)
Definition: osg-test.cpp:165
void add_comb_child(osg::Group *comb, osg::Group *child, struct db_full_path *child_path, struct db_i *dbip)
Definition: osg-test.cpp:284
#define BN_VLIST_POLY_END
last vert (repeats 1st), draw poly
Definition: vlist.h:87
#define RT_DIR_NULL
Definition: raytrace.h:875
#define DB_OPEN_READONLY
Definition: raytrace.h:3550
struct db_i * db_open(const char *name, const char *mode)
Definition: db_open.c:59
Definition: color.c:51
#define DB_FULL_PATH_ROOT_DIR(_pp)
Definition: db_fullpath.h:54
#define RT_TESS_TOL_MAGIC
Definition: magic.h:170
int db_dirbuild(struct db_i *dbip)
Definition: db5_scan.c:301
void add_dp_to_scene(std::map< const struct directory *, osg::ref_ptr< osg::Group > > *osg_nodes, struct directory *dp, struct db_i *dbip)
Definition: osg-test.cpp:537
int add_path_to_scene(std::map< const struct directory *, osg::ref_ptr< osg::Group > > *osg_nodes, const struct db_full_path *path, struct db_i *dbip)
Definition: osg-test.cpp:560
void create_solid_nodes(std::map< const struct directory *, osg::ref_ptr< osg::Group > > *osg_nodes, struct directory *dp, struct db_i *dbip)
Definition: osg-test.cpp:206
point_t pt[BN_VLIST_CHUNK]
associated 3-point/vect
Definition: vlist.h:75
int d_flags
flags
Definition: raytrace.h:869
double fastf_t
Definition: defines.h:300
int bu_file_exists(const char *path, int *fd)
Definition: file.c:57
osg::ref_ptr< osg::Group > full_assembly_node(std::map< const struct directory *, osg::ref_ptr< osg::Group > > *osg_nodes, struct directory *dp, struct db_i *dbip)
Definition: osg-test.cpp:450
int characterize_dp(struct directory *dp, struct db_i *dbip)
Definition: osg-test.cpp:513
void rt_db_free_internal(struct rt_db_internal *ip)
Definition: dir.c:216
int main(int argc, char **argv)
Definition: osg-test.cpp:588
Definition: color.c:50
#define DB_FULL_PATH_POP(_pp)
Definition: db_fullpath.h:49
int db_path_to_mat(struct db_i *dbip, struct db_full_path *pathp, mat_t mat, int depth, struct resource *resp)
Definition: db_fullpath.c:630
#define BN_VLIST_POINT_DRAW
Draw a single point.
Definition: vlist.h:94
struct rt_g RTG
Definition: globals.c:39
int db_search(struct bu_ptbl *results, int flags, const char *filter, int path_c, struct directory **path_v, struct db_i *dbip)
Search for objects in a geometry database using filters.
Definition: search.c:2232