Panda3D
|
00001 // Filename: geomNode.cxx 00002 // Created by: drose (23Feb02) 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 ©) : 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() != LVecBase4f(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 Colorf &c1 = ca->get_color(); 00188 const LVecBase4f &c2 = csa->get_scale(); 00189 Colorf 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 LMatrix4f &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(const RenderState *state, 00388 PreparedGraphicsObjects *prepared_objects, 00389 Thread *current_thread) { 00390 CDReader cdata(_cycler, current_thread); 00391 GeomList::const_iterator gi; 00392 CPT(GeomList) geoms = cdata->get_geoms(); 00393 for (gi = geoms->begin(); gi != geoms->end(); ++gi) { 00394 CPT(RenderState) geom_state = state->compose((*gi)._state); 00395 const RenderAttrib *attrib = 00396 geom_state->get_attrib(TextureAttrib::get_class_slot()); 00397 if (attrib != (const RenderAttrib *)NULL) { 00398 const TextureAttrib *ta; 00399 DCAST_INTO_V(ta, attrib); 00400 int num_stages = ta->get_num_on_stages(); 00401 for (int i = 0; i < num_stages; ++i) { 00402 Texture *texture = ta->get_on_texture(ta->get_on_stage(i)); 00403 if (texture != (Texture *)NULL) { 00404 texture->prepare(prepared_objects); 00405 } 00406 } 00407 } 00408 } 00409 00410 PandaNode::r_prepare_scene(state, prepared_objects, current_thread); 00411 } 00412 00413 00414 //////////////////////////////////////////////////////////////////// 00415 // Function: GeomNode::combine_with 00416 // Access: Public, Virtual 00417 // Description: Collapses this node with the other node, if possible, 00418 // and returns a pointer to the combined node, or NULL 00419 // if the two nodes cannot safely be combined. 00420 // 00421 // The return value may be this, other, or a new node 00422 // altogether. 00423 // 00424 // This function is called from GraphReducer::flatten(), 00425 // and need not deal with children; its job is just to 00426 // decide whether to collapse the two nodes and what the 00427 // collapsed node should look like. 00428 //////////////////////////////////////////////////////////////////// 00429 PandaNode *GeomNode:: 00430 combine_with(PandaNode *other) { 00431 if (is_exact_type(get_class_type()) && 00432 other->is_exact_type(get_class_type())) { 00433 // Two GeomNodes can combine by moving Geoms from one to the other. 00434 GeomNode *gother = DCAST(GeomNode, other); 00435 add_geoms_from(gother); 00436 return this; 00437 } 00438 00439 return PandaNode::combine_with(other); 00440 } 00441 00442 //////////////////////////////////////////////////////////////////// 00443 // Function: GeomNode::calc_tight_bounds 00444 // Access: Public, Virtual 00445 // Description: This is used to support 00446 // NodePath::calc_tight_bounds(). It is not intended to 00447 // be called directly, and it has nothing to do with the 00448 // normal Panda bounding-volume computation. 00449 // 00450 // If the node contains any geometry, this updates 00451 // min_point and max_point to enclose its bounding box. 00452 // found_any is to be set true if the node has any 00453 // geometry at all, or left alone if it has none. This 00454 // method may be called over several nodes, so it may 00455 // enter with min_point, max_point, and found_any 00456 // already set. 00457 //////////////////////////////////////////////////////////////////// 00458 CPT(TransformState) GeomNode:: 00459 calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, bool &found_any, 00460 const TransformState *transform, Thread *current_thread) const { 00461 CPT(TransformState) next_transform = 00462 PandaNode::calc_tight_bounds(min_point, max_point, found_any, transform, 00463 current_thread); 00464 00465 const LMatrix4f &mat = next_transform->get_mat(); 00466 00467 CDReader cdata(_cycler, current_thread); 00468 GeomList::const_iterator gi; 00469 CPT(GeomList) geoms = cdata->get_geoms(); 00470 for (gi = geoms->begin(); gi != geoms->end(); ++gi) { 00471 CPT(Geom) geom = (*gi)._geom.get_read_pointer(); 00472 geom->calc_tight_bounds(min_point, max_point, found_any, 00473 geom->get_vertex_data(current_thread)->animate_vertices(true, current_thread), 00474 !next_transform->is_identity(), mat, 00475 current_thread); 00476 } 00477 00478 return next_transform; 00479 } 00480 00481 //////////////////////////////////////////////////////////////////// 00482 // Function: GeomNode::is_renderable 00483 // Access: Public, Virtual 00484 // Description: Returns true if there is some value to visiting this 00485 // particular node during the cull traversal for any 00486 // camera, false otherwise. This will be used to 00487 // optimize the result of get_net_draw_show_mask(), so 00488 // that any subtrees that contain only nodes for which 00489 // is_renderable() is false need not be visited. 00490 //////////////////////////////////////////////////////////////////// 00491 bool GeomNode:: 00492 is_renderable() const { 00493 return true; 00494 } 00495 00496 //////////////////////////////////////////////////////////////////// 00497 // Function: GeomNode::add_for_draw 00498 // Access: Public, Virtual 00499 // Description: Adds the node's contents to the CullResult we are 00500 // building up during the cull traversal, so that it 00501 // will be drawn at render time. For most nodes other 00502 // than GeomNodes, this is a do-nothing operation. 00503 //////////////////////////////////////////////////////////////////// 00504 void GeomNode:: 00505 add_for_draw(CullTraverser *trav, CullTraverserData &data) { 00506 trav->_geom_nodes_pcollector.add_level(1); 00507 00508 if (pgraph_cat.is_spam()) { 00509 pgraph_cat.spam() 00510 << "Found " << *this << " in state " << *data._state 00511 << " draw_mask = " << data._draw_mask << "\n"; 00512 } 00513 00514 // Get all the Geoms, with no decalling. 00515 Geoms geoms = get_geoms(trav->get_current_thread()); 00516 int num_geoms = geoms.get_num_geoms(); 00517 trav->_geoms_pcollector.add_level(num_geoms); 00518 CPT(TransformState) net_transform = data.get_net_transform(trav); 00519 CPT(TransformState) modelview_transform = data.get_modelview_transform(trav); 00520 CPT(TransformState) internal_transform = trav->get_gsg()->get_cs_transform()->compose(modelview_transform); 00521 00522 for (int i = 0; i < num_geoms; i++) { 00523 const Geom *geom = geoms.get_geom(i); 00524 if (geom->is_empty()) { 00525 continue; 00526 } 00527 00528 CPT(RenderState) state = data._state->compose(geoms.get_geom_state(i)); 00529 if (state->has_cull_callback() && !state->cull_callback(trav, data)) { 00530 // Cull. 00531 continue; 00532 } 00533 00534 // Cull the Geom bounding volume against the view frustum 00535 // and/or the cull planes. Don't bother unless we've got more 00536 // than one Geom, since otherwise the bounding volume of the 00537 // GeomNode is (probably) the same as that of the one Geom, 00538 // and we've already culled against that. 00539 if (num_geoms > 1) { 00540 if (data._view_frustum != (GeometricBoundingVolume *)NULL) { 00541 // Cull the individual Geom against the view frustum. 00542 CPT(BoundingVolume) geom_volume = geom->get_bounds(); 00543 const GeometricBoundingVolume *geom_gbv = 00544 DCAST(GeometricBoundingVolume, geom_volume); 00545 00546 int result = data._view_frustum->contains(geom_gbv); 00547 if (result == BoundingVolume::IF_no_intersection) { 00548 // Cull this Geom. 00549 continue; 00550 } 00551 } 00552 if (!data._cull_planes->is_empty()) { 00553 // Also cull the Geom against the cull planes. 00554 CPT(BoundingVolume) geom_volume = geom->get_bounds(); 00555 const GeometricBoundingVolume *geom_gbv = 00556 DCAST(GeometricBoundingVolume, geom_volume); 00557 int result; 00558 data._cull_planes->do_cull(result, state, geom_gbv); 00559 if (result == BoundingVolume::IF_no_intersection) { 00560 // Cull. 00561 continue; 00562 } 00563 } 00564 } 00565 00566 CullableObject *object = 00567 new CullableObject(geom, state, net_transform, 00568 modelview_transform, internal_transform); 00569 trav->get_cull_handler()->record_object(object, trav); 00570 } 00571 } 00572 00573 //////////////////////////////////////////////////////////////////// 00574 // Function: GeomNode::get_legal_collide_mask 00575 // Access: Published, Virtual 00576 // Description: Returns the subset of CollideMask bits that may be 00577 // set for this particular type of PandaNode. For most 00578 // nodes, this is 0; it doesn't make sense to set a 00579 // CollideMask for most kinds of nodes. 00580 // 00581 // For nodes that can be collided with, such as GeomNode 00582 // and CollisionNode, this returns all bits on. 00583 //////////////////////////////////////////////////////////////////// 00584 CollideMask GeomNode:: 00585 get_legal_collide_mask() const { 00586 return CollideMask::all_on(); 00587 } 00588 00589 //////////////////////////////////////////////////////////////////// 00590 // Function: GeomNode::add_geom 00591 // Access: Published 00592 // Description: Adds a new Geom to the node. The geom is given the 00593 // indicated state (which may be 00594 // RenderState::make_empty(), to completely inherit its 00595 // state from the scene graph). 00596 //////////////////////////////////////////////////////////////////// 00597 void GeomNode:: 00598 add_geom(Geom *geom, const RenderState *state) { 00599 nassertv(geom != (Geom *)NULL); 00600 nassertv(geom->check_valid()); 00601 nassertv(state != (RenderState *)NULL); 00602 00603 Thread *current_thread = Thread::get_current_thread(); 00604 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) { 00605 CDStageWriter cdata(_cycler, pipeline_stage, current_thread); 00606 00607 cdata->modify_geoms()->push_back(GeomEntry(geom, state)); 00608 } 00609 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler); 00610 00611 mark_internal_bounds_stale(); 00612 } 00613 00614 //////////////////////////////////////////////////////////////////// 00615 // Function: GeomNode::add_geoms_from 00616 // Access: Published 00617 // Description: Copies the Geoms (and their associated RenderStates) 00618 // from the indicated GeomNode into this one. 00619 //////////////////////////////////////////////////////////////////// 00620 void GeomNode:: 00621 add_geoms_from(const GeomNode *other) { 00622 Thread *current_thread = Thread::get_current_thread(); 00623 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) { 00624 CDStageWriter cdata(_cycler, pipeline_stage, current_thread); 00625 CDStageReader cdata_other(other->_cycler, pipeline_stage, current_thread); 00626 00627 GeomList::const_iterator gi; 00628 CPT(GeomList) other_geoms = cdata_other->get_geoms(); 00629 PT(GeomList) this_geoms = cdata->modify_geoms(); 00630 for (gi = other_geoms->begin(); gi != other_geoms->end(); ++gi) { 00631 const GeomEntry &entry = (*gi); 00632 nassertv(entry._geom.get_read_pointer()->check_valid()); 00633 this_geoms->push_back(entry); 00634 } 00635 } 00636 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler); 00637 00638 mark_internal_bounds_stale(); 00639 } 00640 00641 //////////////////////////////////////////////////////////////////// 00642 // Function: GeomNode::set_geom 00643 // Access: Public 00644 // Description: Replaces the nth Geom of the node with a new pointer. 00645 // There must already be a Geom in this slot. 00646 // 00647 // Note that if this method is called in a downstream 00648 // stage (for instance, during cull or draw), then it 00649 // will propagate the new list of Geoms upstream all the 00650 // way to pipeline stage 0, which may step on changes 00651 // that were made independently in pipeline stage 0. 00652 // Use with caution. 00653 //////////////////////////////////////////////////////////////////// 00654 void GeomNode:: 00655 set_geom(int n, Geom *geom) { 00656 nassertv(geom != (Geom *)NULL); 00657 nassertv(geom->check_valid()); 00658 00659 CDWriter cdata(_cycler, true); 00660 PT(GeomList) geoms = cdata->modify_geoms(); 00661 nassertv(n >= 0 && n < (int)geoms->size()); 00662 (*geoms)[n]._geom = geom; 00663 00664 mark_internal_bounds_stale(); 00665 } 00666 00667 //////////////////////////////////////////////////////////////////// 00668 // Function: GeomNode::check_valid 00669 // Access: Published 00670 // Description: Verifies that the each Geom within the GeomNode 00671 // reference vertices that actually exist within its 00672 // GeomVertexData. Returns true if the GeomNode appears 00673 // to be valid, false otherwise. 00674 //////////////////////////////////////////////////////////////////// 00675 bool GeomNode:: 00676 check_valid() const { 00677 int num_geoms = get_num_geoms(); 00678 for (int i = 0; i < num_geoms; i++) { 00679 const Geom *geom = get_geom(i); 00680 if (!geom->check_valid()) { 00681 return false; 00682 } 00683 } 00684 00685 return true; 00686 } 00687 00688 //////////////////////////////////////////////////////////////////// 00689 // Function: GeomNode::decompose 00690 // Access: Published 00691 // Description: Calls decompose() on each Geom with the GeomNode. 00692 // This decomposes higher-order primitive types, like 00693 // triangle strips, into lower-order types like indexed 00694 // triangles. Normally there is no reason to do this, 00695 // but it can be useful as an early preprocessing step, 00696 // to allow a later call to unify() to proceed more 00697 // quickly. 00698 // 00699 // See also SceneGraphReducer::decompose(), which is the 00700 // normal way this is called. 00701 //////////////////////////////////////////////////////////////////// 00702 void GeomNode:: 00703 decompose() { 00704 Thread *current_thread = Thread::get_current_thread(); 00705 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) { 00706 CDStageWriter cdata(_cycler, pipeline_stage, current_thread); 00707 00708 GeomList::iterator gi; 00709 PT(GeomList) geoms = cdata->modify_geoms(); 00710 for (gi = geoms->begin(); gi != geoms->end(); ++gi) { 00711 GeomEntry &entry = (*gi); 00712 nassertv(entry._geom.test_ref_count_integrity()); 00713 PT(Geom) geom = entry._geom.get_write_pointer(); 00714 geom->decompose_in_place(); 00715 } 00716 } 00717 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler); 00718 } 00719 00720 //////////////////////////////////////////////////////////////////// 00721 // Function: GeomNode::unify 00722 // Access: Published 00723 // Description: Attempts to unify all of the Geoms contained within 00724 // this node into a single Geom, or at least as few 00725 // Geoms as possible. In turn, the individual 00726 // GeomPrimitives contained within each resulting Geom 00727 // are also unified. The goal is to reduce the number 00728 // of GeomPrimitives within the node as far as possible. 00729 // This may result in composite primitives, such as 00730 // triangle strips and triangle fans, being decomposed 00731 // into triangles. See also Geom::unify(). 00732 // 00733 // max_indices represents the maximum number of indices 00734 // that will be put in any one GeomPrimitive. If 00735 // preserve_order is true, then the primitives will not 00736 // be reordered during the operation, even if this 00737 // results in a suboptimal result. 00738 // 00739 // In order for this to be successful, the primitives 00740 // must reference the same GeomVertexData, have the same 00741 // fundamental primitive type, and have compatible shade 00742 // models. 00743 //////////////////////////////////////////////////////////////////// 00744 void GeomNode:: 00745 unify(int max_indices, bool preserve_order) { 00746 bool any_changed = false; 00747 00748 Thread *current_thread = Thread::get_current_thread(); 00749 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) { 00750 CDStageWriter cdata(_cycler, pipeline_stage, current_thread); 00751 00752 PT(GeomList) new_geoms = new GeomList; 00753 00754 // Try to unify each Geom with each preceding Geom. This is an n^2 00755 // operation, but usually there are only a handful of Geoms to 00756 // consider, so that's not a big deal. 00757 GeomList::const_iterator gi; 00758 CPT(GeomList) old_geoms = cdata->get_geoms(); 00759 for (gi = old_geoms->begin(); gi != old_geoms->end(); ++gi) { 00760 const GeomEntry &old_entry = (*gi); 00761 00762 bool unified = false; 00763 00764 // Go from back to front, to minimize damage to the primitive ordering. 00765 GeomList::reverse_iterator gj; 00766 for (gj = new_geoms->rbegin(); gj != new_geoms->rend() && !unified; ++gj) { 00767 GeomEntry &new_entry = (*gj); 00768 if (old_entry._state == new_entry._state) { 00769 // Both states match, so try to combine the primitives. 00770 CPT(Geom) old_geom = old_entry._geom.get_read_pointer(); 00771 PT(Geom) new_geom = new_entry._geom.get_write_pointer(); 00772 if (new_geom->copy_primitives_from(old_geom)) { 00773 // Successfully combined! 00774 unified = true; 00775 any_changed = true; 00776 } 00777 } 00778 00779 if (preserve_order) { 00780 // If we're insisting on preserving the order, we can only 00781 // attempt to merge with the tail of the list. 00782 break; 00783 } 00784 } 00785 00786 if (!unified) { 00787 // Couldn't unify this Geom with anything, so just add it to the 00788 // output list. 00789 new_geoms->push_back(old_entry); 00790 } 00791 } 00792 00793 // Done! We'll keep whatever's left in the output list. 00794 cdata->set_geoms(new_geoms); 00795 00796 // Finally, go back through and unify the resulting geom(s). 00797 GeomList::iterator wgi; 00798 for (wgi = new_geoms->begin(); wgi != new_geoms->end(); ++wgi) { 00799 GeomEntry &entry = (*wgi); 00800 nassertv(entry._geom.test_ref_count_integrity()); 00801 PT(Geom) geom = entry._geom.get_write_pointer(); 00802 geom->unify_in_place(max_indices, preserve_order); 00803 } 00804 } 00805 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler); 00806 00807 if (any_changed) { 00808 mark_internal_bounds_stale(); 00809 } 00810 } 00811 00812 //////////////////////////////////////////////////////////////////// 00813 // Function: GeomNode::write_geoms 00814 // Access: Published 00815 // Description: Writes a short description of all the Geoms in the 00816 // node. 00817 //////////////////////////////////////////////////////////////////// 00818 void GeomNode:: 00819 write_geoms(ostream &out, int indent_level) const { 00820 CDReader cdata(_cycler); 00821 write(out, indent_level); 00822 GeomList::const_iterator gi; 00823 CPT(GeomList) geoms = cdata->get_geoms(); 00824 for (gi = geoms->begin(); gi != geoms->end(); ++gi) { 00825 const GeomEntry &entry = (*gi); 00826 indent(out, indent_level + 2) 00827 << *entry._geom.get_read_pointer() << " " << *entry._state << "\n"; 00828 } 00829 } 00830 00831 //////////////////////////////////////////////////////////////////// 00832 // Function: GeomNode::write_verbose 00833 // Access: Published 00834 // Description: Writes a detailed description of all the Geoms in the 00835 // node. 00836 //////////////////////////////////////////////////////////////////// 00837 void GeomNode:: 00838 write_verbose(ostream &out, int indent_level) const { 00839 CDReader cdata(_cycler); 00840 write(out, indent_level); 00841 GeomList::const_iterator gi; 00842 CPT(GeomList) geoms = cdata->get_geoms(); 00843 for (gi = geoms->begin(); gi != geoms->end(); ++gi) { 00844 const GeomEntry &entry = (*gi); 00845 CPT(Geom) geom = entry._geom.get_read_pointer(); 00846 indent(out, indent_level + 2) 00847 << *geom << " " << *entry._state << "\n"; 00848 geom->write(out, indent_level + 4); 00849 } 00850 } 00851 00852 //////////////////////////////////////////////////////////////////// 00853 // Function: GeomNode::output 00854 // Access: Public, Virtual 00855 // Description: 00856 //////////////////////////////////////////////////////////////////// 00857 void GeomNode:: 00858 output(ostream &out) const { 00859 // Accumulate the total set of RenderAttrib types that are applied 00860 // to any of our Geoms, so we can output them too. The result will 00861 // be the list of attrib types that might be applied to some Geoms, 00862 // but not necessarily to all Geoms. 00863 00864 CDReader cdata(_cycler); 00865 00866 pset<TypeHandle> attrib_types; 00867 00868 GeomList::const_iterator gi; 00869 CPT(RenderState) common = RenderState::make_empty(); 00870 00871 CPT(GeomList) geoms = cdata->get_geoms(); 00872 for (gi = geoms->begin(); gi != geoms->end(); ++gi) { 00873 const GeomEntry &entry = (*gi); 00874 common = common->compose(entry._state); 00875 } 00876 00877 PandaNode::output(out); 00878 out << " (" << geoms->size() << " geoms"; 00879 00880 if (!common->is_empty()) { 00881 out << ": " << *common; 00882 } 00883 00884 out << ")"; 00885 } 00886 00887 //////////////////////////////////////////////////////////////////// 00888 // Function: GeomNode::is_geom_node 00889 // Access: Public, Virtual 00890 // Description: A simple downcast check. Returns true if this kind 00891 // of node happens to inherit from GeomNode, false 00892 // otherwise. 00893 // 00894 // This is provided as a a faster alternative to calling 00895 // is_of_type(GeomNode::get_class_type()), since this 00896 // test is so important to rendering. 00897 //////////////////////////////////////////////////////////////////// 00898 bool GeomNode:: 00899 is_geom_node() const { 00900 return true; 00901 } 00902 00903 //////////////////////////////////////////////////////////////////// 00904 // Function: GeomNode::do_premunge 00905 // Access: Public 00906 // Description: Uses the indicated GSG to premunge the Geoms in this 00907 // node to optimize them for eventual rendering. See 00908 // SceneGraphReducer::premunge(). 00909 //////////////////////////////////////////////////////////////////// 00910 void GeomNode:: 00911 do_premunge(GraphicsStateGuardianBase *gsg, 00912 const RenderState *node_state, 00913 GeomTransformer &transformer) { 00914 Thread *current_thread = Thread::get_current_thread(); 00915 00916 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) { 00917 CDStageWriter cdata(_cycler, pipeline_stage, current_thread); 00918 00919 GeomList::iterator gi; 00920 PT(GeomList) geoms = cdata->modify_geoms(); 00921 for (gi = geoms->begin(); gi != geoms->end(); ++gi) { 00922 GeomEntry &entry = (*gi); 00923 CPT(RenderState) geom_state = node_state->compose(entry._state); 00924 CPT(Geom) geom = entry._geom.get_read_pointer(); 00925 PT(GeomMunger) munger = gsg->get_geom_munger(geom_state, current_thread); 00926 entry._geom = transformer.premunge_geom(geom, munger); 00927 } 00928 } 00929 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler); 00930 } 00931 00932 //////////////////////////////////////////////////////////////////// 00933 // Function: GeomNode::r_mark_geom_bounds_stale 00934 // Access: Protected, Virtual 00935 // Description: Recursively calls Geom::mark_bounds_stale() on every 00936 // Geom at this node and below. 00937 //////////////////////////////////////////////////////////////////// 00938 void GeomNode:: 00939 r_mark_geom_bounds_stale(Thread *current_thread) { 00940 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) { 00941 CDStageWriter cdata(_cycler, pipeline_stage, current_thread); 00942 00943 GeomList::iterator gi; 00944 PT(GeomList) geoms = cdata->modify_geoms(); 00945 for (gi = geoms->begin(); gi != geoms->end(); ++gi) { 00946 GeomEntry &entry = (*gi); 00947 entry._geom.get_read_pointer()->mark_bounds_stale(); 00948 } 00949 } 00950 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler); 00951 mark_internal_bounds_stale(); 00952 00953 PandaNode::r_mark_geom_bounds_stale(current_thread); 00954 } 00955 00956 //////////////////////////////////////////////////////////////////// 00957 // Function: GeomNode::compute_internal_bounds 00958 // Access: Protected, Virtual 00959 // Description: Returns a newly-allocated BoundingVolume that 00960 // represents the internal contents of the node. Should 00961 // be overridden by PandaNode classes that contain 00962 // something internally. 00963 //////////////////////////////////////////////////////////////////// 00964 void GeomNode:: 00965 compute_internal_bounds(CPT(BoundingVolume) &internal_bounds, 00966 int &internal_vertices, 00967 int pipeline_stage, 00968 Thread *current_thread) const { 00969 int num_vertices = 0; 00970 00971 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread); 00972 00973 pvector<const BoundingVolume *> child_volumes; 00974 pvector<CPT(BoundingVolume) > child_volumes_ref; 00975 bool all_box = true; 00976 00977 GeomList::const_iterator gi; 00978 CPT(GeomList) geoms = cdata->get_geoms(); 00979 child_volumes.reserve(geoms->size()); 00980 child_volumes_ref.reserve(geoms->size()); 00981 00982 for (gi = geoms->begin(); gi != geoms->end(); ++gi) { 00983 const GeomEntry &entry = (*gi); 00984 CPT(Geom) geom = entry._geom.get_read_pointer(); 00985 CPT(BoundingVolume) volume = geom->get_bounds(); 00986 00987 if (!volume->is_empty()) { 00988 child_volumes.push_back(volume); 00989 child_volumes_ref.push_back(volume); 00990 if (!volume->is_exact_type(BoundingBox::get_class_type())) { 00991 all_box = false; 00992 } 00993 } 00994 num_vertices += geom->get_nested_vertices(); 00995 } 00996 00997 PT(GeometricBoundingVolume) gbv; 00998 00999 BoundingVolume::BoundsType btype = get_bounds_type(); 01000 if (btype == BoundingVolume::BT_default) { 01001 btype = bounds_type; 01002 } 01003 01004 if (btype == BoundingVolume::BT_box || 01005 (btype != BoundingVolume::BT_sphere && all_box)) { 01006 // If all of the child volumes are a BoundingBox, then our volume 01007 // is also a BoundingBox. 01008 gbv = new BoundingBox; 01009 } else { 01010 // Otherwise, it's a sphere. 01011 gbv = new BoundingSphere; 01012 } 01013 01014 if (child_volumes.size() > 0) { 01015 const BoundingVolume **child_begin = &child_volumes[0]; 01016 const BoundingVolume **child_end = child_begin + child_volumes.size(); 01017 ((BoundingVolume *)gbv)->around(child_begin, child_end); 01018 } 01019 01020 internal_bounds = gbv; 01021 internal_vertices = num_vertices; 01022 } 01023 01024 //////////////////////////////////////////////////////////////////// 01025 // Function: GeomNode::register_with_read_factory 01026 // Access: Public, Static 01027 // Description: Tells the BamReader how to create objects of type 01028 // GeomNode. 01029 //////////////////////////////////////////////////////////////////// 01030 void GeomNode:: 01031 register_with_read_factory() { 01032 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); 01033 } 01034 01035 //////////////////////////////////////////////////////////////////// 01036 // Function: GeomNode::write_datagram 01037 // Access: Public, Virtual 01038 // Description: Writes the contents of this object to the datagram 01039 // for shipping out to a Bam file. 01040 //////////////////////////////////////////////////////////////////// 01041 void GeomNode:: 01042 write_datagram(BamWriter *manager, Datagram &dg) { 01043 PandaNode::write_datagram(manager, dg); 01044 manager->write_cdata(dg, _cycler); 01045 } 01046 01047 //////////////////////////////////////////////////////////////////// 01048 // Function: GeomNode::finalize 01049 // Access: Public, Virtual 01050 // Description: Called by the BamReader to perform any final actions 01051 // needed for setting up the object after all objects 01052 // have been read and all pointers have been completed. 01053 //////////////////////////////////////////////////////////////////// 01054 void GeomNode:: 01055 finalize(BamReader *manager) { 01056 if (manager->get_file_minor_ver() < 14) { 01057 // With version 6.14, we changed the default ColorAttrib 01058 // behavior from make_vertex() to make_flat(). This means that 01059 // every Geom that contains vertex colors now needs to have an 01060 // explicit ColorAttrib::make_vertex() on its state. 01061 01062 // Since we shouldn't override a different ColorAttrib inherited 01063 // from above, we create this new attrib with an override of -1. 01064 01065 CPT(InternalName) color = InternalName::get_color(); 01066 CPT(RenderAttrib) vertex_color = ColorAttrib::make_vertex(); 01067 01068 Thread *current_thread = Thread::get_current_thread(); 01069 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) { 01070 CDStageWriter cdata(_cycler, pipeline_stage, current_thread); 01071 01072 GeomList::iterator gi; 01073 PT(GeomList) geoms = cdata->modify_geoms(); 01074 for (gi = geoms->begin(); gi != geoms->end(); ++gi) { 01075 GeomEntry &entry = (*gi); 01076 CPT(Geom) geom = entry._geom.get_read_pointer(); 01077 01078 // Force the various GeomVertexArrayFormat objects to finalize 01079 // themselves. We have to do this before we can reliably call 01080 // GeomVertexData::has_column(). 01081 CPT(GeomVertexData) vdata = geom->get_vertex_data(current_thread); 01082 CPT(GeomVertexFormat) vformat = vdata->get_format(); 01083 for (int i = 0; i < vformat->get_num_arrays(); ++i) { 01084 const GeomVertexArrayFormat *varray = vformat->get_array(i); 01085 manager->finalize_now((GeomVertexArrayFormat *)varray); 01086 } 01087 01088 if (vdata->has_column(color) && 01089 !entry._state->has_attrib(ColorAttrib::get_class_slot())) { 01090 // We'll be reassigning the RenderState. Therefore, save it 01091 // temporarily to increment its reference count. 01092 PT(BamAuxData) aux_data = new BamAuxData; 01093 aux_data->_hold_state = entry._state; 01094 manager->set_aux_data((RenderState *)entry._state.p(), "hold_state", aux_data); 01095 01096 entry._state = entry._state->add_attrib(vertex_color, -1); 01097 } 01098 } 01099 } 01100 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler); 01101 } 01102 } 01103 01104 //////////////////////////////////////////////////////////////////// 01105 // Function: GeomNode::make_from_bam 01106 // Access: Protected, Static 01107 // Description: This function is called by the BamReader's factory 01108 // when a new object of type GeomNode is encountered 01109 // in the Bam file. It should create the GeomNode 01110 // and extract its information from the file. 01111 //////////////////////////////////////////////////////////////////// 01112 TypedWritable *GeomNode:: 01113 make_from_bam(const FactoryParams ¶ms) { 01114 GeomNode *node = new GeomNode(""); 01115 DatagramIterator scan; 01116 BamReader *manager; 01117 01118 parse_params(params, scan, manager); 01119 node->fillin(scan, manager); 01120 01121 if (manager->get_file_minor_ver() < 14) { 01122 manager->register_finalize(node); 01123 } 01124 01125 return node; 01126 } 01127 01128 //////////////////////////////////////////////////////////////////// 01129 // Function: GeomNode::fillin 01130 // Access: Protected 01131 // Description: This internal function is called by make_from_bam to 01132 // read in all of the relevant data from the BamFile for 01133 // the new GeomNode. 01134 //////////////////////////////////////////////////////////////////// 01135 void GeomNode:: 01136 fillin(DatagramIterator &scan, BamReader *manager) { 01137 PandaNode::fillin(scan, manager); 01138 manager->read_cdata(scan, _cycler); 01139 } 01140 01141 //////////////////////////////////////////////////////////////////// 01142 // Function: GeomNode::CData::Copy Constructor 01143 // Access: Public 01144 // Description: 01145 //////////////////////////////////////////////////////////////////// 01146 GeomNode::CData:: 01147 CData(const GeomNode::CData ©) : 01148 _geoms(copy._geoms) 01149 { 01150 } 01151 01152 //////////////////////////////////////////////////////////////////// 01153 // Function: GeomNode::CData::make_copy 01154 // Access: Public, Virtual 01155 // Description: 01156 //////////////////////////////////////////////////////////////////// 01157 CycleData *GeomNode::CData:: 01158 make_copy() const { 01159 return new CData(*this); 01160 } 01161 01162 //////////////////////////////////////////////////////////////////// 01163 // Function: GeomNode::CData::write_datagram 01164 // Access: Public, Virtual 01165 // Description: Writes the contents of this object to the datagram 01166 // for shipping out to a Bam file. 01167 //////////////////////////////////////////////////////////////////// 01168 void GeomNode::CData:: 01169 write_datagram(BamWriter *manager, Datagram &dg) const { 01170 CPT(GeomList) geoms = _geoms.get_read_pointer(); 01171 int num_geoms = geoms->size(); 01172 nassertv(num_geoms == (int)(PN_uint16)num_geoms); 01173 dg.add_uint16(num_geoms); 01174 01175 GeomList::const_iterator gi; 01176 for (gi = geoms->begin(); gi != geoms->end(); ++gi) { 01177 const GeomEntry &entry = (*gi); 01178 manager->write_pointer(dg, entry._geom.get_read_pointer()); 01179 manager->write_pointer(dg, entry._state); 01180 } 01181 } 01182 01183 //////////////////////////////////////////////////////////////////// 01184 // Function: GeomNode::CData::complete_pointers 01185 // Access: Public, Virtual 01186 // Description: Receives an array of pointers, one for each time 01187 // manager->read_pointer() was called in fillin(). 01188 // Returns the number of pointers processed. 01189 //////////////////////////////////////////////////////////////////// 01190 int GeomNode::CData:: 01191 complete_pointers(TypedWritable **p_list, BamReader *manager) { 01192 int pi = CycleData::complete_pointers(p_list, manager); 01193 01194 // Get the geom and state pointers. 01195 GeomList::iterator gi; 01196 PT(GeomList) geoms = _geoms.get_write_pointer(); 01197 for (gi = geoms->begin(); gi != geoms->end(); ++gi) { 01198 GeomEntry &entry = (*gi); 01199 entry._geom = DCAST(Geom, p_list[pi++]); 01200 entry._state = DCAST(RenderState, p_list[pi++]); 01201 } 01202 01203 return pi; 01204 } 01205 01206 //////////////////////////////////////////////////////////////////// 01207 // Function: GeomNode::CData::fillin 01208 // Access: Public, Virtual 01209 // Description: This internal function is called by make_from_bam to 01210 // read in all of the relevant data from the BamFile for 01211 // the new GeomNode. 01212 //////////////////////////////////////////////////////////////////// 01213 void GeomNode::CData:: 01214 fillin(DatagramIterator &scan, BamReader *manager) { 01215 int num_geoms = scan.get_uint16(); 01216 // Read the list of geoms and states. Push back a NULL for each one. 01217 PT(GeomList) geoms = new GeomList; 01218 geoms->reserve(num_geoms); 01219 for (int i = 0; i < num_geoms; i++) { 01220 manager->read_pointer(scan); 01221 manager->read_pointer(scan); 01222 geoms->push_back(GeomEntry(NULL, NULL)); 01223 } 01224 _geoms = geoms; 01225 }