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  */
100 void GeomNode::
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  */
320 void GeomNode::
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  */
333 bool GeomNode::
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  */
348 bool GeomNode::
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  */
361 void GeomNode::
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  */
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  // Get all the Geoms, with no decalling.
511  Geoms geoms = get_geoms(trav->get_current_thread());
512  int num_geoms = geoms.get_num_geoms();
513  trav->_geoms_pcollector.add_level(num_geoms);
514  CPT(TransformState) internal_transform = data.get_internal_transform(trav);
515 
516  for (int i = 0; i < num_geoms; i++) {
517  CPT(Geom) geom = geoms.get_geom(i);
518  if (geom->is_empty()) {
519  continue;
520  }
521 
522  CPT(RenderState) state = data._state->compose(geoms.get_geom_state(i));
523  if (state->has_cull_callback() && !state->cull_callback(trav, data)) {
524  // Cull.
525  continue;
526  }
527 
528  // Cull the Geom bounding volume against the view frustum andor the cull
529  // planes. Don't bother unless we've got more than one Geom, since
530  // otherwise the bounding volume of the GeomNode is (probably) the same as
531  // that of the one Geom, and we've already culled against that.
532  if (num_geoms > 1) {
533  if (data._view_frustum != nullptr) {
534  // Cull the individual Geom against the view frustum.
535  CPT(BoundingVolume) geom_volume = geom->get_bounds();
536  const GeometricBoundingVolume *geom_gbv =
537  DCAST(GeometricBoundingVolume, geom_volume);
538 
539  int result = data._view_frustum->contains(geom_gbv);
540  if (result == BoundingVolume::IF_no_intersection) {
541  // Cull this Geom.
542  continue;
543  }
544  }
545  if (!data._cull_planes->is_empty()) {
546  // Also cull the Geom against the cull planes.
547  CPT(BoundingVolume) geom_volume = geom->get_bounds();
548  const GeometricBoundingVolume *geom_gbv =
549  DCAST(GeometricBoundingVolume, geom_volume);
550  int result;
551  data._cull_planes->do_cull(result, state, geom_gbv);
552  if (result == BoundingVolume::IF_no_intersection) {
553  // Cull.
554  continue;
555  }
556  }
557  }
558 
559  CullableObject *object =
560  new CullableObject(std::move(geom), std::move(state), internal_transform);
561  trav->get_cull_handler()->record_object(object, trav);
562  }
563 }
564 
565 /**
566  * Returns the subset of CollideMask bits that may be set for this particular
567  * type of PandaNode. For most nodes, this is 0; it doesn't make sense to set
568  * a CollideMask for most kinds of nodes.
569  *
570  * For nodes that can be collided with, such as GeomNode and CollisionNode,
571  * this returns all bits on.
572  */
575  return CollideMask::all_on();
576 }
577 
578 /**
579  * Adds a new Geom to the node. The geom is given the indicated state (which
580  * may be RenderState::make_empty(), to completely inherit its state from the
581  * scene graph).
582  */
583 void GeomNode::
584 add_geom(Geom *geom, const RenderState *state) {
585  nassertv(geom != nullptr);
586  nassertv(geom->check_valid());
587  nassertv(state != nullptr);
588 
589  Thread *current_thread = Thread::get_current_thread();
590  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
591  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
592 
593  cdata->modify_geoms()->push_back(GeomEntry(geom, state));
594  }
595  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
596 
597  mark_internal_bounds_stale();
598 }
599 
600 /**
601  * Copies the Geoms (and their associated RenderStates) from the indicated
602  * GeomNode into this one.
603  */
604 void GeomNode::
605 add_geoms_from(const GeomNode *other) {
606  Thread *current_thread = Thread::get_current_thread();
607  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
608  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
609  CDStageReader cdata_other(other->_cycler, pipeline_stage, current_thread);
610 
611  GeomList::const_iterator gi;
612  CPT(GeomList) other_geoms = cdata_other->get_geoms();
613  PT(GeomList) this_geoms = cdata->modify_geoms();
614  for (gi = other_geoms->begin(); gi != other_geoms->end(); ++gi) {
615  const GeomEntry &entry = (*gi);
616  nassertv(entry._geom.get_read_pointer()->check_valid());
617  this_geoms->push_back(entry);
618  }
619  }
620  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
621 
622  mark_internal_bounds_stale();
623 }
624 
625 /**
626  * Replaces the nth Geom of the node with a new pointer. There must already
627  * be a Geom in this slot.
628  *
629  * Note that if this method is called in a downstream stage (for instance,
630  * during cull or draw), then it will propagate the new list of Geoms upstream
631  * all the way to pipeline stage 0, which may step on changes that were made
632  * independently in pipeline stage 0. Use with caution.
633  */
634 void GeomNode::
635 set_geom(int n, Geom *geom) {
636  nassertv(geom != nullptr);
637  nassertv(geom->check_valid());
638 
639  CDWriter cdata(_cycler, true);
640  PT(GeomList) geoms = cdata->modify_geoms();
641  nassertv(n >= 0 && n < (int)geoms->size());
642  (*geoms)[n]._geom = geom;
643 
644  mark_internal_bounds_stale();
645 }
646 
647 /**
648  * Verifies that the each Geom within the GeomNode reference vertices that
649  * actually exist within its GeomVertexData. Returns true if the GeomNode
650  * appears to be valid, false otherwise.
651  */
652 bool GeomNode::
653 check_valid() const {
654  int num_geoms = get_num_geoms();
655  for (int i = 0; i < num_geoms; i++) {
656  const Geom *geom = get_geom(i);
657  if (!geom->check_valid()) {
658  return false;
659  }
660  }
661 
662  return true;
663 }
664 
665 /**
666  * Calls decompose() on each Geom with the GeomNode. This decomposes higher-
667  * order primitive types, like triangle strips, into lower-order types like
668  * indexed triangles. Normally there is no reason to do this, but it can be
669  * useful as an early preprocessing step, to allow a later call to unify() to
670  * proceed more quickly.
671  *
672  * See also SceneGraphReducer::decompose(), which is the normal way this is
673  * called.
674  */
675 void GeomNode::
677  Thread *current_thread = Thread::get_current_thread();
678  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
679  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
680 
681  GeomList::iterator gi;
682  PT(GeomList) geoms = cdata->modify_geoms();
683  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
684  GeomEntry &entry = (*gi);
685  nassertv(entry._geom.test_ref_count_integrity());
686  PT(Geom) geom = entry._geom.get_write_pointer();
687  geom->decompose_in_place();
688  }
689  }
690  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
691 }
692 
693 /**
694  * Attempts to unify all of the Geoms contained within this node into a single
695  * Geom, or at least as few Geoms as possible. In turn, the individual
696  * GeomPrimitives contained within each resulting Geom are also unified. The
697  * goal is to reduce the number of GeomPrimitives within the node as far as
698  * possible. This may result in composite primitives, such as triangle strips
699  * and triangle fans, being decomposed into triangles. See also
700  * Geom::unify().
701  *
702  * max_indices represents the maximum number of indices that will be put in
703  * any one GeomPrimitive. If preserve_order is true, then the primitives will
704  * not be reordered during the operation, even if this results in a suboptimal
705  * result.
706  *
707  * In order for this to be successful, the primitives must reference the same
708  * GeomVertexData, have the same fundamental primitive type, and have
709  * compatible shade models.
710  */
711 void GeomNode::
712 unify(int max_indices, bool preserve_order) {
713  bool any_changed = false;
714 
715  Thread *current_thread = Thread::get_current_thread();
716  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
717  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
718 
719  PT(GeomList) new_geoms = new GeomList;
720 
721  // Try to unify each Geom with each preceding Geom. This is an n^2
722  // operation, but usually there are only a handful of Geoms to consider,
723  // so that's not a big deal.
724  GeomList::const_iterator gi;
725  CPT(GeomList) old_geoms = cdata->get_geoms();
726  for (gi = old_geoms->begin(); gi != old_geoms->end(); ++gi) {
727  const GeomEntry &old_entry = (*gi);
728 
729  bool unified = false;
730 
731  // Go from back to front, to minimize damage to the primitive ordering.
732  GeomList::reverse_iterator gj;
733  for (gj = new_geoms->rbegin(); gj != new_geoms->rend() && !unified; ++gj) {
734  GeomEntry &new_entry = (*gj);
735  if (old_entry._state == new_entry._state) {
736  // Both states match, so try to combine the primitives.
737  CPT(Geom) old_geom = old_entry._geom.get_read_pointer();
738  PT(Geom) new_geom = new_entry._geom.get_write_pointer();
739  if (new_geom->copy_primitives_from(old_geom)) {
740  // Successfully combined!
741  unified = true;
742  any_changed = true;
743  }
744  }
745 
746  if (preserve_order) {
747  // If we're insisting on preserving the order, we can only attempt
748  // to merge with the tail of the list.
749  break;
750  }
751  }
752 
753  if (!unified) {
754  // Couldn't unify this Geom with anything, so just add it to the
755  // output list.
756  new_geoms->push_back(old_entry);
757  }
758  }
759 
760  // Done! We'll keep whatever's left in the output list.
761  cdata->set_geoms(new_geoms);
762 
763  // Finally, go back through and unify the resulting geom(s).
764  GeomList::iterator wgi;
765  for (wgi = new_geoms->begin(); wgi != new_geoms->end(); ++wgi) {
766  GeomEntry &entry = (*wgi);
767  nassertv(entry._geom.test_ref_count_integrity());
768  PT(Geom) geom = entry._geom.get_write_pointer();
769  geom->unify_in_place(max_indices, preserve_order);
770  }
771  }
772  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
773 
774  if (any_changed) {
775  mark_internal_bounds_stale();
776  }
777 }
778 
779 /**
780  * Writes a short description of all the Geoms in the node.
781  */
782 void GeomNode::
783 write_geoms(std::ostream &out, int indent_level) const {
784  CDReader cdata(_cycler);
785  write(out, indent_level);
786  GeomList::const_iterator gi;
787  CPT(GeomList) geoms = cdata->get_geoms();
788  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
789  const GeomEntry &entry = (*gi);
790  indent(out, indent_level + 2)
791  << *entry._geom.get_read_pointer() << " " << *entry._state << "\n";
792  }
793 }
794 
795 /**
796  * Writes a detailed description of all the Geoms in the node.
797  */
798 void GeomNode::
799 write_verbose(std::ostream &out, int indent_level) const {
800  CDReader cdata(_cycler);
801  write(out, indent_level);
802  GeomList::const_iterator gi;
803  CPT(GeomList) geoms = cdata->get_geoms();
804  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
805  const GeomEntry &entry = (*gi);
806  CPT(Geom) geom = entry._geom.get_read_pointer();
807  indent(out, indent_level + 2)
808  << *geom << " " << *entry._state << "\n";
809  geom->write(out, indent_level + 4);
810  }
811 }
812 
813 /**
814  *
815  */
816 void GeomNode::
817 output(std::ostream &out) const {
818  // Accumulate the total set of RenderAttrib types that are applied to any of
819  // our Geoms, so we can output them too. The result will be the list of
820  // attrib types that might be applied to some Geoms, but not necessarily to
821  // all Geoms.
822 
823  CDReader cdata(_cycler);
824 
825  pset<TypeHandle> attrib_types;
826 
827  GeomList::const_iterator gi;
828  CPT(RenderState) common = RenderState::make_empty();
829 
830  CPT(GeomList) geoms = cdata->get_geoms();
831  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
832  const GeomEntry &entry = (*gi);
833  common = common->compose(entry._state);
834  }
835 
836  PandaNode::output(out);
837  out << " (" << geoms->size() << " geoms";
838 
839  if (!common->is_empty()) {
840  out << ": " << *common;
841  }
842 
843  out << ")";
844 }
845 
846 /**
847  * A simple downcast check. Returns true if this kind of node happens to
848  * inherit from GeomNode, false otherwise.
849  *
850  * This is provided as a a faster alternative to calling
851  * is_of_type(GeomNode::get_class_type()), since this test is so important to
852  * rendering.
853  */
854 bool GeomNode::
855 is_geom_node() const {
856  return true;
857 }
858 
859 /**
860  * Uses the indicated GSG to premunge the Geoms in this node to optimize them
861  * for eventual rendering. See SceneGraphReducer::premunge().
862  */
863 void GeomNode::
865  const RenderState *node_state,
866  GeomTransformer &transformer) {
867  Thread *current_thread = Thread::get_current_thread();
868 
869  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
870  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
871 
872  GeomList::iterator gi;
873  PT(GeomList) geoms = cdata->modify_geoms();
874  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
875  GeomEntry &entry = (*gi);
876  CPT(RenderState) geom_state = node_state->compose(entry._state);
877  CPT(Geom) geom = entry._geom.get_read_pointer();
878  PT(GeomMunger) munger = gsg->get_geom_munger(geom_state, current_thread);
879  entry._geom = transformer.premunge_geom(geom, munger);
880  }
881  }
882  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
883 }
884 
885 /**
886  * Recursively calls Geom::mark_bounds_stale() on every Geom at this node and
887  * below.
888  */
889 void GeomNode::
890 r_mark_geom_bounds_stale(Thread *current_thread) {
891  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
892  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
893 
894  GeomList::iterator gi;
895  PT(GeomList) geoms = cdata->modify_geoms();
896  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
897  GeomEntry &entry = (*gi);
898  entry._geom.get_read_pointer()->mark_bounds_stale();
899  }
900  }
901  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
902  mark_internal_bounds_stale();
903 
904  PandaNode::r_mark_geom_bounds_stale(current_thread);
905 }
906 
907 /**
908  * Returns a newly-allocated BoundingVolume that represents the internal
909  * contents of the node. Should be overridden by PandaNode classes that
910  * contain something internally.
911  */
912 void GeomNode::
913 compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
914  int &internal_vertices,
915  int pipeline_stage,
916  Thread *current_thread) const {
917  int num_vertices = 0;
918 
919  CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
920 
921  pvector<const BoundingVolume *> child_volumes;
922  pvector<CPT(BoundingVolume) > child_volumes_ref;
923  bool all_box = true;
924 
925  GeomList::const_iterator gi;
926  CPT(GeomList) geoms = cdata->get_geoms();
927  child_volumes.reserve(geoms->size());
928  child_volumes_ref.reserve(geoms->size());
929 
930  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
931  const GeomEntry &entry = (*gi);
932  CPT(Geom) geom = entry._geom.get_read_pointer();
933  CPT(BoundingVolume) volume = geom->get_bounds();
934 
935  if (!volume->is_empty()) {
936  child_volumes.push_back(volume);
937  child_volumes_ref.push_back(volume);
938  if (!volume->is_exact_type(BoundingBox::get_class_type())) {
939  all_box = false;
940  }
941  }
942  num_vertices += geom->get_nested_vertices();
943  }
944 
945  PT(GeometricBoundingVolume) gbv;
946 
947  BoundingVolume::BoundsType btype = get_bounds_type();
948  if (btype == BoundingVolume::BT_default) {
949  btype = bounds_type;
950  }
951 
952  if (btype == BoundingVolume::BT_box ||
953  (btype != BoundingVolume::BT_sphere && all_box)) {
954  // If all of the child volumes are a BoundingBox, then our volume is also
955  // a BoundingBox.
956  gbv = new BoundingBox;
957  } else {
958  // Otherwise, it's a sphere.
959  gbv = new BoundingSphere;
960  }
961 
962  if (child_volumes.size() > 0) {
963  const BoundingVolume **child_begin = &child_volumes[0];
964  const BoundingVolume **child_end = child_begin + child_volumes.size();
965  ((BoundingVolume *)gbv)->around(child_begin, child_end);
966  }
967 
968  internal_bounds = gbv;
969  internal_vertices = num_vertices;
970 }
971 
972 /**
973  * Tells the BamReader how to create objects of type GeomNode.
974  */
975 void GeomNode::
977  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
978 }
979 
980 /**
981  * Writes the contents of this object to the datagram for shipping out to a
982  * Bam file.
983  */
984 void GeomNode::
986  PandaNode::write_datagram(manager, dg);
987  manager->write_cdata(dg, _cycler);
988 }
989 
990 /**
991  * Called by the BamReader to perform any final actions needed for setting up
992  * the object after all objects have been read and all pointers have been
993  * completed.
994  */
995 void GeomNode::
996 finalize(BamReader *manager) {
997  if (manager->get_file_minor_ver() < 14) {
998  // With version 6.14, we changed the default ColorAttrib behavior from
999  // make_vertex() to make_flat(). This means that every Geom that contains
1000  // vertex colors now needs to have an explicit ColorAttrib::make_vertex()
1001  // on its state.
1002 
1003  // Since we shouldn't override a different ColorAttrib inherited from
1004  // above, we create this new attrib with an override of -1.
1005 
1006  CPT(InternalName) color = InternalName::get_color();
1007  CPT(RenderAttrib) vertex_color = ColorAttrib::make_vertex();
1008 
1009  Thread *current_thread = Thread::get_current_thread();
1010  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1011  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1012 
1013  GeomList::iterator gi;
1014  PT(GeomList) geoms = cdata->modify_geoms();
1015  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
1016  GeomEntry &entry = (*gi);
1017  CPT(Geom) geom = entry._geom.get_read_pointer();
1018 
1019  // Force the various GeomVertexArrayFormat objects to finalize
1020  // themselves. We have to do this before we can reliably call
1021  // GeomVertexData::has_column().
1022  CPT(GeomVertexData) vdata = geom->get_vertex_data(current_thread);
1023  CPT(GeomVertexFormat) vformat = vdata->get_format();
1024  for (size_t i = 0; i < vformat->get_num_arrays(); ++i) {
1025  const GeomVertexArrayFormat *varray = vformat->get_array(i);
1026  manager->finalize_now((GeomVertexArrayFormat *)varray);
1027  }
1028 
1029  if (vdata->has_column(color) &&
1030  !entry._state->has_attrib(ColorAttrib::get_class_slot())) {
1031  // We'll be reassigning the RenderState. Therefore, save it
1032  // temporarily to increment its reference count.
1033  PT(BamAuxData) aux_data = new BamAuxData;
1034  aux_data->_hold_state = entry._state;
1035  manager->set_aux_data((RenderState *)entry._state.p(), "hold_state", aux_data);
1036 
1037  entry._state = entry._state->add_attrib(vertex_color, -1);
1038  }
1039  }
1040  }
1041  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1042  }
1043 }
1044 
1045 /**
1046  * This function is called by the BamReader's factory when a new object of
1047  * type GeomNode is encountered in the Bam file. It should create the
1048  * GeomNode and extract its information from the file.
1049  */
1050 TypedWritable *GeomNode::
1051 make_from_bam(const FactoryParams &params) {
1052  GeomNode *node = new GeomNode("");
1053  DatagramIterator scan;
1054  BamReader *manager;
1055 
1056  parse_params(params, scan, manager);
1057  node->fillin(scan, manager);
1058 
1059  if (manager->get_file_minor_ver() < 14) {
1060  manager->register_finalize(node);
1061  }
1062 
1063  return node;
1064 }
1065 
1066 /**
1067  * This internal function is called by make_from_bam to read in all of the
1068  * relevant data from the BamFile for the new GeomNode.
1069  */
1070 void GeomNode::
1071 fillin(DatagramIterator &scan, BamReader *manager) {
1072  PandaNode::fillin(scan, manager);
1073  manager->read_cdata(scan, _cycler);
1074 }
1075 
1076 /**
1077  *
1078  */
1079 GeomNode::CData::
1080 CData(const GeomNode::CData &copy) :
1081  _geoms(copy._geoms)
1082 {
1083 }
1084 
1085 /**
1086  *
1087  */
1088 CycleData *GeomNode::CData::
1089 make_copy() const {
1090  return new CData(*this);
1091 }
1092 
1093 /**
1094  * Writes the contents of this object to the datagram for shipping out to a
1095  * Bam file.
1096  */
1097 void GeomNode::CData::
1098 write_datagram(BamWriter *manager, Datagram &dg) const {
1099  CPT(GeomList) geoms = _geoms.get_read_pointer();
1100  int num_geoms = geoms->size();
1101  nassertv(num_geoms == (int)(uint16_t)num_geoms);
1102  dg.add_uint16(num_geoms);
1103 
1104  GeomList::const_iterator gi;
1105  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
1106  const GeomEntry &entry = (*gi);
1107  manager->write_pointer(dg, entry._geom.get_read_pointer());
1108  manager->write_pointer(dg, entry._state);
1109  }
1110 }
1111 
1112 /**
1113  * Receives an array of pointers, one for each time manager->read_pointer()
1114  * was called in fillin(). Returns the number of pointers processed.
1115  */
1116 int GeomNode::CData::
1117 complete_pointers(TypedWritable **p_list, BamReader *manager) {
1118  int pi = CycleData::complete_pointers(p_list, manager);
1119 
1120  // Get the geom and state pointers.
1121  GeomList::iterator gi;
1122  PT(GeomList) geoms = _geoms.get_write_pointer();
1123  for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
1124  GeomEntry &entry = (*gi);
1125  entry._geom = DCAST(Geom, p_list[pi++]);
1126  entry._state = DCAST(RenderState, p_list[pi++]);
1127  }
1128 
1129  return pi;
1130 }
1131 
1132 /**
1133  * This internal function is called by make_from_bam to read in all of the
1134  * relevant data from the BamFile for the new GeomNode.
1135  */
1136 void GeomNode::CData::
1137 fillin(DatagramIterator &scan, BamReader *manager) {
1138  int num_geoms = scan.get_uint16();
1139  // Read the list of geoms and states. Push back a NULL for each one.
1140  PT(GeomList) geoms = new GeomList;
1141  geoms->reserve(num_geoms);
1142  for (int i = 0; i < num_geoms; i++) {
1143  manager->read_pointer(scan);
1144  manager->read_pointer(scan);
1145  geoms->push_back(GeomEntry(nullptr, nullptr));
1146  }
1147  _geoms = geoms;
1148 }
This is just a simple derivative of GeomMunger that adds the ability to munge states.
Definition: stateMunger.h:26
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
void set_geom(int n, Geom *geom)
Replaces the nth Geom of the node with a new pointer.
Definition: geomNode.cxx:635
A basic node of the scene graph or data graph.
Definition: pandaNode.h:64
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
Definition: boundingBox.h:29
CullHandler * get_cull_handler() const
Returns the object that will receive the culled Geoms.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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...
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
Definition: typedObject.I:38
This is our own Panda specialization on the default STL map.
Definition: pmap.h:49
Indicates a coordinate-system transform on vertices.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool set_color(Geom *geom, const LColor &color)
Overrides the color indicated within the Geom with the given replacement color.
This is the base class for a number of render attributes (other than transform) that may be set on sc...
Definition: renderAttrib.h:51
bool transform_vertices(Geom *geom, const LMatrix4 &mat)
Transforms the vertices and the normals in the indicated Geom by the indicated matrix.
virtual bool is_geom_node() const
A simple downcast check.
Definition: geomNode.cxx:855
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...
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:3589
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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 add_geoms_from(const GeomNode *other)
Copies the Geoms (and their associated RenderStates) from the indicated GeomNode into this one.
Definition: geomNode.cxx:605
bool reverse_normals(Geom *geom)
Reverses the lighting normals on the vertex data, if any.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
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:325
void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler)
Reads in the indicated CycleData object.
Definition: bamReader.cxx:695
static BitMask< WType, nbits > all_on()
Returns a BitMask whose bits are all on.
Definition: bitMask.I:32
bool check_valid() const
Verifies that the each Geom within the GeomNode reference vertices that actually exist within its Geo...
Definition: geomNode.cxx:653
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
get_num_on_stages
Returns the number of stages that are turned on by the attribute.
Definition: textureAttrib.h:55
void collect(PandaNode *node, int attrib_types)
Collects the state and transform from the indicated node and adds it to the accumulator,...
Thread * get_current_thread() const
Returns the currently-executing thread object, as passed to the CullTraverser constructor.
Definition: cullTraverser.I:27
This is a convenience class to specialize ConfigVariable as a boolean type.
get_on_stage
Returns the nth stage turned on by the attribute, sorted in render order.
Definition: textureAttrib.h:55
This defines a bounding sphere, consisting of a center and a radius.
Objects of this class are used to convert vertex data from a Geom into a format suitable for passing ...
Definition: geomMunger.h:50
This class is similar to CycleDataWriter, except it allows writing to a particular stage of the pipel...
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:996
virtual bool is_renderable() const
Returns true if there is some value to visiting this particular node during the cull traversal for an...
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:47
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
Definition: geomPrimitive.h:56
void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler)
Writes out the indicated CycleData object.
Definition: bamWriter.cxx:425
virtual PandaNode * make_copy() const
Returns a newly-allocated PandaNode that is a shallow copy of this one.
Definition: geomNode.cxx:87
Definition: shader.h:49
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 collects together the pieces of data that are accumulated for each node while walking the scene ...
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...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void decompose()
Calls decompose() on each Geom with the GeomNode.
Definition: geomNode.cxx:676
int get_num_geoms() const
Returns the number of geoms of the node.
Definition: geomNode.I:279
A table of objects that are saved within the graphics context for reference by handle later.
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
Definition: bamReader.I:83
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:2442
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
Definition: textureAttrib.h:31
Indicates which faces should be culled based on their vertex ordering.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
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
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
Definition: datagram.I:85
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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:864
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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:574
The smallest atom of cull.
void write_verbose(std::ostream &out, int indent_level) const
Writes a detailed description of all the Geoms in the node.
Definition: geomNode.cxx:799
This class is used by the SceneGraphReducer to maintain and accumulate the set of attributes we have ...
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
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
void write_geoms(std::ostream &out, int indent_level) const
Writes a short description of all the Geoms in the node.
Definition: geomNode.cxx:783
get_bounds_type
Returns the bounding volume type set with set_bounds_type().
Definition: pandaNode.h:293
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A container for geometry primitives.
Definition: geom.h:54
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
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 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
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:985
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
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool remove_column(Geom *geom, const InternalName *column)
Removes the named column from the vertex data in the Geom.
void finalize_now(TypedWritable *whom)
Forces the finalization of a particular object.
Definition: bamReader.cxx:897
Encodes a string name in a hash table, mapping it to a pointer.
Definition: internalName.h:38
Applies a scale to colors in the scene graph and on vertices.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
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_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
This class defines the physical layout of the vertex data stored within a Geom.
Applies a transform matrix to UV's before they are rendered.
This class is similar to CycleDataReader, except it allows reading from a particular stage of the pip...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool check_valid() const
Verifies that the all of the primitives within the geom reference vertices that actually exist within...
Definition: geom.cxx:1061
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
static void register_with_read_factory()
Tells the BamReader how to create objects of type GeomNode.
Definition: geomNode.cxx:976
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
get_effective_mode
Returns the effective culling mode.
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
get_num_geoms
Returns the number of geoms in the node.
Definition: geomNode.h:71
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A thread; that is, a lightweight process.
Definition: thread.h:46
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
Definition: bamReader.cxx:610
This is similar to RefCountObj, but it implements a CopyOnWriteObject inheritance instead of a Refere...
This describes the structure of a single array within a Geom data.
CPT(TransformState) GeomNode
This is used to support NodePath::calc_tight_bounds().
Definition: geomNode.cxx:461
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:712
Indicates what color should be applied to renderable geometry.
Definition: colorAttrib.h:27
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
This is our own Panda specialization on the default STL set.
Definition: pset.h:49
A class to retrieve the individual data elements previously stored in a Datagram.
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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 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
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
Defines the properties of a named stage of the multitexture pipeline.
Definition: textureStage.h:35
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
get_texcoord_name
See set_texcoord_name.
Definition: textureStage.h:192
A general bitmask class.
Definition: bitMask.h:32
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A node that holds Geom objects, renderable pieces of geometry.
Definition: geomNode.h:34
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void add_geom(Geom *geom, const RenderState *state=RenderState::make_empty())
Adds a new Geom to the node.
Definition: geomNode.cxx:584
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the data for one array of a GeomVertexData structure.
get_on_texture
Returns the texture associated with the indicated stage, or NULL if no texture is associated.
Definition: textureAttrib.h:69
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
An object specifically designed to transform the vertices of a Geom without disturbing indexing or af...
bool transform_colors(Geom *geom, const LVecBase4 &scale)
Transforms the colors in the indicated Geom by the indicated scale.