Panda3D
 All Classes Functions Variables Enumerations
geomNode.cxx
00001 // Filename: geomNode.cxx
00002 // Created by:  drose (23eb02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "geomNode.h"
00016 #include "geom.h"
00017 #include "geomTransformer.h"
00018 #include "sceneGraphReducer.h"
00019 #include "accumulatedAttribs.h"
00020 #include "colorAttrib.h"
00021 #include "colorScaleAttrib.h"
00022 #include "texMatrixAttrib.h"
00023 #include "textureAttrib.h"
00024 #include "bamReader.h"
00025 #include "bamWriter.h"
00026 #include "datagram.h"
00027 #include "datagramIterator.h"
00028 #include "indent.h"
00029 #include "pset.h"
00030 #include "config_pgraph.h"
00031 #include "graphicsStateGuardianBase.h"
00032 #include "boundingBox.h"
00033 #include "config_mathutil.h"
00034 
00035 
00036 bool allow_flatten_color = ConfigVariableBool
00037     ("allow-flatten-color", false,
00038      PRC_DESC("allows color to always be flattened to vertices"));
00039 
00040 TypeHandle GeomNode::_type_handle;
00041 
00042 ////////////////////////////////////////////////////////////////////
00043 //     Function: GeomNode::Constructor
00044 //       Access: Published
00045 //  Description:
00046 ////////////////////////////////////////////////////////////////////
00047 GeomNode::
00048 GeomNode(const string &name) :
00049   PandaNode(name)
00050 {
00051   _preserved = preserve_geom_nodes;
00052 
00053   // GeomNodes have a certain set of bits on by default.
00054   set_into_collide_mask(get_default_collide_mask());
00055 }
00056 
00057 ////////////////////////////////////////////////////////////////////
00058 //     Function: GeomNode::Copy Constructor
00059 //       Access: Protected
00060 //  Description:
00061 ////////////////////////////////////////////////////////////////////
00062 GeomNode::
00063 GeomNode(const GeomNode &copy) :
00064   PandaNode(copy),
00065   _preserved(copy._preserved),
00066   _cycler(copy._cycler)
00067 {
00068 }
00069 
00070 ////////////////////////////////////////////////////////////////////
00071 //     Function: GeomNode::Destructor
00072 //       Access: Public, Virtual
00073 //  Description:
00074 ////////////////////////////////////////////////////////////////////
00075 GeomNode::
00076 ~GeomNode() {
00077 }
00078 
00079 ////////////////////////////////////////////////////////////////////
00080 //     Function: GeomNode::make_copy
00081 //       Access: Public, Virtual
00082 //  Description: Returns a newly-allocated PandaNode that is a shallow
00083 //               copy of this one.  It will be a different pointer,
00084 //               but its internal data may or may not be shared with
00085 //               that of the original PandaNode.  No children will be
00086 //               copied.
00087 ////////////////////////////////////////////////////////////////////
00088 PandaNode *GeomNode::
00089 make_copy() const {
00090   return new GeomNode(*this);
00091 }
00092 
00093 ////////////////////////////////////////////////////////////////////
00094 //     Function: GeomNode::apply_attribs_to_vertices
00095 //       Access: Public, Virtual
00096 //  Description: Applies whatever attributes are specified in the
00097 //               AccumulatedAttribs object (and by the attrib_types
00098 //               bitmask) to the vertices on this node, if
00099 //               appropriate.  If this node uses geom arrays like a
00100 //               GeomNode, the supplied GeomTransformer may be used to
00101 //               unify shared arrays across multiple different nodes.
00102 //
00103 //               This is a generalization of xform().
00104 ////////////////////////////////////////////////////////////////////
00105 void GeomNode::
00106 apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
00107                           GeomTransformer &transformer) {
00108   if (pgraph_cat.is_debug()) {
00109     pgraph_cat.debug()
00110       << "Transforming geometry:\n";
00111     attribs.write(pgraph_cat.debug(false), attrib_types, 2);
00112   }
00113 
00114   if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
00115     if (!attribs._transform->is_identity()) {
00116       transformer.transform_vertices(this, attribs._transform->get_mat());
00117     }
00118   }
00119 
00120   Thread *current_thread = Thread::get_current_thread();
00121   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
00122     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00123     GeomList::iterator gi;
00124     PT(GeomList) geoms = cdata->modify_geoms();
00125 
00126     // Iterate based on the number of geoms, not using STL iterators.
00127     // This allows us to append to the list in the code below (which
00128     // we might do when doublesiding polys) without visiting those new
00129     // nodes during the traversal.
00130     size_t num_geoms = geoms->size();
00131     for (size_t i = 0; i < num_geoms; ++i) {
00132       GeomEntry *entry = &(*geoms)[i];
00133       PT(Geom) new_geom = entry->_geom.get_read_pointer()->make_copy();
00134 
00135       AccumulatedAttribs geom_attribs = attribs;
00136       entry->_state = geom_attribs.collect(entry->_state, attrib_types);
00137       
00138       bool any_changed = false;
00139 
00140       if ((attrib_types & SceneGraphReducer::TT_color) != 0) {
00141         CPT(RenderAttrib) ra = geom_attribs._color;
00142         if (ra != (const RenderAttrib *)NULL) {
00143           int override = geom_attribs._color_override;
00144           entry->_state = entry->_state->add_attrib(ra, override);
00145         }
00146 
00147         ra = entry->_state->get_attrib_def(ColorAttrib::get_class_slot());
00148         CPT (ColorAttrib) ca = DCAST(ColorAttrib, ra);          
00149         if (ca->get_color_type() != ColorAttrib::T_vertex) {
00150           if(allow_flatten_color) { 
00151               if(transformer.set_color(new_geom, ca->get_color())) {
00152                 any_changed = true;
00153                 entry->_state = entry->_state->set_attrib(ColorAttrib::make_vertex());
00154               }
00155           } else {
00156             if (transformer.remove_column(new_geom, InternalName::get_color())) {
00157               any_changed = true;
00158             }
00159           }            
00160         }
00161       }      
00162       if ((attrib_types & SceneGraphReducer::TT_color_scale) != 0) {
00163         if (geom_attribs._color_scale != (const RenderAttrib *)NULL) {
00164           CPT(ColorScaleAttrib) csa = DCAST(ColorScaleAttrib, geom_attribs._color_scale);
00165           if (csa->get_scale() != LVecBase4(1.0f, 1.0f, 1.0f, 1.0f)) {
00166 
00167             
00168             // Now, if we have an "off" or "flat" color attribute, we
00169             // simply modify the color attribute, and leave the
00170             // vertices alone.
00171             CPT(RenderAttrib) ra = entry->_state->get_attrib_def(ColorAttrib::get_class_slot());
00172             CPT(ColorAttrib) ca = DCAST(ColorAttrib, ra);
00173             if(allow_flatten_color) {
00174               if (transformer.transform_colors(new_geom, csa->get_scale())) {
00175                 any_changed = true;
00176               }
00177             } else {
00178               if (ca->get_color_type() == ColorAttrib::T_off) {
00179                 entry->_state = entry->_state->set_attrib(ColorAttrib::make_vertex());
00180                 // ColorAttrib::T_off means the color scale becomes
00181                 // the new color.
00182                 entry->_state = entry->_state->set_attrib(ColorAttrib::make_flat(csa->get_scale()));
00183               
00184               } else if (ca->get_color_type() == ColorAttrib::T_flat) {
00185                 // ColorAttrib::T_flat means the color scale modulates
00186                 // the specified color to produce a new color.
00187                 const LColor &c1 = ca->get_color();
00188                 const LVecBase4 &c2 = csa->get_scale();
00189                 LColor color(c1[0] * c2[0], c1[1] * c2[1], 
00190                              c1[2] * c2[2], c1[3] * c2[3]);
00191                 entry->_state = entry->_state->set_attrib(ColorAttrib::make_flat(color));
00192               
00193               } else {
00194                 // Otherwise, we have vertex color, and we just scale
00195                 // it normally.
00196                 if (transformer.transform_colors(new_geom, csa->get_scale())) {
00197                   any_changed = true;
00198                 }
00199                 entry->_state = entry->_state->set_attrib(ColorAttrib::make_vertex());
00200               }
00201             }
00202           }
00203         }
00204       }
00205 
00206       if ((attrib_types & SceneGraphReducer::TT_tex_matrix) != 0) {
00207         if (geom_attribs._tex_matrix != (const RenderAttrib *)NULL) {
00208           // Determine which texture coordinate names are used more than
00209           // once.  This assumes we have discovered all of the textures
00210           // that are in effect on the GeomNode; this may not be true if
00211           // there is a texture that has been applied at a node above
00212           // that from which we started the flatten operation, but
00213           // caveat programmer.
00214           NameCount name_count;
00215           
00216           if (geom_attribs._texture != (RenderAttrib *)NULL) {
00217             const TextureAttrib *ta = DCAST(TextureAttrib, geom_attribs._texture);
00218             int num_on_stages = ta->get_num_on_stages();
00219             for (int si = 0; si < num_on_stages; si++) {
00220               TextureStage *stage = ta->get_on_stage(si);
00221               const InternalName *name = stage->get_texcoord_name();
00222               count_name(name_count, name);
00223             }
00224           }
00225           
00226           const TexMatrixAttrib *tma = 
00227             DCAST(TexMatrixAttrib, geom_attribs._tex_matrix);
00228           
00229           CPT(TexMatrixAttrib) new_tma = DCAST(TexMatrixAttrib, TexMatrixAttrib::make());
00230           
00231           int num_stages = tma->get_num_stages();
00232           for (int i = 0; i < num_stages; i++) {
00233             TextureStage *stage = tma->get_stage(i);
00234             InternalName *name = stage->get_texcoord_name();
00235             if (get_name_count(name_count, name) > 1) {
00236               // We can't transform these texcoords, since the name is
00237               // used by more than one active stage.
00238               new_tma = DCAST(TexMatrixAttrib, new_tma->add_stage(stage, tma->get_transform(stage)));
00239               
00240             } else {
00241               // It's safe to transform these texcoords; the name is
00242               // used by no more than one active stage.
00243               if (transformer.transform_texcoords(new_geom, name, name, tma->get_mat(stage))) {
00244                 any_changed = true;
00245               }
00246             }
00247           }
00248           
00249           if (!new_tma->is_empty()) {
00250             entry->_state = entry->_state->add_attrib(new_tma);
00251           }
00252         }
00253       }
00254 
00255       if ((attrib_types & SceneGraphReducer::TT_other) != 0) {
00256         entry->_state = geom_attribs._other->compose(entry->_state);
00257       }
00258 
00259       // We handle cull_face last, since that might involve
00260       // duplicating the geom, and we'd also like to duplicate all of
00261       // the changes we may have applied in the above.
00262 
00263       if ((attrib_types & SceneGraphReducer::TT_cull_face) != 0) {
00264         if (geom_attribs._cull_face != (const RenderAttrib *)NULL) {
00265           const CullFaceAttrib *cfa = DCAST(CullFaceAttrib, geom_attribs._cull_face);
00266           CullFaceAttrib::Mode mode = cfa->get_effective_mode();
00267           switch (mode) {
00268           case CullFaceAttrib::M_cull_none:
00269             // Doublesided polys.  Duplicate them.
00270             {
00271               bool has_normals = (new_geom->get_vertex_data()->has_column(InternalName::get_normal()));
00272               if (has_normals) {
00273                 // If the geometry has normals, we have to duplicate
00274                 // it to reverse the normals on the duplicate copy.
00275                 PT(Geom) dup_geom = new_geom->reverse();
00276                 transformer.reverse_normals(dup_geom);
00277 
00278                 geoms->push_back(GeomEntry(dup_geom, entry->_state));
00279 
00280                 // The above push_back() operation might have
00281                 // invalidated our old pointer into the list, so we
00282                 // reassign it now.
00283                 entry = &(*geoms)[i];
00284                 
00285               } else {
00286                 // If there are no normals, we can just doubleside it in
00287                 // place.  This is preferable because we can share vertices.
00288                 new_geom->doubleside_in_place();
00289                 any_changed = true;
00290               }
00291             }
00292             break;
00293         
00294           case CullFaceAttrib::M_cull_counter_clockwise:
00295             // Reverse winding order.
00296             new_geom->reverse_in_place();
00297             transformer.reverse_normals(new_geom);
00298             any_changed = true;
00299             break;
00300             
00301           default:
00302             break;
00303           }
00304         }
00305       }
00306 
00307       if (any_changed) {
00308         entry->_geom = new_geom;
00309       }
00310     }
00311   }
00312   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
00313 
00314   if ((attrib_types & SceneGraphReducer::TT_apply_texture_color) != 0) {
00315     transformer.apply_texture_colors(this, attribs._other);
00316   }
00317 
00318   transformer.register_vertices(this, false);
00319 }
00320 
00321 ////////////////////////////////////////////////////////////////////
00322 //     Function: GeomNode::xform
00323 //       Access: Public, Virtual
00324 //  Description: Transforms the contents of this node by the indicated
00325 //               matrix, if it means anything to do so.  For most
00326 //               kinds of nodes, this does nothing.
00327 //
00328 //               For a GeomNode, this does the right thing, but it is
00329 //               better to use a GeomTransformer instead, since it
00330 //               will share the new arrays properly between different
00331 //               GeomNodes.
00332 ////////////////////////////////////////////////////////////////////
00333 void GeomNode::
00334 xform(const LMatrix4 &mat) {
00335   GeomTransformer transformer;
00336   transformer.transform_vertices(this, mat);
00337 }
00338 
00339 
00340 ////////////////////////////////////////////////////////////////////
00341 //     Function: GeomNode::safe_to_flatten
00342 //       Access: Public, Virtual
00343 //  Description: Returns true if it is generally safe to flatten out
00344 //               this particular kind of PandaNode by duplicating
00345 //               instances (by calling dupe_for_flatten()), false
00346 //               otherwise (for instance, a Camera cannot be safely
00347 //               flattened, because the Camera pointer itself is
00348 //               meaningful).
00349 ////////////////////////////////////////////////////////////////////
00350 bool GeomNode::
00351 safe_to_flatten() const {
00352   if (_preserved) {
00353     return false;
00354   }
00355 
00356   return true;
00357 }
00358 
00359 ////////////////////////////////////////////////////////////////////
00360 //     Function: GeomNode::safe_to_combine
00361 //       Access: Public, Virtual
00362 //  Description: Returns true if it is generally safe to combine this
00363 //               particular kind of PandaNode with other kinds of
00364 //               PandaNodes of compatible type, adding children or
00365 //               whatever.  For instance, an LODNode should not be
00366 //               combined with any other PandaNode, because its set of
00367 //               children is meaningful.
00368 ////////////////////////////////////////////////////////////////////
00369 bool GeomNode::
00370 safe_to_combine() const {
00371   if (_preserved) {
00372     return false;
00373   }
00374 
00375   return true;
00376 }
00377 
00378 ////////////////////////////////////////////////////////////////////
00379 //     Function: GeomNode::r_prepare_scene
00380 //       Access: Protected, Virtual
00381 //  Description: The recursive implementation of prepare_scene().
00382 //               Don't call this directly; call
00383 //               PandaNode::prepare_scene() or
00384 //               NodePath::prepare_scene() instead.
00385 ////////////////////////////////////////////////////////////////////
00386 void GeomNode::
00387 r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state,
00388                 GeomTransformer &transformer, Thread *current_thread) {
00389   PreparedGraphicsObjects *prepared_objects = gsg->get_prepared_objects();
00390 
00391   CDReader cdata(_cycler, current_thread);
00392   GeomList::const_iterator gi;
00393   CPT(GeomList) geoms = cdata->get_geoms();
00394   for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00395     const GeomEntry &entry = (*gi);
00396     CPT(RenderState) geom_state = node_state->compose(entry._state);
00397     CPT(Geom) geom = entry._geom.get_read_pointer();
00398 
00399     // Munge the geom as required by the GSG.
00400     PT(GeomMunger) munger = gsg->get_geom_munger(geom_state, current_thread);
00401     geom = transformer.premunge_geom(geom, munger);
00402 
00403     // Prepare each of the vertex arrays in the munged Geom.
00404     CPT(GeomVertexData) vdata = geom->get_vertex_data(current_thread);
00405     vdata = vdata->animate_vertices(false, current_thread);
00406     GeomVertexDataPipelineReader vdata_reader(vdata, current_thread);
00407     int num_arrays = vdata_reader.get_num_arrays();
00408     for (int i = 0; i < num_arrays; ++i) {
00409       CPT(GeomVertexArrayData) array = vdata_reader.get_array(i);
00410       ((GeomVertexArrayData *)array.p())->prepare(prepared_objects);
00411     }
00412 
00413     // And also each of the index arrays.
00414     int num_primitives = geom->get_num_primitives();
00415     for (int i = 0; i < num_primitives; ++i) {
00416       CPT(GeomPrimitive) prim = geom->get_primitive(i);
00417       ((GeomPrimitive *)prim.p())->prepare(prepared_objects);
00418     }
00419 
00420     // And now prepare each of the textures.
00421     const RenderAttrib *attrib = 
00422       geom_state->get_attrib(TextureAttrib::get_class_slot());
00423     if (attrib != (const RenderAttrib *)NULL) {
00424       const TextureAttrib *ta;
00425       DCAST_INTO_V(ta, attrib);
00426       int num_stages = ta->get_num_on_stages();
00427       for (int i = 0; i < num_stages; ++i) {
00428         Texture *texture = ta->get_on_texture(ta->get_on_stage(i));
00429         if (texture != (Texture *)NULL) {
00430           texture->prepare(prepared_objects);
00431         }
00432       }
00433     }
00434   }
00435   
00436   PandaNode::r_prepare_scene(gsg, node_state, transformer, current_thread);
00437 }
00438 
00439 
00440 ////////////////////////////////////////////////////////////////////
00441 //     Function: GeomNode::combine_with
00442 //       Access: Public, Virtual
00443 //  Description: Collapses this node with the other node, if possible,
00444 //               and returns a pointer to the combined node, or NULL
00445 //               if the two nodes cannot safely be combined.
00446 //
00447 //               The return value may be this, other, or a new node
00448 //               altogether.
00449 //
00450 //               This function is called from GraphReducer::flatten(),
00451 //               and need not deal with children; its job is just to
00452 //               decide whether to collapse the two nodes and what the
00453 //               collapsed node should look like.
00454 ////////////////////////////////////////////////////////////////////
00455 PandaNode *GeomNode::
00456 combine_with(PandaNode *other) {
00457   if (is_exact_type(get_class_type()) &&
00458       other->is_exact_type(get_class_type())) {
00459     // Two GeomNodes can combine by moving Geoms from one to the other.
00460     GeomNode *gother = DCAST(GeomNode, other);
00461     add_geoms_from(gother);
00462     return this;
00463   }
00464 
00465   return PandaNode::combine_with(other);
00466 }
00467 
00468 ////////////////////////////////////////////////////////////////////
00469 //     Function: GeomNode::calc_tight_bounds
00470 //       Access: Public, Virtual
00471 //  Description: This is used to support
00472 //               NodePath::calc_tight_bounds().  It is not intended to
00473 //               be called directly, and it has nothing to do with the
00474 //               normal Panda bounding-volume computation.
00475 //
00476 //               If the node contains any geometry, this updates
00477 //               min_point and max_point to enclose its bounding box.
00478 //               found_any is to be set true if the node has any
00479 //               geometry at all, or left alone if it has none.  This
00480 //               method may be called over several nodes, so it may
00481 //               enter with min_point, max_point, and found_any
00482 //               already set.
00483 ////////////////////////////////////////////////////////////////////
00484 CPT(TransformState) GeomNode::
00485 calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, bool &found_any,
00486                   const TransformState *transform, Thread *current_thread) const {
00487   CPT(TransformState) next_transform = 
00488     PandaNode::calc_tight_bounds(min_point, max_point, found_any, transform,
00489                                  current_thread);
00490 
00491   const LMatrix4 &mat = next_transform->get_mat();
00492 
00493   CDReader cdata(_cycler, current_thread);
00494   GeomList::const_iterator gi;
00495   CPT(GeomList) geoms = cdata->get_geoms();
00496   for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00497     CPT(Geom) geom = (*gi)._geom.get_read_pointer();
00498     geom->calc_tight_bounds(min_point, max_point, found_any,
00499                             geom->get_vertex_data(current_thread)->animate_vertices(true, current_thread),
00500                             !next_transform->is_identity(), mat,
00501                             current_thread);
00502   }
00503 
00504   return next_transform;
00505 }
00506 
00507 ////////////////////////////////////////////////////////////////////
00508 //     Function: GeomNode::is_renderable
00509 //       Access: Public, Virtual
00510 //  Description: Returns true if there is some value to visiting this
00511 //               particular node during the cull traversal for any
00512 //               camera, false otherwise.  This will be used to
00513 //               optimize the result of get_net_draw_show_mask(), so
00514 //               that any subtrees that contain only nodes for which
00515 //               is_renderable() is false need not be visited.
00516 ////////////////////////////////////////////////////////////////////
00517 bool GeomNode::
00518 is_renderable() const {
00519   return true;
00520 }
00521 
00522 ////////////////////////////////////////////////////////////////////
00523 //     Function: GeomNode::add_for_draw
00524 //       Access: Public, Virtual
00525 //  Description: Adds the node's contents to the CullResult we are
00526 //               building up during the cull traversal, so that it
00527 //               will be drawn at render time.  For most nodes other
00528 //               than GeomNodes, this is a do-nothing operation.
00529 ////////////////////////////////////////////////////////////////////
00530 void GeomNode::
00531 add_for_draw(CullTraverser *trav, CullTraverserData &data) {
00532   trav->_geom_nodes_pcollector.add_level(1);
00533 
00534   if (pgraph_cat.is_spam()) {
00535     pgraph_cat.spam()
00536       << "Found " << *this << " in state " << *data._state 
00537       << " draw_mask = " << data._draw_mask << "\n";
00538   }
00539   
00540   // Get all the Geoms, with no decalling.
00541   Geoms geoms = get_geoms(trav->get_current_thread());
00542   int num_geoms = geoms.get_num_geoms();
00543   trav->_geoms_pcollector.add_level(num_geoms);
00544   CPT(TransformState) net_transform = data.get_net_transform(trav);
00545   CPT(TransformState) modelview_transform = data.get_modelview_transform(trav);
00546   CPT(TransformState) internal_transform = trav->get_gsg()->get_cs_transform()->compose(modelview_transform);
00547 
00548   for (int i = 0; i < num_geoms; i++) {
00549     const Geom *geom = geoms.get_geom(i);
00550     if (geom->is_empty()) {
00551       continue;
00552     }
00553 
00554     CPT(RenderState) state = data._state->compose(geoms.get_geom_state(i));
00555     if (state->has_cull_callback() && !state->cull_callback(trav, data)) {
00556       // Cull.
00557       continue;
00558     }
00559     
00560     // Cull the Geom bounding volume against the view frustum
00561     // and/or the cull planes.  Don't bother unless we've got more
00562     // than one Geom, since otherwise the bounding volume of the
00563     // GeomNode is (probably) the same as that of the one Geom,
00564     // and we've already culled against that.
00565     if (num_geoms > 1) {
00566       if (data._view_frustum != (GeometricBoundingVolume *)NULL) {
00567         // Cull the individual Geom against the view frustum.
00568         CPT(BoundingVolume) geom_volume = geom->get_bounds();
00569         const GeometricBoundingVolume *geom_gbv =
00570           DCAST(GeometricBoundingVolume, geom_volume);
00571         
00572         int result = data._view_frustum->contains(geom_gbv);
00573         if (result == BoundingVolume::IF_no_intersection) {
00574           // Cull this Geom.
00575           continue;
00576         }
00577       }
00578       if (!data._cull_planes->is_empty()) {
00579         // Also cull the Geom against the cull planes.
00580         CPT(BoundingVolume) geom_volume = geom->get_bounds();
00581         const GeometricBoundingVolume *geom_gbv =
00582           DCAST(GeometricBoundingVolume, geom_volume);
00583         int result;
00584         data._cull_planes->do_cull(result, state, geom_gbv);
00585         if (result == BoundingVolume::IF_no_intersection) {
00586           // Cull.
00587           continue;
00588         }
00589       }
00590     }
00591     
00592     CullableObject *object = 
00593       new CullableObject(geom, state, net_transform, 
00594                          modelview_transform, internal_transform);
00595     trav->get_cull_handler()->record_object(object, trav);
00596   }
00597 }
00598 
00599 ////////////////////////////////////////////////////////////////////
00600 //     Function: GeomNode::get_legal_collide_mask
00601 //       Access: Published, Virtual
00602 //  Description: Returns the subset of CollideMask bits that may be
00603 //               set for this particular type of PandaNode.  For most
00604 //               nodes, this is 0; it doesn't make sense to set a
00605 //               CollideMask for most kinds of nodes.
00606 //
00607 //               For nodes that can be collided with, such as GeomNode
00608 //               and CollisionNode, this returns all bits on.
00609 ////////////////////////////////////////////////////////////////////
00610 CollideMask GeomNode::
00611 get_legal_collide_mask() const {
00612   return CollideMask::all_on();
00613 }
00614 
00615 ////////////////////////////////////////////////////////////////////
00616 //     Function: GeomNode::add_geom
00617 //       Access: Published
00618 //  Description: Adds a new Geom to the node.  The geom is given the
00619 //               indicated state (which may be
00620 //               RenderState::make_empty(), to completely inherit its
00621 //               state from the scene graph).
00622 ////////////////////////////////////////////////////////////////////
00623 void GeomNode::
00624 add_geom(Geom *geom, const RenderState *state) {
00625   nassertv(geom != (Geom *)NULL);
00626   nassertv(geom->check_valid());
00627   nassertv(state != (RenderState *)NULL);
00628 
00629   Thread *current_thread = Thread::get_current_thread();
00630   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
00631     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00632 
00633     cdata->modify_geoms()->push_back(GeomEntry(geom, state));
00634   }
00635   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
00636 
00637   mark_internal_bounds_stale();
00638 }
00639 
00640 ////////////////////////////////////////////////////////////////////
00641 //     Function: GeomNode::add_geoms_from
00642 //       Access: Published
00643 //  Description: Copies the Geoms (and their associated RenderStates)
00644 //               from the indicated GeomNode into this one.
00645 ////////////////////////////////////////////////////////////////////
00646 void GeomNode::
00647 add_geoms_from(const GeomNode *other) {
00648   Thread *current_thread = Thread::get_current_thread();
00649   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
00650     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00651     CDStageReader cdata_other(other->_cycler, pipeline_stage, current_thread);
00652 
00653     GeomList::const_iterator gi;
00654     CPT(GeomList) other_geoms = cdata_other->get_geoms();
00655     PT(GeomList) this_geoms = cdata->modify_geoms();
00656     for (gi = other_geoms->begin(); gi != other_geoms->end(); ++gi) {
00657       const GeomEntry &entry = (*gi);
00658       nassertv(entry._geom.get_read_pointer()->check_valid());
00659       this_geoms->push_back(entry);
00660     }
00661   }
00662   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
00663 
00664   mark_internal_bounds_stale();
00665 }
00666 
00667 ////////////////////////////////////////////////////////////////////
00668 //     Function: GeomNode::set_geom
00669 //       Access: Public
00670 //  Description: Replaces the nth Geom of the node with a new pointer.
00671 //               There must already be a Geom in this slot.
00672 //
00673 //               Note that if this method is called in a downstream
00674 //               stage (for instance, during cull or draw), then it
00675 //               will propagate the new list of Geoms upstream all the
00676 //               way to pipeline stage 0, which may step on changes
00677 //               that were made independently in pipeline stage 0.
00678 //               Use with caution.
00679 ////////////////////////////////////////////////////////////////////
00680 void GeomNode::
00681 set_geom(int n, Geom *geom) {
00682   nassertv(geom != (Geom *)NULL);
00683   nassertv(geom->check_valid());
00684 
00685   CDWriter cdata(_cycler, true);
00686   PT(GeomList) geoms = cdata->modify_geoms();
00687   nassertv(n >= 0 && n < (int)geoms->size());
00688   (*geoms)[n]._geom = geom;
00689 
00690   mark_internal_bounds_stale();
00691 }
00692 
00693 ////////////////////////////////////////////////////////////////////
00694 //     Function: GeomNode::check_valid
00695 //       Access: Published
00696 //  Description: Verifies that the each Geom within the GeomNode
00697 //               reference vertices that actually exist within its
00698 //               GeomVertexData.  Returns true if the GeomNode appears
00699 //               to be valid, false otherwise.
00700 ////////////////////////////////////////////////////////////////////
00701 bool GeomNode::
00702 check_valid() const {
00703   int num_geoms = get_num_geoms();
00704   for (int i = 0; i < num_geoms; i++) {
00705     const Geom *geom = get_geom(i);
00706     if (!geom->check_valid()) {
00707       return false;
00708     }
00709   }
00710 
00711   return true;
00712 }
00713 
00714 ////////////////////////////////////////////////////////////////////
00715 //     Function: GeomNode::decompose
00716 //       Access: Published
00717 //  Description: Calls decompose() on each Geom with the GeomNode.
00718 //               This decomposes higher-order primitive types, like
00719 //               triangle strips, into lower-order types like indexed
00720 //               triangles.  Normally there is no reason to do this,
00721 //               but it can be useful as an early preprocessing step,
00722 //               to allow a later call to unify() to proceed more
00723 //               quickly.
00724 //
00725 //               See also SceneGraphReducer::decompose(), which is the
00726 //               normal way this is called.
00727 ////////////////////////////////////////////////////////////////////
00728 void GeomNode::
00729 decompose() {
00730   Thread *current_thread = Thread::get_current_thread();
00731   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
00732     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00733 
00734     GeomList::iterator gi;
00735     PT(GeomList) geoms = cdata->modify_geoms();
00736     for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00737       GeomEntry &entry = (*gi);
00738       nassertv(entry._geom.test_ref_count_integrity());
00739       PT(Geom) geom = entry._geom.get_write_pointer();
00740       geom->decompose_in_place();
00741     }
00742   }
00743   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
00744 }
00745 
00746 ////////////////////////////////////////////////////////////////////
00747 //     Function: GeomNode::unify
00748 //       Access: Published
00749 //  Description: Attempts to unify all of the Geoms contained within
00750 //               this node into a single Geom, or at least as few
00751 //               Geoms as possible.  In turn, the individual
00752 //               GeomPrimitives contained within each resulting Geom
00753 //               are also unified.  The goal is to reduce the number
00754 //               of GeomPrimitives within the node as far as possible.
00755 //               This may result in composite primitives, such as
00756 //               triangle strips and triangle fans, being decomposed
00757 //               into triangles.  See also Geom::unify().
00758 //
00759 //               max_indices represents the maximum number of indices
00760 //               that will be put in any one GeomPrimitive.  If
00761 //               preserve_order is true, then the primitives will not
00762 //               be reordered during the operation, even if this
00763 //               results in a suboptimal result.
00764 //
00765 //               In order for this to be successful, the primitives
00766 //               must reference the same GeomVertexData, have the same
00767 //               fundamental primitive type, and have compatible shade
00768 //               models.
00769 ////////////////////////////////////////////////////////////////////
00770 void GeomNode::
00771 unify(int max_indices, bool preserve_order) {
00772   bool any_changed = false;
00773 
00774   Thread *current_thread = Thread::get_current_thread();
00775   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
00776     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00777 
00778     PT(GeomList) new_geoms = new GeomList;
00779 
00780     // Try to unify each Geom with each preceding Geom.  This is an n^2
00781     // operation, but usually there are only a handful of Geoms to
00782     // consider, so that's not a big deal.
00783     GeomList::const_iterator gi;
00784     CPT(GeomList) old_geoms = cdata->get_geoms();
00785     for (gi = old_geoms->begin(); gi != old_geoms->end(); ++gi) {
00786       const GeomEntry &old_entry = (*gi);
00787       
00788       bool unified = false;
00789 
00790       // Go from back to front, to minimize damage to the primitive ordering.
00791       GeomList::reverse_iterator gj;
00792       for (gj = new_geoms->rbegin(); gj != new_geoms->rend() && !unified; ++gj) {
00793         GeomEntry &new_entry = (*gj);
00794         if (old_entry._state == new_entry._state) {
00795           // Both states match, so try to combine the primitives.
00796           CPT(Geom) old_geom = old_entry._geom.get_read_pointer();
00797           PT(Geom) new_geom = new_entry._geom.get_write_pointer();
00798           if (new_geom->copy_primitives_from(old_geom)) {
00799             // Successfully combined!
00800             unified = true;
00801             any_changed = true;
00802           }
00803         }
00804 
00805         if (preserve_order) {
00806           // If we're insisting on preserving the order, we can only
00807           // attempt to merge with the tail of the list.
00808           break;
00809         }
00810       }
00811       
00812       if (!unified) {
00813         // Couldn't unify this Geom with anything, so just add it to the
00814         // output list.
00815         new_geoms->push_back(old_entry);
00816       }
00817     }
00818     
00819     // Done!  We'll keep whatever's left in the output list.
00820     cdata->set_geoms(new_geoms);
00821 
00822     // Finally, go back through and unify the resulting geom(s).
00823     GeomList::iterator wgi;
00824     for (wgi = new_geoms->begin(); wgi != new_geoms->end(); ++wgi) {
00825       GeomEntry &entry = (*wgi);
00826       nassertv(entry._geom.test_ref_count_integrity());
00827       PT(Geom) geom = entry._geom.get_write_pointer();
00828       geom->unify_in_place(max_indices, preserve_order);
00829     }
00830   }
00831   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
00832 
00833   if (any_changed) {
00834     mark_internal_bounds_stale();
00835   }
00836 }
00837 
00838 ////////////////////////////////////////////////////////////////////
00839 //     Function: GeomNode::write_geoms
00840 //       Access: Published
00841 //  Description: Writes a short description of all the Geoms in the
00842 //               node.
00843 ////////////////////////////////////////////////////////////////////
00844 void GeomNode::
00845 write_geoms(ostream &out, int indent_level) const {
00846   CDReader cdata(_cycler);
00847   write(out, indent_level);
00848   GeomList::const_iterator gi;
00849   CPT(GeomList) geoms = cdata->get_geoms();
00850   for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00851     const GeomEntry &entry = (*gi);
00852     indent(out, indent_level + 2) 
00853       << *entry._geom.get_read_pointer() << " " << *entry._state << "\n";
00854   }
00855 }
00856 
00857 ////////////////////////////////////////////////////////////////////
00858 //     Function: GeomNode::write_verbose
00859 //       Access: Published
00860 //  Description: Writes a detailed description of all the Geoms in the
00861 //               node.
00862 ////////////////////////////////////////////////////////////////////
00863 void GeomNode::
00864 write_verbose(ostream &out, int indent_level) const {
00865   CDReader cdata(_cycler);
00866   write(out, indent_level);
00867   GeomList::const_iterator gi;
00868   CPT(GeomList) geoms = cdata->get_geoms();
00869   for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00870     const GeomEntry &entry = (*gi);
00871     CPT(Geom) geom = entry._geom.get_read_pointer();
00872     indent(out, indent_level + 2) 
00873       << *geom << " " << *entry._state << "\n";
00874     geom->write(out, indent_level + 4);
00875   }
00876 }
00877 
00878 ////////////////////////////////////////////////////////////////////
00879 //     Function: GeomNode::output
00880 //       Access: Public, Virtual
00881 //  Description: 
00882 ////////////////////////////////////////////////////////////////////
00883 void GeomNode::
00884 output(ostream &out) const {
00885   // Accumulate the total set of RenderAttrib types that are applied
00886   // to any of our Geoms, so we can output them too.  The result will
00887   // be the list of attrib types that might be applied to some Geoms,
00888   // but not necessarily to all Geoms.
00889 
00890   CDReader cdata(_cycler);
00891 
00892   pset<TypeHandle> attrib_types;
00893 
00894   GeomList::const_iterator gi;
00895   CPT(RenderState) common = RenderState::make_empty();
00896 
00897   CPT(GeomList) geoms = cdata->get_geoms();
00898   for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00899     const GeomEntry &entry = (*gi);
00900     common = common->compose(entry._state);
00901   }
00902 
00903   PandaNode::output(out);
00904   out << " (" << geoms->size() << " geoms";
00905 
00906   if (!common->is_empty()) {
00907     out << ": " << *common;    
00908   }
00909 
00910   out << ")";
00911 }
00912 
00913 ////////////////////////////////////////////////////////////////////
00914 //     Function: GeomNode::is_geom_node
00915 //       Access: Public, Virtual
00916 //  Description: A simple downcast check.  Returns true if this kind
00917 //               of node happens to inherit from GeomNode, false
00918 //               otherwise.
00919 //
00920 //               This is provided as a a faster alternative to calling
00921 //               is_of_type(GeomNode::get_class_type()), since this
00922 //               test is so important to rendering.
00923 ////////////////////////////////////////////////////////////////////
00924 bool GeomNode::
00925 is_geom_node() const {
00926   return true;
00927 }
00928 
00929 ////////////////////////////////////////////////////////////////////
00930 //     Function: GeomNode::do_premunge
00931 //       Access: Public
00932 //  Description: Uses the indicated GSG to premunge the Geoms in this
00933 //               node to optimize them for eventual rendering.  See
00934 //               SceneGraphReducer::premunge().
00935 ////////////////////////////////////////////////////////////////////
00936 void GeomNode::
00937 do_premunge(GraphicsStateGuardianBase *gsg,
00938             const RenderState *node_state,
00939             GeomTransformer &transformer) {
00940   Thread *current_thread = Thread::get_current_thread();
00941 
00942   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
00943     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00944 
00945     GeomList::iterator gi;
00946     PT(GeomList) geoms = cdata->modify_geoms();
00947     for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00948       GeomEntry &entry = (*gi);
00949       CPT(RenderState) geom_state = node_state->compose(entry._state);
00950       CPT(Geom) geom = entry._geom.get_read_pointer();
00951       PT(GeomMunger) munger = gsg->get_geom_munger(geom_state, current_thread);
00952       entry._geom = transformer.premunge_geom(geom, munger);
00953     }
00954   }
00955   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
00956 }
00957 
00958 ////////////////////////////////////////////////////////////////////
00959 //     Function: GeomNode::r_mark_geom_bounds_stale
00960 //       Access: Protected, Virtual
00961 //  Description: Recursively calls Geom::mark_bounds_stale() on every
00962 //               Geom at this node and below.
00963 ////////////////////////////////////////////////////////////////////
00964 void GeomNode::
00965 r_mark_geom_bounds_stale(Thread *current_thread) {
00966   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
00967     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00968 
00969     GeomList::iterator gi;
00970     PT(GeomList) geoms = cdata->modify_geoms();
00971     for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00972       GeomEntry &entry = (*gi);
00973       entry._geom.get_read_pointer()->mark_bounds_stale();
00974     }
00975   }
00976   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
00977   mark_internal_bounds_stale();
00978 
00979   PandaNode::r_mark_geom_bounds_stale(current_thread);
00980 }
00981 
00982 ////////////////////////////////////////////////////////////////////
00983 //     Function: GeomNode::compute_internal_bounds
00984 //       Access: Protected, Virtual
00985 //  Description: Returns a newly-allocated BoundingVolume that
00986 //               represents the internal contents of the node.  Should
00987 //               be overridden by PandaNode classes that contain
00988 //               something internally.
00989 ////////////////////////////////////////////////////////////////////
00990 void GeomNode::
00991 compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
00992                         int &internal_vertices,
00993                         int pipeline_stage,
00994                         Thread *current_thread) const {
00995   int num_vertices = 0;
00996 
00997   CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
00998 
00999   pvector<const BoundingVolume *> child_volumes;
01000   pvector<CPT(BoundingVolume) > child_volumes_ref;
01001   bool all_box = true;
01002 
01003   GeomList::const_iterator gi;
01004   CPT(GeomList) geoms = cdata->get_geoms();
01005   child_volumes.reserve(geoms->size());
01006   child_volumes_ref.reserve(geoms->size());
01007 
01008   for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
01009     const GeomEntry &entry = (*gi);
01010     CPT(Geom) geom = entry._geom.get_read_pointer();
01011     CPT(BoundingVolume) volume = geom->get_bounds();
01012 
01013     if (!volume->is_empty()) {
01014       child_volumes.push_back(volume);
01015       child_volumes_ref.push_back(volume);
01016       if (!volume->is_exact_type(BoundingBox::get_class_type())) {
01017         all_box = false;
01018       }
01019     }
01020     num_vertices += geom->get_nested_vertices();
01021   }
01022 
01023   PT(GeometricBoundingVolume) gbv;
01024 
01025   BoundingVolume::BoundsType btype = get_bounds_type();
01026   if (btype == BoundingVolume::BT_default) {
01027     btype = bounds_type;
01028   }
01029 
01030   if (btype == BoundingVolume::BT_box ||
01031       (btype != BoundingVolume::BT_sphere && all_box)) {
01032     // If all of the child volumes are a BoundingBox, then our volume
01033     // is also a BoundingBox.
01034     gbv = new BoundingBox;
01035   } else {
01036     // Otherwise, it's a sphere.
01037     gbv = new BoundingSphere;
01038   }
01039 
01040   if (child_volumes.size() > 0) {
01041     const BoundingVolume **child_begin = &child_volumes[0];
01042     const BoundingVolume **child_end = child_begin + child_volumes.size();
01043     ((BoundingVolume *)gbv)->around(child_begin, child_end);
01044   }
01045   
01046   internal_bounds = gbv;
01047   internal_vertices = num_vertices;
01048 }
01049 
01050 ////////////////////////////////////////////////////////////////////
01051 //     Function: GeomNode::register_with_read_factory
01052 //       Access: Public, Static
01053 //  Description: Tells the BamReader how to create objects of type
01054 //               GeomNode.
01055 ////////////////////////////////////////////////////////////////////
01056 void GeomNode::
01057 register_with_read_factory() {
01058   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
01059 }
01060 
01061 ////////////////////////////////////////////////////////////////////
01062 //     Function: GeomNode::write_datagram
01063 //       Access: Public, Virtual
01064 //  Description: Writes the contents of this object to the datagram
01065 //               for shipping out to a Bam file.
01066 ////////////////////////////////////////////////////////////////////
01067 void GeomNode::
01068 write_datagram(BamWriter *manager, Datagram &dg) {
01069   PandaNode::write_datagram(manager, dg);
01070   manager->write_cdata(dg, _cycler);
01071 }
01072 
01073 ////////////////////////////////////////////////////////////////////
01074 //     Function: GeomNode::finalize
01075 //       Access: Public, Virtual
01076 //  Description: Called by the BamReader to perform any final actions
01077 //               needed for setting up the object after all objects
01078 //               have been read and all pointers have been completed.
01079 ////////////////////////////////////////////////////////////////////
01080 void GeomNode::
01081 finalize(BamReader *manager) {
01082   if (manager->get_file_minor_ver() < 14) {
01083     // With version 6.14, we changed the default ColorAttrib
01084     // behavior from make_vertex() to make_flat().  This means that
01085     // every Geom that contains vertex colors now needs to have an
01086     // explicit ColorAttrib::make_vertex() on its state.
01087 
01088     // Since we shouldn't override a different ColorAttrib inherited
01089     // from above, we create this new attrib with an override of -1.
01090 
01091     CPT(InternalName) color = InternalName::get_color();
01092     CPT(RenderAttrib) vertex_color = ColorAttrib::make_vertex();
01093 
01094     Thread *current_thread = Thread::get_current_thread();
01095     OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01096       CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01097 
01098       GeomList::iterator gi;
01099       PT(GeomList) geoms = cdata->modify_geoms();
01100       for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
01101         GeomEntry &entry = (*gi);
01102         CPT(Geom) geom = entry._geom.get_read_pointer();
01103 
01104         // Force the various GeomVertexArrayFormat objects to finalize
01105         // themselves.  We have to do this before we can reliably call
01106         // GeomVertexData::has_column().
01107         CPT(GeomVertexData) vdata = geom->get_vertex_data(current_thread);
01108         CPT(GeomVertexFormat) vformat = vdata->get_format();
01109         for (int i = 0; i < vformat->get_num_arrays(); ++i) {
01110           const GeomVertexArrayFormat *varray = vformat->get_array(i);
01111           manager->finalize_now((GeomVertexArrayFormat *)varray);
01112         }
01113 
01114         if (vdata->has_column(color) &&
01115             !entry._state->has_attrib(ColorAttrib::get_class_slot())) {
01116           // We'll be reassigning the RenderState.  Therefore, save it
01117           // temporarily to increment its reference count.
01118           PT(BamAuxData) aux_data = new BamAuxData;
01119           aux_data->_hold_state = entry._state;
01120           manager->set_aux_data((RenderState *)entry._state.p(), "hold_state", aux_data);
01121 
01122           entry._state = entry._state->add_attrib(vertex_color, -1);
01123         }
01124       }
01125     }
01126     CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01127   }
01128 }
01129 
01130 ////////////////////////////////////////////////////////////////////
01131 //     Function: GeomNode::make_from_bam
01132 //       Access: Protected, Static
01133 //  Description: This function is called by the BamReader's factory
01134 //               when a new object of type GeomNode is encountered
01135 //               in the Bam file.  It should create the GeomNode
01136 //               and extract its information from the file.
01137 ////////////////////////////////////////////////////////////////////
01138 TypedWritable *GeomNode::
01139 make_from_bam(const FactoryParams &params) {
01140   GeomNode *node = new GeomNode("");
01141   DatagramIterator scan;
01142   BamReader *manager;
01143 
01144   parse_params(params, scan, manager);
01145   node->fillin(scan, manager);
01146 
01147   if (manager->get_file_minor_ver() < 14) {
01148     manager->register_finalize(node);
01149   }
01150 
01151   return node;
01152 }
01153 
01154 ////////////////////////////////////////////////////////////////////
01155 //     Function: GeomNode::fillin
01156 //       Access: Protected
01157 //  Description: This internal function is called by make_from_bam to
01158 //               read in all of the relevant data from the BamFile for
01159 //               the new GeomNode.
01160 ////////////////////////////////////////////////////////////////////
01161 void GeomNode::
01162 fillin(DatagramIterator &scan, BamReader *manager) {
01163   PandaNode::fillin(scan, manager);
01164   manager->read_cdata(scan, _cycler);
01165 }
01166 
01167 ////////////////////////////////////////////////////////////////////
01168 //     Function: GeomNode::CData::Copy Constructor
01169 //       Access: Public
01170 //  Description:
01171 ////////////////////////////////////////////////////////////////////
01172 GeomNode::CData::
01173 CData(const GeomNode::CData &copy) :
01174   _geoms(copy._geoms)
01175 {
01176 }
01177 
01178 ////////////////////////////////////////////////////////////////////
01179 //     Function: GeomNode::CData::make_copy
01180 //       Access: Public, Virtual
01181 //  Description:
01182 ////////////////////////////////////////////////////////////////////
01183 CycleData *GeomNode::CData::
01184 make_copy() const {
01185   return new CData(*this);
01186 }
01187 
01188 ////////////////////////////////////////////////////////////////////
01189 //     Function: GeomNode::CData::write_datagram
01190 //       Access: Public, Virtual
01191 //  Description: Writes the contents of this object to the datagram
01192 //               for shipping out to a Bam file.
01193 ////////////////////////////////////////////////////////////////////
01194 void GeomNode::CData::
01195 write_datagram(BamWriter *manager, Datagram &dg) const {
01196   CPT(GeomList) geoms = _geoms.get_read_pointer();
01197   int num_geoms = geoms->size();
01198   nassertv(num_geoms == (int)(PN_uint16)num_geoms);
01199   dg.add_uint16(num_geoms);
01200   
01201   GeomList::const_iterator gi;
01202   for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
01203     const GeomEntry &entry = (*gi);
01204     manager->write_pointer(dg, entry._geom.get_read_pointer());
01205     manager->write_pointer(dg, entry._state);
01206   }
01207 }
01208 
01209 ////////////////////////////////////////////////////////////////////
01210 //     Function: GeomNode::CData::complete_pointers
01211 //       Access: Public, Virtual
01212 //  Description: Receives an array of pointers, one for each time
01213 //               manager->read_pointer() was called in fillin().
01214 //               Returns the number of pointers processed.
01215 ////////////////////////////////////////////////////////////////////
01216 int GeomNode::CData::
01217 complete_pointers(TypedWritable **p_list, BamReader *manager) {
01218   int pi = CycleData::complete_pointers(p_list, manager);
01219 
01220   // Get the geom and state pointers.
01221   GeomList::iterator gi;
01222   PT(GeomList) geoms = _geoms.get_write_pointer();
01223   for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
01224     GeomEntry &entry = (*gi);
01225     entry._geom = DCAST(Geom, p_list[pi++]);
01226     entry._state = DCAST(RenderState, p_list[pi++]);
01227   }
01228 
01229   return pi;
01230 }
01231 
01232 ////////////////////////////////////////////////////////////////////
01233 //     Function: GeomNode::CData::fillin
01234 //       Access: Public, Virtual
01235 //  Description: This internal function is called by make_from_bam to
01236 //               read in all of the relevant data from the BamFile for
01237 //               the new GeomNode.
01238 ////////////////////////////////////////////////////////////////////
01239 void GeomNode::CData::
01240 fillin(DatagramIterator &scan, BamReader *manager) {
01241   int num_geoms = scan.get_uint16();
01242   // Read the list of geoms and states.  Push back a NULL for each one.
01243   PT(GeomList) geoms = new GeomList;
01244   geoms->reserve(num_geoms);
01245   for (int i = 0; i < num_geoms; i++) {
01246     manager->read_pointer(scan);
01247     manager->read_pointer(scan);
01248     geoms->push_back(GeomEntry(NULL, NULL));
01249   }
01250   _geoms = geoms;
01251 }
 All Classes Functions Variables Enumerations