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