Panda3D
geomNode.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file geomNode.cxx
10  * @author drose
11  * @date 2002-02-23
12  */
13 
14 #include "geomNode.h"
15 #include "geom.h"
16 #include "geomTransformer.h"
17 #include "sceneGraphReducer.h"
18 #include "stateMunger.h"
19 #include "accumulatedAttribs.h"
20 #include "colorAttrib.h"
21 #include "colorScaleAttrib.h"
22 #include "cullFaceAttrib.h"
23 #include "texMatrixAttrib.h"
24 #include "textureAttrib.h"
25 #include "shaderAttrib.h"
26 #include "bamReader.h"
27 #include "bamWriter.h"
28 #include "cullableObject.h"
29 #include "cullHandler.h"
30 #include "cullTraverser.h"
31 #include "cullTraverserData.h"
32 #include "datagram.h"
33 #include "datagramIterator.h"
34 #include "indent.h"
35 #include "pset.h"
36 #include "config_pgraph.h"
38 #include "boundingBox.h"
39 #include "boundingSphere.h"
40 #include "config_mathutil.h"
42 
43 
44 bool allow_flatten_color = ConfigVariableBool
45  ("allow-flatten-color", false,
46  PRC_DESC("allows color to always be flattened to vertices"));
47 
48 TypeHandle GeomNode::_type_handle;
49 
50 /**
51  *
52  */
53 GeomNode::
54 GeomNode(const std::string &name) :
55  PandaNode(name)
56 {
57  _preserved = preserve_geom_nodes;
58 
59  // GeomNodes have a certain set of bits on by default.
60  set_into_collide_mask(get_default_collide_mask());
61 }
62 
63 /**
64  *
65  */
66 GeomNode::
67 GeomNode(const GeomNode &copy) :
68  PandaNode(copy),
69  _preserved(copy._preserved),
70  _cycler(copy._cycler)
71 {
72 }
73 
74 /**
75  *
76  */
77 GeomNode::
78 ~GeomNode() {
79 }
80 
81 /**
82  * Returns a newly-allocated PandaNode that is a shallow copy of this one. It
83  * will be a different pointer, but its internal data may or may not be shared
84  * with that of the original PandaNode. No children will be copied.
85  */
87 make_copy() const {
88  return new GeomNode(*this);
89 }
90 
91 /**
92  * Applies whatever attributes are specified in the AccumulatedAttribs object
93  * (and by the attrib_types bitmask) to the vertices on this node, if
94  * appropriate. If this node uses geom arrays like a GeomNode, the supplied
95  * GeomTransformer may be used to unify shared arrays across multiple
96  * different nodes.
97  *
98  * This is a generalization of xform().
99  */
101 apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
102  GeomTransformer &transformer) {
103  if (pgraph_cat.is_debug()) {
104  pgraph_cat.debug()
105  << "Transforming geometry:\n";
106  attribs.write(pgraph_cat.debug(false), attrib_types, 2);
107  }
108 
109  if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
110  if (!attribs._transform->is_identity()) {
111  transformer.transform_vertices(this, attribs._transform->get_mat());
112  }
113  }
114 
115  Thread *current_thread = Thread::get_current_thread();
116  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
117  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
118  PT(GeomList) geoms = cdata->modify_geoms();
119 
120  // Iterate based on the number of geoms, not using STL iterators. This
121  // allows us to append to the list in the code below (which we might do
122  // when doublesiding polys) without visiting those new nodes during the
123  // traversal.
124  size_t num_geoms = geoms->size();
125  for (size_t i = 0; i < num_geoms; ++i) {
126  GeomEntry *entry = &(*geoms)[i];
127  PT(Geom) new_geom = entry->_geom.get_read_pointer()->make_copy();
128 
129  AccumulatedAttribs geom_attribs = attribs;
130  entry->_state = geom_attribs.collect(entry->_state, attrib_types);
131 
132  bool any_changed = false;
133 
134  if ((attrib_types & SceneGraphReducer::TT_color) != 0) {
135  CPT(RenderAttrib) ra = geom_attribs._color;
136  if (ra != nullptr) {
137  int override = geom_attribs._color_override;
138  entry->_state = entry->_state->add_attrib(ra, override);
139  }
140 
141  ra = entry->_state->get_attrib_def(ColorAttrib::get_class_slot());
142  CPT (ColorAttrib) ca = DCAST(ColorAttrib, ra);
143  if (ca->get_color_type() != ColorAttrib::T_vertex) {
144  if(allow_flatten_color) {
145  if(transformer.set_color(new_geom, ca->get_color())) {
146  any_changed = true;
147  entry->_state = entry->_state->set_attrib(ColorAttrib::make_vertex());
148  }
149  } else {
150  if (transformer.remove_column(new_geom, InternalName::get_color())) {
151  any_changed = true;
152  }
153  }
154  }
155  }
156  if ((attrib_types & SceneGraphReducer::TT_color_scale) != 0) {
157  if (geom_attribs._color_scale != nullptr) {
158  CPT(ColorScaleAttrib) csa = DCAST(ColorScaleAttrib, geom_attribs._color_scale);
159  if (csa->get_scale() != LVecBase4(1.0f, 1.0f, 1.0f, 1.0f)) {
160 
161 
162  // Now, if we have an "off" or "flat" color attribute, we simply
163  // modify the color attribute, and leave the vertices alone.
164  CPT(RenderAttrib) ra = entry->_state->get_attrib_def(ColorAttrib::get_class_slot());
165  CPT(ColorAttrib) ca = DCAST(ColorAttrib, ra);
166  if(allow_flatten_color) {
167  if (transformer.transform_colors(new_geom, csa->get_scale())) {
168  any_changed = true;
169  }
170  } else {
171  if (ca->get_color_type() == ColorAttrib::T_off) {
172  entry->_state = entry->_state->set_attrib(ColorAttrib::make_vertex());
173  // ColorAttrib::T_off means the color scale becomes the new
174  // color.
175  entry->_state = entry->_state->set_attrib(ColorAttrib::make_flat(csa->get_scale()));
176 
177  } else if (ca->get_color_type() == ColorAttrib::T_flat) {
178  // ColorAttrib::T_flat means the color scale modulates the
179  // specified color to produce a new color.
180  const LColor &c1 = ca->get_color();
181  const LVecBase4 &c2 = csa->get_scale();
182  LColor color(c1[0] * c2[0], c1[1] * c2[1],
183  c1[2] * c2[2], c1[3] * c2[3]);
184  entry->_state = entry->_state->set_attrib(ColorAttrib::make_flat(color));
185 
186  } else {
187  // Otherwise, we have vertex color, and we just scale it
188  // normally.
189  if (transformer.transform_colors(new_geom, csa->get_scale())) {
190  any_changed = true;
191  }
192  entry->_state = entry->_state->set_attrib(ColorAttrib::make_vertex());
193  }
194  }
195  }
196  }
197  }
198 
199  if ((attrib_types & SceneGraphReducer::TT_tex_matrix) != 0) {
200  if (geom_attribs._tex_matrix != nullptr) {
201  // Determine which texture coordinate names are used more than once.
202  // This assumes we have discovered all of the textures that are in
203  // effect on the GeomNode; this may not be true if there is a
204  // texture that has been applied at a node above that from which we
205  // started the flatten operation, but caveat programmer.
206  NameCount name_count;
207 
208  if (geom_attribs._texture != nullptr) {
209  const TextureAttrib *ta = DCAST(TextureAttrib, geom_attribs._texture);
210  int num_on_stages = ta->get_num_on_stages();
211  for (int si = 0; si < num_on_stages; si++) {
212  TextureStage *stage = ta->get_on_stage(si);
213  const InternalName *name = stage->get_texcoord_name();
214  count_name(name_count, name);
215  }
216  }
217 
218  const TexMatrixAttrib *tma =
219  DCAST(TexMatrixAttrib, geom_attribs._tex_matrix);
220 
221  CPT(TexMatrixAttrib) new_tma = DCAST(TexMatrixAttrib, TexMatrixAttrib::make());
222 
223  int num_stages = tma->get_num_stages();
224  for (int i = 0; i < num_stages; i++) {
225  TextureStage *stage = tma->get_stage(i);
226  InternalName *name = stage->get_texcoord_name();
227  if (get_name_count(name_count, name) > 1) {
228  // We can't transform these texcoords, since the name is used by
229  // more than one active stage.
230  new_tma = DCAST(TexMatrixAttrib, new_tma->add_stage(stage, tma->get_transform(stage)));
231 
232  } else {
233  // It's safe to transform these texcoords; the name is used by
234  // no more than one active stage.
235  if (transformer.transform_texcoords(new_geom, name, name, tma->get_mat(stage))) {
236  any_changed = true;
237  }
238  }
239  }
240 
241  if (!new_tma->is_empty()) {
242  entry->_state = entry->_state->add_attrib(new_tma);
243  }
244  }
245  }
246 
247  if ((attrib_types & SceneGraphReducer::TT_other) != 0) {
248  entry->_state = geom_attribs._other->compose(entry->_state);
249  }
250 
251  // We handle cull_face last, since that might involve duplicating the
252  // geom, and we'd also like to duplicate all of the changes we may have
253  // applied in the above.
254 
255  if ((attrib_types & SceneGraphReducer::TT_cull_face) != 0) {
256  if (geom_attribs._cull_face != nullptr) {
257  const CullFaceAttrib *cfa = DCAST(CullFaceAttrib, geom_attribs._cull_face);
258  CullFaceAttrib::Mode mode = cfa->get_effective_mode();
259  switch (mode) {
260  case CullFaceAttrib::M_cull_none:
261  // Doublesided polys. Duplicate them.
262  {
263  bool has_normals = (new_geom->get_vertex_data()->has_column(InternalName::get_normal()));
264  if (has_normals) {
265  // If the geometry has normals, we have to duplicate it to
266  // reverse the normals on the duplicate copy.
267  PT(Geom) dup_geom = new_geom->reverse();
268  transformer.reverse_normals(dup_geom);
269 
270  geoms->push_back(GeomEntry(dup_geom, entry->_state));
271 
272  // The above push_back() operation might have invalidated our
273  // old pointer into the list, so we reassign it now.
274  entry = &(*geoms)[i];
275 
276  } else {
277  // If there are no normals, we can just doubleside it in
278  // place. This is preferable because we can share vertices.
279  new_geom->doubleside_in_place();
280  any_changed = true;
281  }
282  }
283  break;
284 
285  case CullFaceAttrib::M_cull_counter_clockwise:
286  // Reverse winding order.
287  new_geom->reverse_in_place();
288  transformer.reverse_normals(new_geom);
289  any_changed = true;
290  break;
291 
292  default:
293  break;
294  }
295  }
296  }
297 
298  if (any_changed) {
299  entry->_geom = new_geom;
300  }
301  }
302  }
303  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
304 
305  if ((attrib_types & SceneGraphReducer::TT_apply_texture_color) != 0) {
306  transformer.apply_texture_colors(this, attribs._other);
307  }
308 
309  transformer.register_vertices(this, false);
310 }
311 
312 /**
313  * Transforms the contents of this node by the indicated matrix, if it means
314  * anything to do so. For most kinds of nodes, this does nothing.
315  *
316  * For a GeomNode, this does the right thing, but it is better to use a
317  * GeomTransformer instead, since it will share the new arrays properly
318  * between different GeomNodes.
319  */
321 xform(const LMatrix4 &mat) {
322  GeomTransformer transformer;
323  transformer.transform_vertices(this, mat);
324 }
325 
326 
327 /**
328  * Returns true if it is generally safe to flatten out this particular kind of
329  * PandaNode by duplicating instances (by calling dupe_for_flatten()), false
330  * otherwise (for instance, a Camera cannot be safely flattened, because the
331  * Camera pointer itself is meaningful).
332  */
334 safe_to_flatten() const {
335  if (_preserved) {
336  return false;
337  }
338 
339  return true;
340 }
341 
342 /**
343  * Returns true if it is generally safe to combine this particular kind of
344  * PandaNode with other kinds of PandaNodes of compatible type, adding
345  * children or whatever. For instance, an LODNode should not be combined with
346  * any other PandaNode, because its set of children is meaningful.
347  */
349 safe_to_combine() const {
350  if (_preserved) {
351  return false;
352  }
353 
354  return true;
355 }
356 
357 /**
358  * The recursive implementation of prepare_scene(). Don't call this directly;
359  * call PandaNode::prepare_scene() or NodePath::prepare_scene() instead.
360  */
363  GeomTransformer &transformer, Thread *current_thread) {
364  PreparedGraphicsObjects *prepared_objects = gsg->get_prepared_objects();
365 
366  CDReader cdata(_cycler, current_thread);
367  GeomList::const_iterator gi;
368  CPT(GeomList) geoms = cdata->get_geoms();
369  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
370  const GeomEntry &entry = (*gi);
371  CPT(RenderState) geom_state = node_state->compose(entry._state);
372  CPT(Geom) geom = entry._geom.get_read_pointer();
373 
374  // Munge the geom as required by the GSG.
375  PT(GeomMunger) munger = gsg->get_geom_munger(geom_state, current_thread);
376  geom = transformer.premunge_geom(geom, munger);
377 
378  // Prepare each of the vertex arrays in the munged Geom.
379  CPT(GeomVertexData) vdata = geom->get_animated_vertex_data(false, current_thread);
380  GeomVertexDataPipelineReader vdata_reader(vdata, current_thread);
381  int num_arrays = vdata_reader.get_num_arrays();
382  for (int i = 0; i < num_arrays; ++i) {
383  CPT(GeomVertexArrayData) array = vdata_reader.get_array(i);
384  prepared_objects->enqueue_vertex_buffer((GeomVertexArrayData *)array.p());
385  }
386 
387  // And also each of the index arrays.
388  int num_primitives = geom->get_num_primitives();
389  for (int i = 0; i < num_primitives; ++i) {
390  CPT(GeomPrimitive) prim = geom->get_primitive(i);
391  prepared_objects->enqueue_index_buffer((GeomPrimitive *)prim.p());
392  }
393 
394  if (munger->is_of_type(StateMunger::get_class_type())) {
395  StateMunger *state_munger = (StateMunger *)munger.p();
396  geom_state = state_munger->munge_state(geom_state);
397  }
398 
399  // And now prepare each of the textures.
400  const TextureAttrib *ta;
401  if (geom_state->get_attrib(ta)) {
402  int num_stages = ta->get_num_on_stages();
403  for (int i = 0; i < num_stages; ++i) {
404  Texture *texture = ta->get_on_texture(ta->get_on_stage(i));
405  // TODO: prepare the sampler states, if specified.
406  if (texture != nullptr) {
407  prepared_objects->enqueue_texture(texture);
408  }
409  }
410  }
411 
412  // As well as the shaders.
413  const ShaderAttrib *sa;
414  if (geom_state->get_attrib(sa)) {
415  Shader *shader = (Shader *)sa->get_shader();
416  if (shader != nullptr) {
417  prepared_objects->enqueue_shader(shader);
418  }
419  // TODO: prepare the shader inputs.
420  }
421  }
422 
423  PandaNode::r_prepare_scene(gsg, node_state, transformer, current_thread);
424 }
425 
426 
427 /**
428  * Collapses this node with the other node, if possible, and returns a pointer
429  * to the combined node, or NULL if the two nodes cannot safely be combined.
430  *
431  * The return value may be this, other, or a new node altogether.
432  *
433  * This function is called from GraphReducer::flatten(), and need not deal
434  * with children; its job is just to decide whether to collapse the two nodes
435  * and what the collapsed node should look like.
436  */
438 combine_with(PandaNode *other) {
439  if (is_exact_type(get_class_type()) &&
440  other->is_exact_type(get_class_type())) {
441  // Two GeomNodes can combine by moving Geoms from one to the other.
442  GeomNode *gother = DCAST(GeomNode, other);
443  add_geoms_from(gother);
444  return this;
445  }
446 
447  return PandaNode::combine_with(other);
448 }
449 
450 /**
451  * This is used to support NodePath::calc_tight_bounds(). It is not intended
452  * to be called directly, and it has nothing to do with the normal Panda
453  * bounding-volume computation.
454  *
455  * If the node contains any geometry, this updates min_point and max_point to
456  * enclose its bounding box. found_any is to be set true if the node has any
457  * geometry at all, or left alone if it has none. This method may be called
458  * over several nodes, so it may enter with min_point, max_point, and
459  * found_any already set.
460  */
461 CPT(TransformState) GeomNode::
462 calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, bool &found_any,
463  const TransformState *transform, Thread *current_thread) const {
464  CPT(TransformState) next_transform =
465  PandaNode::calc_tight_bounds(min_point, max_point, found_any, transform,
466  current_thread);
467 
468  const LMatrix4 &mat = next_transform->get_mat();
469 
470  CDReader cdata(_cycler, current_thread);
471  GeomList::const_iterator gi;
472  CPT(GeomList) geoms = cdata->get_geoms();
473  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
474  CPT(Geom) geom = (*gi)._geom.get_read_pointer();
475  geom->calc_tight_bounds(min_point, max_point, found_any,
476  geom->get_animated_vertex_data(true, current_thread),
477  !next_transform->is_identity(), mat,
478  current_thread);
479  }
480 
481  return next_transform;
482 }
483 
484 /**
485  * Returns true if there is some value to visiting this particular node during
486  * the cull traversal for any camera, false otherwise. This will be used to
487  * optimize the result of get_net_draw_show_mask(), so that any subtrees that
488  * contain only nodes for which is_renderable() is false need not be visited.
489  */
490 bool GeomNode::
491 is_renderable() const {
492  return true;
493 }
494 
495 /**
496  * Adds the node's contents to the CullResult we are building up during the
497  * cull traversal, so that it will be drawn at render time. For most nodes
498  * other than GeomNodes, this is a do-nothing operation.
499  */
500 void GeomNode::
502  trav->_geom_nodes_pcollector.add_level(1);
503 
504  if (pgraph_cat.is_spam()) {
505  pgraph_cat.spam()
506  << "Found " << *this << " in state " << *data._state
507  << " draw_mask = " << data._draw_mask << "\n";
508  }
509 
510  Thread *current_thread = trav->get_current_thread();
511 
512  // Get all the Geoms, with no decalling.
513  Geoms geoms = get_geoms(current_thread);
514  int num_geoms = geoms.get_num_geoms();
515  trav->_geoms_pcollector.add_level(num_geoms);
516  CPT(TransformState) internal_transform = data.get_internal_transform(trav);
517 
518  for (int i = 0; i < num_geoms; i++) {
519  CPT(Geom) geom = geoms.get_geom(i);
520  if (geom->is_empty()) {
521  continue;
522  }
523 
524  CPT(RenderState) state = data._state->compose(geoms.get_geom_state(i));
525  if (state->has_cull_callback() && !state->cull_callback(trav, data)) {
526  // Cull.
527  continue;
528  }
529 
530  // Cull the Geom bounding volume against the view frustum andor the cull
531  // planes. Don't bother unless we've got more than one Geom, since
532  // otherwise the bounding volume of the GeomNode is (probably) the same as
533  // that of the one Geom, and we've already culled against that.
534  if (num_geoms > 1) {
535  if (data._view_frustum != nullptr) {
536  // Cull the individual Geom against the view frustum.
537  CPT(BoundingVolume) geom_volume = geom->get_bounds(current_thread);
538  const GeometricBoundingVolume *geom_gbv =
539  geom_volume->as_geometric_bounding_volume();
540 
541  int result = data._view_frustum->contains(geom_gbv);
542  if (result == BoundingVolume::IF_no_intersection) {
543  // Cull this Geom.
544  continue;
545  }
546  }
547  if (!data._cull_planes->is_empty()) {
548  // Also cull the Geom against the cull planes.
549  CPT(BoundingVolume) geom_volume = geom->get_bounds(current_thread);
550  const GeometricBoundingVolume *geom_gbv =
551  geom_volume->as_geometric_bounding_volume();
552  int result;
553  data._cull_planes->do_cull(result, state, geom_gbv);
554  if (result == BoundingVolume::IF_no_intersection) {
555  // Cull.
556  continue;
557  }
558  }
559  }
560 
561  CullableObject *object =
562  new CullableObject(std::move(geom), std::move(state), internal_transform);
563  trav->get_cull_handler()->record_object(object, trav);
564  }
565 }
566 
567 /**
568  * Returns the subset of CollideMask bits that may be set for this particular
569  * type of PandaNode. For most nodes, this is 0; it doesn't make sense to set
570  * a CollideMask for most kinds of nodes.
571  *
572  * For nodes that can be collided with, such as GeomNode and CollisionNode,
573  * this returns all bits on.
574  */
576 get_legal_collide_mask() const {
577  return CollideMask::all_on();
578 }
579 
580 /**
581  * Adds a new Geom to the node. The geom is given the indicated state (which
582  * may be RenderState::make_empty(), to completely inherit its state from the
583  * scene graph).
584  */
586 add_geom(Geom *geom, const RenderState *state) {
587  nassertv(geom != nullptr);
588  nassertv(geom->check_valid());
589  nassertv(state != nullptr);
590 
591  Thread *current_thread = Thread::get_current_thread();
592  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
593  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
594 
595  cdata->modify_geoms()->push_back(GeomEntry(geom, state));
596  }
597  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
598 
599  mark_internal_bounds_stale();
600 }
601 
602 /**
603  * Copies the Geoms (and their associated RenderStates) from the indicated
604  * GeomNode into this one.
605  */
607 add_geoms_from(const GeomNode *other) {
608  Thread *current_thread = Thread::get_current_thread();
609  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
610  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
611  CDStageReader cdata_other(other->_cycler, pipeline_stage, current_thread);
612 
613  GeomList::const_iterator gi;
614  CPT(GeomList) other_geoms = cdata_other->get_geoms();
615  PT(GeomList) this_geoms = cdata->modify_geoms();
616  for (gi = other_geoms->begin(); gi != other_geoms->end(); ++gi) {
617  const GeomEntry &entry = (*gi);
618  nassertv(entry._geom.get_read_pointer()->check_valid());
619  this_geoms->push_back(entry);
620  }
621  }
622  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
623 
624  mark_internal_bounds_stale();
625 }
626 
627 /**
628  * Replaces the nth Geom of the node with a new pointer. There must already
629  * be a Geom in this slot.
630  *
631  * Note that if this method is called in a downstream stage (for instance,
632  * during cull or draw), then it will propagate the new list of Geoms upstream
633  * all the way to pipeline stage 0, which may step on changes that were made
634  * independently in pipeline stage 0. Use with caution.
635  */
637 set_geom(int n, Geom *geom) {
638  nassertv(geom != nullptr);
639  nassertv(geom->check_valid());
640 
641  CDWriter cdata(_cycler, true);
642  PT(GeomList) geoms = cdata->modify_geoms();
643  nassertv(n >= 0 && n < (int)geoms->size());
644  (*geoms)[n]._geom = geom;
645 
646  mark_internal_bounds_stale();
647 }
648 
649 /**
650  * Verifies that the each Geom within the GeomNode reference vertices that
651  * actually exist within its GeomVertexData. Returns true if the GeomNode
652  * appears to be valid, false otherwise.
653  */
655 check_valid() const {
656  int num_geoms = get_num_geoms();
657  for (int i = 0; i < num_geoms; i++) {
658  const Geom *geom = get_geom(i);
659  if (!geom->check_valid()) {
660  return false;
661  }
662  }
663 
664  return true;
665 }
666 
667 /**
668  * Calls decompose() on each Geom with the GeomNode. This decomposes higher-
669  * order primitive types, like triangle strips, into lower-order types like
670  * indexed triangles. Normally there is no reason to do this, but it can be
671  * useful as an early preprocessing step, to allow a later call to unify() to
672  * proceed more quickly.
673  *
674  * See also SceneGraphReducer::decompose(), which is the normal way this is
675  * called.
676  */
678 decompose() {
679  Thread *current_thread = Thread::get_current_thread();
680  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
681  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
682 
683  GeomList::iterator gi;
684  PT(GeomList) geoms = cdata->modify_geoms();
685  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
686  GeomEntry &entry = (*gi);
687  nassertv(entry._geom.test_ref_count_integrity());
688  PT(Geom) geom = entry._geom.get_write_pointer();
689  geom->decompose_in_place();
690  }
691  }
692  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
693 }
694 
695 /**
696  * Attempts to unify all of the Geoms contained within this node into a single
697  * Geom, or at least as few Geoms as possible. In turn, the individual
698  * GeomPrimitives contained within each resulting Geom are also unified. The
699  * goal is to reduce the number of GeomPrimitives within the node as far as
700  * possible. This may result in composite primitives, such as triangle strips
701  * and triangle fans, being decomposed into triangles. See also
702  * Geom::unify().
703  *
704  * max_indices represents the maximum number of indices that will be put in
705  * any one GeomPrimitive. If preserve_order is true, then the primitives will
706  * not be reordered during the operation, even if this results in a suboptimal
707  * result.
708  *
709  * In order for this to be successful, the primitives must reference the same
710  * GeomVertexData, have the same fundamental primitive type, and have
711  * compatible shade models.
712  */
714 unify(int max_indices, bool preserve_order) {
715  bool any_changed = false;
716 
717  Thread *current_thread = Thread::get_current_thread();
718  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
719  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
720 
721  PT(GeomList) new_geoms = new GeomList;
722 
723  // Try to unify each Geom with each preceding Geom. This is an n^2
724  // operation, but usually there are only a handful of Geoms to consider,
725  // so that's not a big deal.
726  GeomList::const_iterator gi;
727  CPT(GeomList) old_geoms = cdata->get_geoms();
728  for (gi = old_geoms->begin(); gi != old_geoms->end(); ++gi) {
729  const GeomEntry &old_entry = (*gi);
730 
731  bool unified = false;
732 
733  // Go from back to front, to minimize damage to the primitive ordering.
734  GeomList::reverse_iterator gj;
735  for (gj = new_geoms->rbegin(); gj != new_geoms->rend() && !unified; ++gj) {
736  GeomEntry &new_entry = (*gj);
737  if (old_entry._state == new_entry._state) {
738  // Both states match, so try to combine the primitives.
739  CPT(Geom) old_geom = old_entry._geom.get_read_pointer();
740  PT(Geom) new_geom = new_entry._geom.get_write_pointer();
741  if (new_geom->copy_primitives_from(old_geom)) {
742  // Successfully combined!
743  unified = true;
744  any_changed = true;
745  }
746  }
747 
748  if (preserve_order) {
749  // If we're insisting on preserving the order, we can only attempt
750  // to merge with the tail of the list.
751  break;
752  }
753  }
754 
755  if (!unified) {
756  // Couldn't unify this Geom with anything, so just add it to the
757  // output list.
758  new_geoms->push_back(old_entry);
759  }
760  }
761 
762  // Done! We'll keep whatever's left in the output list.
763  cdata->set_geoms(new_geoms);
764 
765  // Finally, go back through and unify the resulting geom(s).
766  GeomList::iterator wgi;
767  for (wgi = new_geoms->begin(); wgi != new_geoms->end(); ++wgi) {
768  GeomEntry &entry = (*wgi);
769  nassertv(entry._geom.test_ref_count_integrity());
770  PT(Geom) geom = entry._geom.get_write_pointer();
771  geom->unify_in_place(max_indices, preserve_order);
772  }
773  }
774  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
775 
776  if (any_changed) {
777  mark_internal_bounds_stale();
778  }
779 }
780 
781 /**
782  * Writes a short description of all the Geoms in the node.
783  */
785 write_geoms(std::ostream &out, int indent_level) const {
786  CDReader cdata(_cycler);
787  write(out, indent_level);
788  GeomList::const_iterator gi;
789  CPT(GeomList) geoms = cdata->get_geoms();
790  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
791  const GeomEntry &entry = (*gi);
792  indent(out, indent_level + 2)
793  << *entry._geom.get_read_pointer() << " " << *entry._state << "\n";
794  }
795 }
796 
797 /**
798  * Writes a detailed description of all the Geoms in the node.
799  */
801 write_verbose(std::ostream &out, int indent_level) const {
802  CDReader cdata(_cycler);
803  write(out, indent_level);
804  GeomList::const_iterator gi;
805  CPT(GeomList) geoms = cdata->get_geoms();
806  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
807  const GeomEntry &entry = (*gi);
808  CPT(Geom) geom = entry._geom.get_read_pointer();
809  indent(out, indent_level + 2)
810  << *geom << " " << *entry._state << "\n";
811  geom->write(out, indent_level + 4);
812  }
813 }
814 
815 /**
816  *
817  */
818 void GeomNode::
819 output(std::ostream &out) const {
820  // Accumulate the total set of RenderAttrib types that are applied to any of
821  // our Geoms, so we can output them too. The result will be the list of
822  // attrib types that might be applied to some Geoms, but not necessarily to
823  // all Geoms.
824 
825  CDReader cdata(_cycler);
826 
827  pset<TypeHandle> attrib_types;
828 
829  GeomList::const_iterator gi;
830  CPT(RenderState) common = RenderState::make_empty();
831 
832  CPT(GeomList) geoms = cdata->get_geoms();
833  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
834  const GeomEntry &entry = (*gi);
835  common = common->compose(entry._state);
836  }
837 
838  PandaNode::output(out);
839  out << " (" << geoms->size() << " geoms";
840 
841  if (!common->is_empty()) {
842  out << ": " << *common;
843  }
844 
845  out << ")";
846 }
847 
848 /**
849  * A simple downcast check. Returns true if this kind of node happens to
850  * inherit from GeomNode, false otherwise.
851  *
852  * This is provided as a a faster alternative to calling
853  * is_of_type(GeomNode::get_class_type()), since this test is so important to
854  * rendering.
855  */
857 is_geom_node() const {
858  return true;
859 }
860 
861 /**
862  * Uses the indicated GSG to premunge the Geoms in this node to optimize them
863  * for eventual rendering. See SceneGraphReducer::premunge().
864  */
867  const RenderState *node_state,
868  GeomTransformer &transformer) {
869  Thread *current_thread = Thread::get_current_thread();
870 
871  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
872  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
873 
874  GeomList::iterator gi;
875  PT(GeomList) geoms = cdata->modify_geoms();
876  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
877  GeomEntry &entry = (*gi);
878  CPT(RenderState) geom_state = node_state->compose(entry._state);
879  CPT(Geom) geom = entry._geom.get_read_pointer();
880  PT(GeomMunger) munger = gsg->get_geom_munger(geom_state, current_thread);
881  entry._geom = transformer.premunge_geom(geom, munger);
882  }
883  }
884  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
885 }
886 
887 /**
888  * Recursively calls Geom::mark_bounds_stale() on every Geom at this node and
889  * below.
890  */
891 void GeomNode::
892 r_mark_geom_bounds_stale(Thread *current_thread) {
893  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
894  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
895 
896  GeomList::iterator gi;
897  PT(GeomList) geoms = cdata->modify_geoms();
898  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
899  GeomEntry &entry = (*gi);
900  entry._geom.get_read_pointer()->mark_bounds_stale();
901  }
902  }
903  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
904  mark_internal_bounds_stale();
905 
906  PandaNode::r_mark_geom_bounds_stale(current_thread);
907 }
908 
909 /**
910  * Returns a newly-allocated BoundingVolume that represents the internal
911  * contents of the node. Should be overridden by PandaNode classes that
912  * contain something internally.
913  */
914 void GeomNode::
915 compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
916  int &internal_vertices,
917  int pipeline_stage,
918  Thread *current_thread) const {
919  int num_vertices = 0;
920 
921  CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
922 
923  pvector<const BoundingVolume *> child_volumes;
924  pvector<CPT(BoundingVolume) > child_volumes_ref;
925  bool all_box = true;
926 
927  GeomList::const_iterator gi;
928  CPT(GeomList) geoms = cdata->get_geoms();
929  child_volumes.reserve(geoms->size());
930  child_volumes_ref.reserve(geoms->size());
931 
932  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
933  const GeomEntry &entry = (*gi);
934  CPT(Geom) geom = entry._geom.get_read_pointer();
935  CPT(BoundingVolume) volume = geom->get_bounds();
936 
937  if (!volume->is_empty()) {
938  child_volumes.push_back(volume);
939  child_volumes_ref.push_back(volume);
940  if (!volume->is_exact_type(BoundingBox::get_class_type())) {
941  all_box = false;
942  }
943  }
944  num_vertices += geom->get_nested_vertices();
945  }
946 
947  PT(GeometricBoundingVolume) gbv;
948 
949  BoundingVolume::BoundsType btype = get_bounds_type();
950  if (btype == BoundingVolume::BT_default) {
951  btype = bounds_type;
952  }
953 
954  if (btype == BoundingVolume::BT_box ||
955  (btype != BoundingVolume::BT_sphere && all_box)) {
956  // If all of the child volumes are a BoundingBox, then our volume is also
957  // a BoundingBox.
958  gbv = new BoundingBox;
959  } else {
960  // Otherwise, it's a sphere.
961  gbv = new BoundingSphere;
962  }
963 
964  if (child_volumes.size() > 0) {
965  const BoundingVolume **child_begin = &child_volumes[0];
966  const BoundingVolume **child_end = child_begin + child_volumes.size();
967  ((BoundingVolume *)gbv)->around(child_begin, child_end);
968  }
969 
970  internal_bounds = gbv;
971  internal_vertices = num_vertices;
972 }
973 
974 /**
975  * Tells the BamReader how to create objects of type GeomNode.
976  */
979  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
980 }
981 
982 /**
983  * Writes the contents of this object to the datagram for shipping out to a
984  * Bam file.
985  */
987 write_datagram(BamWriter *manager, Datagram &dg) {
988  PandaNode::write_datagram(manager, dg);
989  manager->write_cdata(dg, _cycler);
990 }
991 
992 /**
993  * Called by the BamReader to perform any final actions needed for setting up
994  * the object after all objects have been read and all pointers have been
995  * completed.
996  */
998 finalize(BamReader *manager) {
999  if (manager->get_file_minor_ver() < 14) {
1000  // With version 6.14, we changed the default ColorAttrib behavior from
1001  // make_vertex() to make_flat(). This means that every Geom that contains
1002  // vertex colors now needs to have an explicit ColorAttrib::make_vertex()
1003  // on its state.
1004 
1005  // Since we shouldn't override a different ColorAttrib inherited from
1006  // above, we create this new attrib with an override of -1.
1007 
1008  CPT(InternalName) color = InternalName::get_color();
1009  CPT(RenderAttrib) vertex_color = ColorAttrib::make_vertex();
1010 
1011  Thread *current_thread = Thread::get_current_thread();
1012  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1013  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1014 
1015  GeomList::iterator gi;
1016  PT(GeomList) geoms = cdata->modify_geoms();
1017  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
1018  GeomEntry &entry = (*gi);
1019  CPT(Geom) geom = entry._geom.get_read_pointer();
1020 
1021  // Force the various GeomVertexArrayFormat objects to finalize
1022  // themselves. We have to do this before we can reliably call
1023  // GeomVertexData::has_column().
1024  CPT(GeomVertexData) vdata = geom->get_vertex_data(current_thread);
1025  CPT(GeomVertexFormat) vformat = vdata->get_format();
1026  for (size_t i = 0; i < vformat->get_num_arrays(); ++i) {
1027  const GeomVertexArrayFormat *varray = vformat->get_array(i);
1028  manager->finalize_now((GeomVertexArrayFormat *)varray);
1029  }
1030 
1031  if (vdata->has_column(color) &&
1032  !entry._state->has_attrib(ColorAttrib::get_class_slot())) {
1033  // We'll be reassigning the RenderState. Therefore, save it
1034  // temporarily to increment its reference count.
1035  PT(BamAuxData) aux_data = new BamAuxData;
1036  aux_data->_hold_state = entry._state;
1037  manager->set_aux_data((RenderState *)entry._state.p(), "hold_state", aux_data);
1038 
1039  entry._state = entry._state->add_attrib(vertex_color, -1);
1040  }
1041  }
1042  }
1043  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1044  }
1045 }
1046 
1047 /**
1048  * This function is called by the BamReader's factory when a new object of
1049  * type GeomNode is encountered in the Bam file. It should create the
1050  * GeomNode and extract its information from the file.
1051  */
1052 TypedWritable *GeomNode::
1053 make_from_bam(const FactoryParams &params) {
1054  GeomNode *node = new GeomNode("");
1055  DatagramIterator scan;
1056  BamReader *manager;
1057 
1058  parse_params(params, scan, manager);
1059  node->fillin(scan, manager);
1060 
1061  if (manager->get_file_minor_ver() < 14) {
1062  manager->register_finalize(node);
1063  }
1064 
1065  return node;
1066 }
1067 
1068 /**
1069  * This internal function is called by make_from_bam to read in all of the
1070  * relevant data from the BamFile for the new GeomNode.
1071  */
1072 void GeomNode::
1073 fillin(DatagramIterator &scan, BamReader *manager) {
1074  PandaNode::fillin(scan, manager);
1075  manager->read_cdata(scan, _cycler);
1076 }
1077 
1078 /**
1079  *
1080  */
1081 GeomNode::CData::
1082 CData(const GeomNode::CData &copy) :
1083  _geoms(copy._geoms)
1084 {
1085 }
1086 
1087 /**
1088  *
1089  */
1090 CycleData *GeomNode::CData::
1091 make_copy() const {
1092  return new CData(*this);
1093 }
1094 
1095 /**
1096  * Writes the contents of this object to the datagram for shipping out to a
1097  * Bam file.
1098  */
1099 void GeomNode::CData::
1100 write_datagram(BamWriter *manager, Datagram &dg) const {
1101  CPT(GeomList) geoms = _geoms.get_read_pointer();
1102  int num_geoms = geoms->size();
1103  nassertv(num_geoms == (int)(uint16_t)num_geoms);
1104  dg.add_uint16(num_geoms);
1105 
1106  GeomList::const_iterator gi;
1107  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
1108  const GeomEntry &entry = (*gi);
1109  manager->write_pointer(dg, entry._geom.get_read_pointer());
1110  manager->write_pointer(dg, entry._state);
1111  }
1112 }
1113 
1114 /**
1115  * Receives an array of pointers, one for each time manager->read_pointer()
1116  * was called in fillin(). Returns the number of pointers processed.
1117  */
1118 int GeomNode::CData::
1119 complete_pointers(TypedWritable **p_list, BamReader *manager) {
1120  int pi = CycleData::complete_pointers(p_list, manager);
1121 
1122  // Get the geom and state pointers.
1123  GeomList::iterator gi;
1124  PT(GeomList) geoms = _geoms.get_write_pointer();
1125  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
1126  GeomEntry &entry = (*gi);
1127  entry._geom = DCAST(Geom, p_list[pi++]);
1128  entry._state = DCAST(RenderState, p_list[pi++]);
1129  }
1130 
1131  return pi;
1132 }
1133 
1134 /**
1135  * This internal function is called by make_from_bam to read in all of the
1136  * relevant data from the BamFile for the new GeomNode.
1137  */
1138 void GeomNode::CData::
1139 fillin(DatagramIterator &scan, BamReader *manager) {
1140  int num_geoms = scan.get_uint16();
1141  // Read the list of geoms and states. Push back a NULL for each one.
1142  PT(GeomList) geoms = new GeomList;
1143  geoms->reserve(num_geoms);
1144  for (int i = 0; i < num_geoms; i++) {
1145  manager->read_pointer(scan);
1146  manager->read_pointer(scan);
1147  geoms->push_back(GeomEntry(nullptr, nullptr));
1148  }
1149  _geoms = geoms;
1150 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void parse_params(const FactoryParams &params, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
Definition: bamReader.I:275
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This class is used by the SceneGraphReducer to maintain and accumulate the set of attributes we have ...
void collect(PandaNode *node, int attrib_types)
Collects the state and transform from the indicated node and adds it to the accumulator,...
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
Definition: bamReader.cxx:808
void finalize_now(TypedWritable *whom)
Forces the finalization of a particular object.
Definition: bamReader.cxx:897
void set_aux_data(TypedWritable *obj, const std::string &name, AuxData *data)
Associates an arbitrary block of data with the indicated object (or NULL), and the indicated name.
Definition: bamReader.cxx:167
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
Definition: bamReader.cxx:610
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
Definition: bamReader.I:83
void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler)
Reads in the indicated CycleData object.
Definition: bamReader.cxx:695
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler)
Writes out the indicated CycleData object.
Definition: bamWriter.cxx:425
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
Definition: bamWriter.cxx:317
static BitMask< uint32_t, nbits > all_on()
Returns a BitMask whose bits are all on.
Definition: bitMask.I:32
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
Definition: boundingBox.h:29
This defines a bounding sphere, consisting of a center and a radius.
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
Indicates what color should be applied to renderable geometry.
Definition: colorAttrib.h:27
Applies a scale to colors in the scene graph and on vertices.
This is a convenience class to specialize ConfigVariable as a boolean type.
This is similar to RefCountObj, but it implements a CopyOnWriteObject inheritance instead of a Refere...
Indicates which faces should be culled based on their vertex ordering.
get_effective_mode
Returns the effective culling mode.
virtual void record_object(CullableObject *object, const CullTraverser *traverser)
This callback function is intended to be overridden by a derived class.
Definition: cullHandler.cxx:43
This collects together the pieces of data that are accumulated for each node while walking the scene ...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
CullHandler * get_cull_handler() const
Returns the object that will receive the culled Geoms.
Thread * get_current_thread() const
Returns the currently-executing thread object, as passed to the CullTraverser constructor.
Definition: cullTraverser.I:27
The smallest atom of cull.
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
This class is similar to CycleDataReader, except it allows reading from a particular stage of the pip...
This class is similar to CycleDataWriter, except it allows writing to a particular stage of the pipel...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:50
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
Definition: cycleData.cxx:48
A class to retrieve the individual data elements previously stored in a Datagram.
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
Definition: datagram.I:85
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
Definition: factory.I:73
Objects of this class are used to convert vertex data from a Geom into a format suitable for passing ...
Definition: geomMunger.h:50
A node that holds Geom objects, renderable pieces of geometry.
Definition: geomNode.h:34
void add_geoms_from(const GeomNode *other)
Copies the Geoms (and their associated RenderStates) from the indicated GeomNode into this one.
Definition: geomNode.cxx:607
void do_premunge(GraphicsStateGuardianBase *gsg, const RenderState *node_state, GeomTransformer &transformer)
Uses the indicated GSG to premunge the Geoms in this node to optimize them for eventual rendering.
Definition: geomNode.cxx:866
void write_geoms(std::ostream &out, int indent_level) const
Writes a short description of all the Geoms in the node.
Definition: geomNode.cxx:785
void add_geom(Geom *geom, const RenderState *state=RenderState::make_empty())
Adds a new Geom to the node.
Definition: geomNode.cxx:586
virtual bool safe_to_combine() const
Returns true if it is generally safe to combine this particular kind of PandaNode with other kinds of...
Definition: geomNode.cxx:349
get_num_geoms
Returns the number of geoms in the node.
Definition: geomNode.h:71
Geoms get_geoms(Thread *current_thread=Thread::get_current_thread()) const
Returns an object that can be used to walk through the list of geoms of the node.
Definition: geomNode.I:177
virtual PandaNode * make_copy() const
Returns a newly-allocated PandaNode that is a shallow copy of this one.
Definition: geomNode.cxx:87
void unify(int max_indices, bool preserve_order)
Attempts to unify all of the Geoms contained within this node into a single Geom, or at least as few ...
Definition: geomNode.cxx:714
virtual void xform(const LMatrix4 &mat)
Transforms the contents of this node by the indicated matrix, if it means anything to do so.
Definition: geomNode.cxx:321
virtual PandaNode * combine_with(PandaNode *other)
Collapses this node with the other node, if possible, and returns a pointer to the combined node,...
Definition: geomNode.cxx:438
virtual void apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types, GeomTransformer &transformer)
Applies whatever attributes are specified in the AccumulatedAttribs object (and by the attrib_types b...
Definition: geomNode.cxx:101
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Definition: geomNode.cxx:987
virtual bool safe_to_flatten() const
Returns true if it is generally safe to flatten out this particular kind of PandaNode by duplicating ...
Definition: geomNode.cxx:334
static void register_with_read_factory()
Tells the BamReader how to create objects of type GeomNode.
Definition: geomNode.cxx:978
virtual bool is_renderable() const
Returns true if there is some value to visiting this particular node during the cull traversal for an...
virtual CollideMask get_legal_collide_mask() const
Returns the subset of CollideMask bits that may be set for this particular type of PandaNode.
Definition: geomNode.cxx:576
virtual bool is_geom_node() const
A simple downcast check.
Definition: geomNode.cxx:857
virtual void add_for_draw(CullTraverser *trav, CullTraverserData &data)
Adds the node's contents to the CullResult we are building up during the cull traversal,...
void set_geom(int n, Geom *geom)
Replaces the nth Geom of the node with a new pointer.
Definition: geomNode.cxx:637
virtual void r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state, GeomTransformer &transformer, Thread *current_thread)
The recursive implementation of prepare_scene().
Definition: geomNode.cxx:362
void write_verbose(std::ostream &out, int indent_level) const
Writes a detailed description of all the Geoms in the node.
Definition: geomNode.cxx:801
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
Definition: geomNode.cxx:998
bool check_valid() const
Verifies that the each Geom within the GeomNode reference vertices that actually exist within its Geo...
Definition: geomNode.cxx:655
void decompose()
Calls decompose() on each Geom with the GeomNode.
Definition: geomNode.cxx:678
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
Definition: geomPrimitive.h:56
An object specifically designed to transform the vertices of a Geom without disturbing indexing or af...
bool apply_texture_colors(Geom *geom, TextureStage *ts, Texture *tex, const TexMatrixAttrib *tma, const LColor &base_color, bool keep_vertex_color)
Removes textures from Geoms by applying the texture colors to the vertices.
bool reverse_normals(Geom *geom)
Reverses the lighting normals on the vertex data, if any.
bool transform_colors(Geom *geom, const LVecBase4 &scale)
Transforms the colors in the indicated Geom by the indicated scale.
bool transform_vertices(Geom *geom, const LMatrix4 &mat)
Transforms the vertices and the normals in the indicated Geom by the indicated matrix.
bool set_color(Geom *geom, const LColor &color)
Overrides the color indicated within the Geom with the given replacement color.
bool remove_column(Geom *geom, const InternalName *column)
Removes the named column from the vertex data in the Geom.
bool transform_texcoords(Geom *geom, const InternalName *from_name, InternalName *to_name, const LMatrix4 &mat)
Transforms the texture coordinates in the indicated Geom by the indicated matrix.
void register_vertices(Geom *geom, bool might_have_unused)
Records the association of the Geom with its GeomVertexData, for the purpose of later removing unused...
This is the data for one array of a GeomVertexData structure.
This describes the structure of a single array within a Geom data.
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
This class defines the physical layout of the vertex data stored within a Geom.
A container for geometry primitives.
Definition: geom.h:54
bool check_valid() const
Verifies that the all of the primitives within the geom reference vertices that actually exist within...
Definition: geom.cxx:1074
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
virtual GeometricBoundingVolume * as_geometric_bounding_volume() final
Virtual downcast method.
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
Encodes a string name in a hash table, mapping it to a pointer.
Definition: internalName.h:38
A basic node of the scene graph or data graph.
Definition: pandaNode.h:65
virtual PandaNode * combine_with(PandaNode *other)
Collapses this PandaNode with the other PandaNode, if possible, and returns a pointer to the combined...
Definition: pandaNode.cxx:319
virtual void r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state, GeomTransformer &transformer, Thread *current_thread)
The recursive implementation of prepare_scene().
Definition: pandaNode.cxx:2436
get_bounds_type
Returns the bounding volume type set with set_bounds_type().
Definition: pandaNode.h:293
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Definition: pandaNode.cxx:3583
A table of objects that are saved within the graphics context for reference by handle later.
void enqueue_vertex_buffer(GeomVertexArrayData *data)
Indicates that a buffer would like to be put on the list to be prepared when the GSG is next ready to...
void enqueue_texture(Texture *tex)
Indicates that a texture would like to be put on the list to be prepared when the GSG is next ready t...
void enqueue_index_buffer(GeomPrimitive *data)
Indicates that a buffer would like to be put on the list to be prepared when the GSG is next ready to...
void enqueue_shader(Shader *shader)
Indicates that a shader would like to be put on the list to be prepared when the GSG is next ready to...
This is the base class for a number of render attributes (other than transform) that may be set on sc...
Definition: renderAttrib.h:51
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
Definition: shader.h:49
This is just a simple derivative of GeomMunger that adds the ability to munge states.
Definition: stateMunger.h:26
Applies a transform matrix to UV's before they are rendered.
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
Definition: textureAttrib.h:31
get_num_on_stages
Returns the number of stages that are turned on by the attribute.
Definition: textureAttrib.h:55
get_on_texture
Returns the texture associated with the indicated stage, or NULL if no texture is associated.
Definition: textureAttrib.h:69
get_on_stage
Returns the nth stage turned on by the attribute, sorted in render order.
Definition: textureAttrib.h:55
Defines the properties of a named stage of the multitexture pipeline.
Definition: textureStage.h:35
get_texcoord_name
See set_texcoord_name.
Definition: textureStage.h:194
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition: texture.h:71
A thread; that is, a lightweight process.
Definition: thread.h:46
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition: thread.h:109
Indicates a coordinate-system transform on vertices.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
Definition: typedObject.I:38
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
This is our own Panda specialization on the default STL map.
Definition: pmap.h:49
This is our own Panda specialization on the default STL set.
Definition: pset.h:49
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CPT(TransformState) GeomNode
This is used to support NodePath::calc_tight_bounds().
Definition: geomNode.cxx:461
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition: indent.cxx:20
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.