Panda3D

geom.cxx

00001 // Filename: geom.cxx
00002 // Created by:  drose (06Mar05)
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 "geom.h"
00016 #include "geomPoints.h"
00017 #include "geomVertexReader.h"
00018 #include "geomVertexRewriter.h"
00019 #include "graphicsStateGuardianBase.h"
00020 #include "preparedGraphicsObjects.h"
00021 #include "pStatTimer.h"
00022 #include "bamReader.h"
00023 #include "bamWriter.h"
00024 #include "boundingSphere.h"
00025 #include "boundingBox.h"
00026 #include "lightMutexHolder.h"
00027 #include "config_mathutil.h"
00028 
00029 UpdateSeq Geom::_next_modified;
00030 PStatCollector Geom::_draw_primitive_setup_pcollector("Draw:Primitive:Setup");
00031 
00032 TypeHandle Geom::_type_handle;
00033 TypeHandle Geom::CDataCache::_type_handle;
00034 TypeHandle Geom::CacheEntry::_type_handle;
00035 TypeHandle Geom::CData::_type_handle;
00036 TypeHandle GeomPipelineReader::_type_handle;
00037 
00038 ////////////////////////////////////////////////////////////////////
00039 //     Function: Geom::make_cow_copy
00040 //       Access: Protected, Virtual
00041 //  Description: Required to implement CopyOnWriteObject.
00042 ////////////////////////////////////////////////////////////////////
00043 PT(CopyOnWriteObject) Geom::
00044 make_cow_copy() {
00045   return make_copy();
00046 }
00047 
00048 ////////////////////////////////////////////////////////////////////
00049 //     Function: Geom::Constructor
00050 //       Access: Published
00051 //  Description: 
00052 ////////////////////////////////////////////////////////////////////
00053 Geom::
00054 Geom(const GeomVertexData *data) {
00055   // Let's ensure the vertex data gets set on all stages at once.
00056   OPEN_ITERATE_ALL_STAGES(_cycler) {
00057     CDStageWriter cdata(_cycler, pipeline_stage);
00058     cdata->_data = (GeomVertexData *)data;
00059   }
00060   CLOSE_ITERATE_ALL_STAGES(_cycler);
00061 }
00062 
00063 ////////////////////////////////////////////////////////////////////
00064 //     Function: Geom::Copy Constructor
00065 //       Access: Protected
00066 //  Description: Use make_copy() to duplicate a Geom.
00067 ////////////////////////////////////////////////////////////////////
00068 Geom::
00069 Geom(const Geom &copy) :
00070   CopyOnWriteObject(copy),
00071   _cycler(copy._cycler)  
00072 {
00073 }
00074 
00075 ////////////////////////////////////////////////////////////////////
00076 //     Function: Geom::Copy Assignment Operator
00077 //       Access: Published
00078 //  Description: The copy assignment operator is not pipeline-safe.
00079 //               This will completely obliterate all stages of the
00080 //               pipeline, so don't do it for a Geom that is actively
00081 //               being used for rendering.
00082 ////////////////////////////////////////////////////////////////////
00083 void Geom::
00084 operator = (const Geom &copy) {
00085   CopyOnWriteObject::operator = (copy);
00086 
00087   clear_cache();
00088 
00089   _cycler = copy._cycler;
00090 
00091   OPEN_ITERATE_ALL_STAGES(_cycler) {
00092     CDStageWriter cdata(_cycler, pipeline_stage);
00093     mark_internal_bounds_stale(cdata);
00094   }
00095   CLOSE_ITERATE_ALL_STAGES(_cycler);
00096 }
00097 
00098 ////////////////////////////////////////////////////////////////////
00099 //     Function: Geom::Destructor
00100 //       Access: Published, Virtual
00101 //  Description: 
00102 ////////////////////////////////////////////////////////////////////
00103 Geom::
00104 ~Geom() {
00105   clear_cache();
00106   release_all();
00107 }
00108 
00109 ////////////////////////////////////////////////////////////////////
00110 //     Function: Geom::make_copy
00111 //       Access: Protected, Virtual
00112 //  Description: Returns a newly-allocated Geom that is a shallow copy
00113 //               of this one.  It will be a different Geom pointer,
00114 //               but its internal data may or may not be shared with
00115 //               that of the original Geom.
00116 ////////////////////////////////////////////////////////////////////
00117 Geom *Geom::
00118 make_copy() const {
00119   return new Geom(*this);
00120 }
00121 
00122 ////////////////////////////////////////////////////////////////////
00123 //     Function: Geom::set_usage_hint
00124 //       Access: Published
00125 //  Description: Changes the UsageHint hint for all of the primitives
00126 //               on this Geom to the same value.  See
00127 //               get_usage_hint().
00128 //
00129 //               Don't call this in a downstream thread unless you
00130 //               don't mind it blowing away other changes you might
00131 //               have recently made in an upstream thread.
00132 ////////////////////////////////////////////////////////////////////
00133 void Geom::
00134 set_usage_hint(Geom::UsageHint usage_hint) {
00135   Thread *current_thread = Thread::get_current_thread();
00136   CDWriter cdata(_cycler, true, current_thread);
00137   cdata->_usage_hint = usage_hint;
00138 
00139   Primitives::iterator pi;
00140   for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
00141     PT(GeomPrimitive) prim = (*pi).get_write_pointer();
00142     prim->set_usage_hint(usage_hint);
00143   }
00144 
00145   clear_cache_stage(current_thread);
00146   cdata->_modified = Geom::get_next_modified();
00147 }
00148 
00149 ////////////////////////////////////////////////////////////////////
00150 //     Function: Geom::modify_vertex_data
00151 //       Access: Published
00152 //  Description: Returns a modifiable pointer to the GeomVertexData,
00153 //               so that application code may directly maniuplate the
00154 //               geom's underlying data.
00155 //
00156 //               Don't call this in a downstream thread unless you
00157 //               don't mind it blowing away other changes you might
00158 //               have recently made in an upstream thread.
00159 ////////////////////////////////////////////////////////////////////
00160 PT(GeomVertexData) Geom::
00161 modify_vertex_data() {
00162   Thread *current_thread = Thread::get_current_thread();
00163   // Perform copy-on-write: if the reference count on the vertex data
00164   // is greater than 1, assume some other Geom has the same pointer,
00165   // so make a copy of it first.
00166   CDWriter cdata(_cycler, true, current_thread);
00167   clear_cache_stage(current_thread);
00168   mark_internal_bounds_stale(cdata);
00169   return cdata->_data.get_write_pointer();
00170 }
00171 
00172 ////////////////////////////////////////////////////////////////////
00173 //     Function: Geom::set_vertex_data
00174 //       Access: Published
00175 //  Description: Replaces the Geom's underlying vertex data table with
00176 //               a completely new table.
00177 //
00178 //               Don't call this in a downstream thread unless you
00179 //               don't mind it blowing away other changes you might
00180 //               have recently made in an upstream thread.
00181 ////////////////////////////////////////////////////////////////////
00182 void Geom::
00183 set_vertex_data(const GeomVertexData *data) {
00184   Thread *current_thread = Thread::get_current_thread();
00185   nassertv(check_will_be_valid(data));
00186   CDWriter cdata(_cycler, true, current_thread);
00187   cdata->_data = (GeomVertexData *)data;
00188   clear_cache_stage(current_thread);
00189   mark_internal_bounds_stale(cdata);
00190   reset_geom_rendering(cdata);
00191 }
00192 
00193 ////////////////////////////////////////////////////////////////////
00194 //     Function: Geom::offset_vertices
00195 //       Access: Published
00196 //  Description: Replaces a Geom's vertex table with a new table, and
00197 //               simultaneously adds the indicated offset to all
00198 //               vertex references within the Geom's primitives.  This
00199 //               is intended to be used to combine multiple
00200 //               GeomVertexDatas from different Geoms into a single
00201 //               big buffer, with each Geom referencing a subset of
00202 //               the vertices in the buffer.
00203 //
00204 //               Don't call this in a downstream thread unless you
00205 //               don't mind it blowing away other changes you might
00206 //               have recently made in an upstream thread.
00207 ////////////////////////////////////////////////////////////////////
00208 void Geom::
00209 offset_vertices(const GeomVertexData *data, int offset) {
00210   Thread *current_thread = Thread::get_current_thread();
00211   CDWriter cdata(_cycler, true, current_thread);
00212   cdata->_data = (GeomVertexData *)data;
00213 
00214 #ifndef NDEBUG
00215   bool all_is_valid = true;
00216 #endif
00217   Primitives::iterator pi;
00218   for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
00219     PT(GeomPrimitive) prim = (*pi).get_write_pointer();
00220     prim->offset_vertices(offset);
00221 
00222 #ifndef NDEBUG
00223     if (!prim->check_valid(data)) {
00224       gobj_cat.warning()
00225         << *prim << " is invalid for " << *data << ":\n";
00226       prim->write(gobj_cat.warning(false), 4);
00227       
00228       all_is_valid = false;
00229     }
00230 #endif
00231   }
00232 
00233   cdata->_modified = Geom::get_next_modified();
00234   clear_cache_stage(current_thread);
00235   nassertv(all_is_valid);
00236 }
00237 
00238 ////////////////////////////////////////////////////////////////////
00239 //     Function: Geom::make_nonindexed
00240 //       Access: Published
00241 //  Description: Converts the geom from indexed to nonindexed by
00242 //               duplicating vertices as necessary.  If composite_only
00243 //               is true, then only composite primitives such as
00244 //               trifans and tristrips are converted.  Returns the
00245 //               number of GeomPrimitive objects converted.
00246 //
00247 //               Don't call this in a downstream thread unless you
00248 //               don't mind it blowing away other changes you might
00249 //               have recently made in an upstream thread.
00250 ////////////////////////////////////////////////////////////////////
00251 int Geom::
00252 make_nonindexed(bool composite_only) {
00253   Thread *current_thread = Thread::get_current_thread();
00254   int num_changed = 0;
00255 
00256   CDWriter cdata(_cycler, true, current_thread);
00257   CPT(GeomVertexData) orig_data = cdata->_data.get_read_pointer();
00258   PT(GeomVertexData) new_data = new GeomVertexData(*orig_data);
00259   new_data->clear_rows();
00260 
00261 #ifndef NDEBUG
00262   bool all_is_valid = true;
00263 #endif
00264   Primitives::iterator pi;
00265   Primitives new_prims;
00266   new_prims.reserve(cdata->_primitives.size());
00267   for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
00268     PT(GeomPrimitive) primitive = (*pi).get_read_pointer()->make_copy();
00269     new_prims.push_back(primitive.p());
00270 
00271     // GeomPoints are considered "composite" for the purposes of
00272     // making nonindexed, since there's no particular advantage to
00273     // having indexed points (as opposed to, say, indexed triangles or
00274     // indexed lines).
00275     if (primitive->is_indexed() && 
00276         (primitive->is_composite() || 
00277          primitive->is_exact_type(GeomPoints::get_class_type()) || 
00278          !composite_only)) {
00279       primitive->make_nonindexed(new_data, orig_data);
00280       ++num_changed;
00281     } else {
00282       // If it's a simple primitive, pack it anyway, so it can share
00283       // the same GeomVertexData.
00284       primitive->pack_vertices(new_data, orig_data);
00285     }
00286 
00287 #ifndef NDEBUG
00288     if (!primitive->check_valid(new_data)) {
00289       all_is_valid = false;
00290     }
00291 #endif
00292   }
00293 
00294   nassertr(all_is_valid, 0);
00295 
00296   if (num_changed != 0) {
00297     // If any at all were changed, then keep the result (otherwise,
00298     // discard it, since we might have de-optimized the indexed
00299     // geometry a bit).
00300     cdata->_data = new_data;
00301     cdata->_primitives.swap(new_prims);
00302     cdata->_modified = Geom::get_next_modified();
00303     clear_cache_stage(current_thread);
00304   }
00305 
00306   return num_changed;
00307 }
00308 
00309 ////////////////////////////////////////////////////////////////////
00310 //     Function: Geom::set_primitive
00311 //       Access: Published
00312 //  Description: Replaces the ith GeomPrimitive object stored within
00313 //               the Geom with the new object.
00314 //
00315 //               Don't call this in a downstream thread unless you
00316 //               don't mind it blowing away other changes you might
00317 //               have recently made in an upstream thread.
00318 ////////////////////////////////////////////////////////////////////
00319 void Geom::
00320 set_primitive(int i, const GeomPrimitive *primitive) {
00321   Thread *current_thread = Thread::get_current_thread();
00322   CDWriter cdata(_cycler, true, current_thread);
00323   nassertv(i >= 0 && i < (int)cdata->_primitives.size());
00324   nassertv(primitive->check_valid(cdata->_data.get_read_pointer()));
00325 
00326   // All primitives within a particular Geom must have the same
00327   // fundamental primitive type (triangles, points, or lines).
00328   nassertv(cdata->_primitive_type == PT_none ||
00329            cdata->_primitive_type == primitive->get_primitive_type());
00330 
00331   // They also should have the a compatible shade model.
00332   CPT(GeomPrimitive) compat = primitive->match_shade_model(cdata->_shade_model);
00333   nassertv_always(compat != (GeomPrimitive *)NULL);
00334 
00335   cdata->_primitives[i] = (GeomPrimitive *)compat.p();
00336   PrimitiveType new_primitive_type = compat->get_primitive_type();
00337   if (new_primitive_type != cdata->_primitive_type) {
00338     cdata->_primitive_type = new_primitive_type;
00339   }
00340   ShadeModel new_shade_model = compat->get_shade_model();
00341   if (new_shade_model != cdata->_shade_model &&
00342       new_shade_model != SM_uniform) {
00343     cdata->_shade_model = new_shade_model;
00344   }
00345 
00346   reset_geom_rendering(cdata);
00347   cdata->_got_usage_hint = false;
00348   cdata->_modified = Geom::get_next_modified();
00349   clear_cache_stage(current_thread);
00350   mark_internal_bounds_stale(cdata);
00351 }
00352 
00353 ////////////////////////////////////////////////////////////////////
00354 //     Function: Geom::add_primitive
00355 //       Access: Published
00356 //  Description: Adds a new GeomPrimitive structure to the Geom
00357 //               object.  This specifies a particular subset of
00358 //               vertices that are used to define geometric primitives
00359 //               of the indicated type.
00360 //
00361 //               Don't call this in a downstream thread unless you
00362 //               don't mind it blowing away other changes you might
00363 //               have recently made in an upstream thread.
00364 ////////////////////////////////////////////////////////////////////
00365 void Geom::
00366 add_primitive(const GeomPrimitive *primitive) {
00367   Thread *current_thread = Thread::get_current_thread();
00368   CDWriter cdata(_cycler, true, current_thread);
00369 
00370   nassertv(primitive->check_valid(cdata->_data.get_read_pointer()));
00371 
00372   // All primitives within a particular Geom must have the same
00373   // fundamental primitive type (triangles, points, or lines).
00374   nassertv(cdata->_primitive_type == PT_none ||
00375            cdata->_primitive_type == primitive->get_primitive_type());
00376 
00377   // They also should have the a compatible shade model.
00378   CPT(GeomPrimitive) compat = primitive->match_shade_model(cdata->_shade_model);
00379   nassertv_always(compat != (GeomPrimitive *)NULL);
00380 
00381   cdata->_primitives.push_back((GeomPrimitive *)compat.p());
00382   PrimitiveType new_primitive_type = compat->get_primitive_type();
00383   if (new_primitive_type != cdata->_primitive_type) {
00384     cdata->_primitive_type = new_primitive_type;
00385   }
00386   ShadeModel new_shade_model = compat->get_shade_model();
00387   if (new_shade_model != cdata->_shade_model &&
00388       new_shade_model != SM_uniform) {
00389     cdata->_shade_model = new_shade_model;
00390   }
00391 
00392   reset_geom_rendering(cdata);
00393   cdata->_got_usage_hint = false;
00394   cdata->_modified = Geom::get_next_modified();
00395   clear_cache_stage(current_thread);
00396   mark_internal_bounds_stale(cdata);
00397 }
00398 
00399 ////////////////////////////////////////////////////////////////////
00400 //     Function: Geom::remove_primitive
00401 //       Access: Published
00402 //  Description: Removes the ith primitive from the list.
00403 //
00404 //               Don't call this in a downstream thread unless you
00405 //               don't mind it blowing away other changes you might
00406 //               have recently made in an upstream thread.
00407 ////////////////////////////////////////////////////////////////////
00408 void Geom::
00409 remove_primitive(int i) {
00410   Thread *current_thread = Thread::get_current_thread();
00411   CDWriter cdata(_cycler, true, current_thread);
00412   nassertv(i >= 0 && i < (int)cdata->_primitives.size());
00413   cdata->_primitives.erase(cdata->_primitives.begin() + i);
00414   if (cdata->_primitives.empty()) {
00415     cdata->_primitive_type = PT_none;
00416     cdata->_shade_model = SM_uniform;
00417   }
00418   reset_geom_rendering(cdata);
00419   cdata->_got_usage_hint = false;
00420   cdata->_modified = Geom::get_next_modified();
00421   clear_cache_stage(current_thread);
00422   mark_internal_bounds_stale(cdata);
00423 }
00424 
00425 ////////////////////////////////////////////////////////////////////
00426 //     Function: Geom::clear_primitives
00427 //       Access: Published
00428 //  Description: Removes all the primitives from the Geom object (but
00429 //               keeps the same table of vertices).  You may then
00430 //               re-add primitives one at a time via calls to
00431 //               add_primitive().
00432 //
00433 //               Don't call this in a downstream thread unless you
00434 //               don't mind it blowing away other changes you might
00435 //               have recently made in an upstream thread.
00436 ////////////////////////////////////////////////////////////////////
00437 void Geom::
00438 clear_primitives() {
00439   Thread *current_thread = Thread::get_current_thread();
00440   CDWriter cdata(_cycler, true, current_thread);
00441   cdata->_primitives.clear();
00442   cdata->_primitive_type = PT_none;
00443   cdata->_shade_model = SM_uniform;
00444   reset_geom_rendering(cdata);
00445   clear_cache_stage(current_thread);
00446   mark_internal_bounds_stale(cdata);
00447 }
00448 
00449 ////////////////////////////////////////////////////////////////////
00450 //     Function: Geom::decompose_in_place
00451 //       Access: Published
00452 //  Description: Decomposes all of the primitives within this Geom,
00453 //               leaving the results in place.  See
00454 //               GeomPrimitive::decompose().
00455 //
00456 //               Don't call this in a downstream thread unless you
00457 //               don't mind it blowing away other changes you might
00458 //               have recently made in an upstream thread.
00459 ////////////////////////////////////////////////////////////////////
00460 void Geom::
00461 decompose_in_place() {
00462   Thread *current_thread = Thread::get_current_thread();
00463   CDWriter cdata(_cycler, true, current_thread);
00464 
00465 #ifndef NDEBUG
00466   bool all_is_valid = true;
00467 #endif
00468   Primitives::iterator pi;
00469   for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
00470     CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->decompose();
00471     (*pi) = (GeomPrimitive *)new_prim.p();
00472 
00473 #ifndef NDEBUG
00474     if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
00475       all_is_valid = false;
00476     }
00477 #endif
00478   }
00479 
00480   cdata->_modified = Geom::get_next_modified();
00481   reset_geom_rendering(cdata);
00482   clear_cache_stage(current_thread);
00483 
00484   nassertv(all_is_valid);
00485 }
00486 
00487 ////////////////////////////////////////////////////////////////////
00488 //     Function: Geom::doubleside_in_place
00489 //       Access: Published
00490 //  Description: Doublesides all of the primitives within this Geom,
00491 //               leaving the results in place.  See
00492 //               GeomPrimitive::doubleside().
00493 //
00494 //               Don't call this in a downstream thread unless you
00495 //               don't mind it blowing away other changes you might
00496 //               have recently made in an upstream thread.
00497 ////////////////////////////////////////////////////////////////////
00498 void Geom::
00499 doubleside_in_place() {
00500   Thread *current_thread = Thread::get_current_thread();
00501   CDWriter cdata(_cycler, true, current_thread);
00502 
00503 #ifndef NDEBUG
00504   bool all_is_valid = true;
00505 #endif
00506   Primitives::iterator pi;
00507   for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
00508     CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->doubleside();
00509     (*pi) = (GeomPrimitive *)new_prim.p();
00510 
00511 #ifndef NDEBUG
00512     if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
00513       all_is_valid = false;
00514     }
00515 #endif
00516   }
00517 
00518   cdata->_modified = Geom::get_next_modified();
00519   reset_geom_rendering(cdata);
00520   clear_cache_stage(current_thread);
00521 
00522   nassertv(all_is_valid);
00523 }
00524 
00525 ////////////////////////////////////////////////////////////////////
00526 //     Function: Geom::reverse_in_place
00527 //       Access: Published
00528 //  Description: Reverses all of the primitives within this Geom,
00529 //               leaving the results in place.  See
00530 //               GeomPrimitive::reverse().
00531 //
00532 //               Don't call this in a downstream thread unless you
00533 //               don't mind it blowing away other changes you might
00534 //               have recently made in an upstream thread.
00535 ////////////////////////////////////////////////////////////////////
00536 void Geom::
00537 reverse_in_place() {
00538   Thread *current_thread = Thread::get_current_thread();
00539   CDWriter cdata(_cycler, true, current_thread);
00540 
00541 #ifndef NDEBUG
00542   bool all_is_valid = true;
00543 #endif
00544   Primitives::iterator pi;
00545   for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
00546     CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->reverse();
00547     (*pi) = (GeomPrimitive *)new_prim.p();
00548 
00549 #ifndef NDEBUG
00550     if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
00551       all_is_valid = false;
00552     }
00553 #endif
00554   }
00555 
00556   cdata->_modified = Geom::get_next_modified();
00557   reset_geom_rendering(cdata);
00558   clear_cache_stage(current_thread);
00559 
00560   nassertv(all_is_valid);
00561 }
00562 
00563 ////////////////////////////////////////////////////////////////////
00564 //     Function: Geom::rotate_in_place
00565 //       Access: Published
00566 //  Description: Rotates all of the primitives within this Geom,
00567 //               leaving the results in place.  See
00568 //               GeomPrimitive::rotate().
00569 //
00570 //               Don't call this in a downstream thread unless you
00571 //               don't mind it blowing away other changes you might
00572 //               have recently made in an upstream thread.
00573 ////////////////////////////////////////////////////////////////////
00574 void Geom::
00575 rotate_in_place() {
00576   Thread *current_thread = Thread::get_current_thread();
00577   CDWriter cdata(_cycler, true, current_thread);
00578 
00579 #ifndef NDEBUG
00580   bool all_is_valid = true;
00581 #endif
00582   Primitives::iterator pi;
00583   for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
00584     CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->rotate();
00585     (*pi) = (GeomPrimitive *)new_prim.p();
00586 
00587 #ifndef NDEBUG
00588     if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
00589       all_is_valid = false;
00590     }
00591 #endif
00592   }
00593 
00594   cdata->_modified = Geom::get_next_modified();
00595   clear_cache_stage(current_thread);
00596 
00597   nassertv(all_is_valid);
00598 }
00599 
00600 ////////////////////////////////////////////////////////////////////
00601 //     Function: Geom::unify_in_place
00602 //       Access: Published
00603 //  Description: Unifies all of the primitives contained within this
00604 //               Geom into a single (or as few as possible, within the
00605 //               constraints of max_indices) primitive objects.  This
00606 //               may require decomposing the primitives if, for
00607 //               instance, the Geom contains both triangle strips and
00608 //               triangle fans.
00609 //
00610 //               max_indices represents the maximum number of indices
00611 //               that will be put in any one GeomPrimitive.  If
00612 //               preserve_order is true, then the primitives will not
00613 //               be reordered during the operation, even if this
00614 //               results in a suboptimal result.
00615 //
00616 //               Don't call this in a downstream thread unless you
00617 //               don't mind it blowing away other changes you might
00618 //               have recently made in an upstream thread.
00619 ////////////////////////////////////////////////////////////////////
00620 void Geom::
00621 unify_in_place(int max_indices, bool preserve_order) {
00622   if (gobj_cat.is_debug()) {
00623     gobj_cat.debug()
00624       << "unify_in_place(" << max_indices << ", " << preserve_order
00625       << "): " << *this << "\n";
00626   }
00627 
00628   Thread *current_thread = Thread::get_current_thread();
00629   if (get_num_primitives() <= 1) {
00630     // If we don't have more than one primitive to start with, no need
00631     // to do anything.
00632     return;
00633   }
00634 
00635   CDWriter cdata(_cycler, true, current_thread);
00636 
00637   typedef pmap<TypeHandle, PT(GeomPrimitive) > NewPrims;
00638 
00639   NewPrims new_prims;
00640 
00641   bool keep_different_types = preserve_triangle_strips && !preserve_order;
00642 
00643   Primitives::const_iterator pi;
00644   for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
00645     CPT(GeomPrimitive) primitive = (*pi).get_read_pointer();
00646     NewPrims::iterator npi = new_prims.find(primitive->get_type());
00647     if (npi == new_prims.end()) {
00648       // This is the first primitive of this type.
00649       if (!keep_different_types && !new_prims.empty()) {
00650         // Actually, since we aren't trying to keep the different
00651         // types of primitives, we should try to combine this type and
00652         // the other type by decomposing them both (into triangles,
00653         // segments, or whatever).
00654 
00655         // First, decompose the incoming one.
00656         primitive = primitive->decompose();
00657         npi = new_prims.find(primitive->get_type());
00658         if (npi == new_prims.end()) {
00659           // That didn't help, so decompose the one already in the
00660           // table.
00661           nassertv(new_prims.size() == 1);
00662           npi = new_prims.begin();
00663           CPT(GeomPrimitive) np = (*npi).second->decompose();
00664           new_prims.clear();
00665           new_prims.insert(NewPrims::value_type(np->get_type(), np->make_copy()));
00666           npi = new_prims.find(primitive->get_type());
00667         }
00668       }
00669     }
00670 
00671     if (npi == new_prims.end()) {
00672       // This is the first primitive of this type.  Just store it.
00673       new_prims.insert(NewPrims::value_type(primitive->get_type(), primitive->make_copy()));
00674 
00675     } else {
00676       // We have already encountered another primitive of this type.
00677       // Combine them.
00678       combine_primitives((*npi).second, primitive, current_thread);
00679     }
00680   }
00681 
00682   // Now, we have one or more primitives, but only one of each type.
00683 #ifndef NDEBUG
00684   if (!keep_different_types && new_prims.size() > 1) {
00685     // This shouldn't be possible, because we decompose as we go, in
00686     // the loop above.  (We have to decompose as we go to preserve the
00687     // ordering of the primitives.)
00688     nassertv(false);
00689   }
00690 #endif
00691 
00692   // Finally, iterate through the remaining primitives, and copy them
00693   // to the output list.
00694   cdata->_primitives.clear();
00695   NewPrims::iterator npi;
00696   for (npi = new_prims.begin(); npi != new_prims.end(); ++npi) {
00697     GeomPrimitive *prim = (*npi).second;
00698 
00699     nassertv(prim->check_valid(cdata->_data.get_read_pointer()));
00700 
00701     // Each new primitive, naturally, inherits the Geom's overall
00702     // shade model.
00703     prim->set_shade_model(cdata->_shade_model);
00704 
00705     // Should we split it up again to satisfy max_indices?
00706     if (prim->get_num_vertices() > max_indices) {
00707       // Copy prim into smaller prims, no one of which has more than
00708       // max_indices vertices.
00709       int i = 0;
00710       
00711       while (i < prim->get_num_primitives()) {
00712         PT(GeomPrimitive) smaller = prim->make_copy();
00713         smaller->clear_vertices();
00714         while (i < prim->get_num_primitives() && 
00715                smaller->get_num_vertices() + prim->get_primitive_num_vertices(i) < max_indices) {
00716           int start = prim->get_primitive_start(i);
00717           int end = prim->get_primitive_end(i);
00718           for (int n = start; n < end; ++n) {
00719             smaller->add_vertex(prim->get_vertex(n));
00720           }
00721           smaller->close_primitive();
00722           
00723           ++i;
00724         }
00725       
00726         cdata->_primitives.push_back(smaller.p());
00727       }
00728       
00729     } else {
00730       // The prim has few enough vertices; keep it.
00731       cdata->_primitives.push_back(prim);
00732     }
00733   }
00734 
00735   cdata->_modified = Geom::get_next_modified();
00736   clear_cache_stage(current_thread);
00737   reset_geom_rendering(cdata);
00738 }
00739 
00740 ////////////////////////////////////////////////////////////////////
00741 //     Function: Geom::make_points_in_place
00742 //       Access: Published
00743 //  Description: Replaces the GeomPrimitives within this Geom with
00744 //               corresponding GeomPoints.  See
00745 //               GeomPrimitive::make_points().
00746 //
00747 //               Don't call this in a downstream thread unless you
00748 //               don't mind it blowing away other changes you might
00749 //               have recently made in an upstream thread.
00750 ////////////////////////////////////////////////////////////////////
00751 void Geom::
00752 make_points_in_place() {
00753   Thread *current_thread = Thread::get_current_thread();
00754   CDWriter cdata(_cycler, true, current_thread);
00755 
00756 #ifndef NDEBUG
00757   bool all_is_valid = true;
00758 #endif
00759   Primitives::iterator pi;
00760   for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
00761     CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->make_points();
00762     (*pi) = (GeomPrimitive *)new_prim.p();
00763 
00764 #ifndef NDEBUG
00765     if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
00766       all_is_valid = false;
00767     }
00768 #endif
00769   }
00770 
00771   cdata->_modified = Geom::get_next_modified();
00772   reset_geom_rendering(cdata);
00773   clear_cache_stage(current_thread);
00774 
00775   nassertv(all_is_valid);
00776 }
00777 
00778 
00779 ////////////////////////////////////////////////////////////////////
00780 //     Function: Geom::copy_primitives_from
00781 //       Access: Published, Virtual
00782 //  Description: Copies the primitives from the indicated Geom into
00783 //               this one.  This does require that both Geoms contain
00784 //               the same fundamental type primitives, both have a
00785 //               compatible shade model, and both use the same
00786 //               GeomVertexData.  Both Geoms must also be the same
00787 //               specific class type (i.e. if one is a GeomTextGlyph,
00788 //               they both must be.)
00789 //
00790 //               Returns true if the copy is successful, or false
00791 //               otherwise (because the Geoms were mismatched).
00792 ////////////////////////////////////////////////////////////////////
00793 bool Geom::
00794 copy_primitives_from(const Geom *other) {
00795   if (get_primitive_type() != PT_none &&
00796       other->get_primitive_type() != get_primitive_type()) {
00797     return false;
00798   }
00799   if (get_vertex_data() != other->get_vertex_data()) {
00800     return false;
00801   }
00802   if (get_type() != other->get_type()) {
00803     return false;
00804   }
00805 
00806   ShadeModel this_shade_model = get_shade_model();
00807   ShadeModel other_shade_model = other->get_shade_model();
00808   if (this_shade_model != SM_uniform && other_shade_model != SM_uniform &&
00809       this_shade_model != other_shade_model) {
00810     if ((this_shade_model == SM_flat_first_vertex && other_shade_model == SM_flat_last_vertex) ||
00811         (this_shade_model == SM_flat_last_vertex && other_shade_model == SM_flat_first_vertex)) {
00812       // This is acceptable; we can rotate the primitives to match.
00813 
00814     } else {
00815       // Otherwise, we have incompatible shade models.
00816       return false;
00817     }
00818   }
00819 
00820   int num_primitives = other->get_num_primitives();
00821   for (int i = 0; i < num_primitives; i++) {
00822     add_primitive(other->get_primitive(i));
00823   }
00824 
00825   return true;
00826 }
00827 
00828 ////////////////////////////////////////////////////////////////////
00829 //     Function: Geom::get_num_bytes
00830 //       Access: Published
00831 //  Description: Returns the number of bytes consumed by the geom and
00832 //               its primitives (but not including its vertex table).
00833 ////////////////////////////////////////////////////////////////////
00834 int Geom::
00835 get_num_bytes() const {
00836   CDReader cdata(_cycler);
00837 
00838   int num_bytes = sizeof(Geom);
00839   Primitives::const_iterator pi;
00840   for (pi = cdata->_primitives.begin(); 
00841        pi != cdata->_primitives.end();
00842        ++pi) {
00843     num_bytes += (*pi).get_read_pointer()->get_num_bytes();
00844   }
00845 
00846   return num_bytes;
00847 }
00848 
00849 ////////////////////////////////////////////////////////////////////
00850 //     Function: Geom::request_resident
00851 //       Access: Published
00852 //  Description: Returns true if all the primitive arrays are
00853 //               currently resident in memory.  If this returns false,
00854 //               the data will be brought back into memory shortly;
00855 //               try again later.
00856 //
00857 //               This does not also test the Geom's associated
00858 //               GeomVertexData.  That must be tested separately.
00859 ////////////////////////////////////////////////////////////////////
00860 bool Geom::
00861 request_resident() const {
00862   CDReader cdata(_cycler);
00863 
00864   bool resident = true;
00865 
00866   Primitives::const_iterator pi;
00867   for (pi = cdata->_primitives.begin(); 
00868        pi != cdata->_primitives.end();
00869        ++pi) {
00870     if (!(*pi).get_read_pointer()->request_resident()) {
00871       resident = false;
00872     }
00873   }
00874 
00875   return resident;
00876 }
00877 
00878 ////////////////////////////////////////////////////////////////////
00879 //     Function: Geom::transform_vertices
00880 //       Access: Published
00881 //  Description: Applies the indicated transform to all of the
00882 //               vertices in the Geom.  If the Geom happens to share a
00883 //               vertex table with another Geom, this operation will
00884 //               duplicate the vertex table instead of breaking the
00885 //               other Geom; however, if multiple Geoms with shared
00886 //               tables are transformed by the same matrix, they will
00887 //               no longer share tables after the operation.  Consider
00888 //               using the GeomTransformer if you will be applying the
00889 //               same transform to multiple Geoms.
00890 ////////////////////////////////////////////////////////////////////
00891 void Geom::
00892 transform_vertices(const LMatrix4 &mat) {
00893   PT(GeomVertexData) new_data = modify_vertex_data();
00894   CPT(GeomVertexFormat) format = new_data->get_format();
00895   
00896   int ci;
00897   for (ci = 0; ci < format->get_num_points(); ci++) {
00898     GeomVertexRewriter data(new_data, format->get_point(ci));
00899     
00900     while (!data.is_at_end()) {
00901       const LPoint3 &point = data.get_data3();
00902       data.set_data3(point * mat);
00903     }
00904   }
00905   for (ci = 0; ci < format->get_num_vectors(); ci++) {
00906     GeomVertexRewriter data(new_data, format->get_vector(ci));
00907     
00908     while (!data.is_at_end()) {
00909       const LVector3 &vector = data.get_data3();
00910       data.set_data3(normalize(vector * mat));
00911     }
00912   }
00913 }
00914 
00915 ////////////////////////////////////////////////////////////////////
00916 //     Function: Geom::check_valid
00917 //       Access: Published
00918 //  Description: Verifies that the all of the primitives within the
00919 //               geom reference vertices that actually exist within
00920 //               the geom's GeomVertexData.  Returns true if the geom
00921 //               appears to be valid, false otherwise.
00922 ////////////////////////////////////////////////////////////////////
00923 bool Geom::
00924 check_valid() const {
00925   Thread *current_thread = Thread::get_current_thread();
00926   GeomPipelineReader geom_reader(this, current_thread);
00927   GeomVertexDataPipelineReader data_reader(geom_reader.get_vertex_data(), current_thread);
00928   data_reader.check_array_readers();
00929   return geom_reader.check_valid(&data_reader);
00930 }
00931 
00932 ////////////////////////////////////////////////////////////////////
00933 //     Function: Geom::check_valid
00934 //       Access: Published
00935 //  Description: Verifies that the all of the primitives within the
00936 //               geom reference vertices that actually exist within
00937 //               the indicated GeomVertexData.  Returns true if the
00938 //               geom appears to be valid, false otherwise.
00939 ////////////////////////////////////////////////////////////////////
00940 bool Geom::
00941 check_valid(const GeomVertexData *vertex_data) const {
00942   Thread *current_thread = Thread::get_current_thread();
00943   GeomPipelineReader geom_reader(this, current_thread);
00944   GeomVertexDataPipelineReader data_reader(vertex_data, current_thread);
00945   data_reader.check_array_readers();
00946   return geom_reader.check_valid(&data_reader);
00947 }
00948 
00949 ////////////////////////////////////////////////////////////////////
00950 //     Function: Geom::get_bounds
00951 //       Access: Published
00952 //  Description: Returns the bounding volume for the Geom.
00953 ////////////////////////////////////////////////////////////////////
00954 CPT(BoundingVolume) Geom::
00955 get_bounds(Thread *current_thread) const {
00956   CDLockedReader cdata(_cycler, current_thread);
00957   if (cdata->_user_bounds != (BoundingVolume *)NULL) {
00958     return cdata->_user_bounds;
00959   }
00960 
00961   if (cdata->_internal_bounds_stale) {
00962     CDWriter cdataw(((Geom *)this)->_cycler, cdata, false);
00963     compute_internal_bounds(cdataw, current_thread);
00964     return cdataw->_internal_bounds;
00965   }
00966   return cdata->_internal_bounds;
00967 }
00968 
00969 ////////////////////////////////////////////////////////////////////
00970 //     Function: Geom::get_nested_vertices
00971 //       Access: Published
00972 //  Description: Returns the number of vertices rendered by all
00973 //               primitives within the Geom.
00974 ////////////////////////////////////////////////////////////////////
00975 int Geom::
00976 get_nested_vertices(Thread *current_thread) const {
00977   CDLockedReader cdata(_cycler, current_thread);
00978   if (cdata->_internal_bounds_stale) {
00979     CDWriter cdataw(((Geom *)this)->_cycler, cdata, false);
00980     compute_internal_bounds(cdataw, current_thread);
00981     return cdataw->_nested_vertices;
00982   }
00983   return cdata->_nested_vertices;
00984 }
00985 
00986 ////////////////////////////////////////////////////////////////////
00987 //     Function: Geom::output
00988 //       Access: Published, Virtual
00989 //  Description: 
00990 ////////////////////////////////////////////////////////////////////
00991 void Geom::
00992 output(ostream &out) const {
00993   CDReader cdata(_cycler);
00994 
00995   // Get a list of the primitive types contained within this object.
00996   int num_faces = 0;
00997   pset<TypeHandle> types;
00998   Primitives::const_iterator pi;
00999   for (pi = cdata->_primitives.begin(); 
01000        pi != cdata->_primitives.end();
01001        ++pi) {
01002     CPT(GeomPrimitive) prim = (*pi).get_read_pointer();
01003     num_faces += prim->get_num_faces();
01004     types.insert(prim->get_type());
01005   }
01006 
01007   out << get_type() << " [";
01008   pset<TypeHandle>::iterator ti;
01009   for (ti = types.begin(); ti != types.end(); ++ti) {
01010     out << " " << (*ti);
01011   }
01012   out << " ], " << num_faces << " faces";
01013 }
01014 
01015 ////////////////////////////////////////////////////////////////////
01016 //     Function: Geom::write
01017 //       Access: Published, Virtual
01018 //  Description: 
01019 ////////////////////////////////////////////////////////////////////
01020 void Geom::
01021 write(ostream &out, int indent_level) const {
01022   CDReader cdata(_cycler);
01023 
01024   // Get a list of the primitive types contained within this object.
01025   Primitives::const_iterator pi;
01026   for (pi = cdata->_primitives.begin(); 
01027        pi != cdata->_primitives.end();
01028        ++pi) {
01029     (*pi).get_read_pointer()->write(out, indent_level);
01030   }
01031 }
01032 
01033 ////////////////////////////////////////////////////////////////////
01034 //     Function: Geom::clear_cache
01035 //       Access: Published
01036 //  Description: Removes all of the previously-cached results of
01037 //               munge_geom().
01038 //
01039 //               This blows away the entire cache, upstream and
01040 //               downstream the pipeline.  Use clear_cache_stage()
01041 //               instead if you only want to blow away the cache at
01042 //               the current stage and upstream.
01043 ////////////////////////////////////////////////////////////////////
01044 void Geom::
01045 clear_cache() {
01046   LightMutexHolder holder(_cache_lock);
01047   for (Cache::iterator ci = _cache.begin();
01048        ci != _cache.end();
01049        ++ci) {
01050     CacheEntry *entry = (*ci).second;
01051     entry->erase();
01052   }
01053   _cache.clear();
01054 }
01055 
01056 ////////////////////////////////////////////////////////////////////
01057 //     Function: Geom::clear_cache_stage
01058 //       Access: Published
01059 //  Description: Removes all of the previously-cached results of
01060 //               munge_geom(), at the current pipeline stage and
01061 //               upstream.  Does not affect the downstream cache.
01062 //
01063 //               Don't call this in a downstream thread unless you
01064 //               don't mind it blowing away other changes you might
01065 //               have recently made in an upstream thread.
01066 ////////////////////////////////////////////////////////////////////
01067 void Geom::
01068 clear_cache_stage(Thread *current_thread) {
01069   LightMutexHolder holder(_cache_lock);
01070   for (Cache::iterator ci = _cache.begin();
01071        ci != _cache.end();
01072        ++ci) {
01073     CacheEntry *entry = (*ci).second;
01074     CDCacheWriter cdata(entry->_cycler, current_thread);
01075     cdata->set_result(NULL, NULL);
01076   }
01077 }
01078 
01079 ////////////////////////////////////////////////////////////////////
01080 //     Function: Geom::prepare
01081 //       Access: Published
01082 //  Description: Indicates that the geom should be enqueued to be
01083 //               prepared in the indicated prepared_objects at the
01084 //               beginning of the next frame.  This will ensure the
01085 //               geom is already loaded into geom memory if it
01086 //               is expected to be rendered soon.
01087 //
01088 //               Use this function instead of prepare_now() to preload
01089 //               geoms from a user interface standpoint.
01090 ////////////////////////////////////////////////////////////////////
01091 void Geom::
01092 prepare(PreparedGraphicsObjects *prepared_objects) {
01093   prepared_objects->enqueue_geom(this);
01094 }
01095 
01096 ////////////////////////////////////////////////////////////////////
01097 //     Function: Geom::is_prepared
01098 //       Access: Published
01099 //  Description: Returns true if the geom has already been prepared
01100 //               or enqueued for preparation on the indicated GSG,
01101 //               false otherwise.
01102 ////////////////////////////////////////////////////////////////////
01103 bool Geom::
01104 is_prepared(PreparedGraphicsObjects *prepared_objects) const {
01105   Contexts::const_iterator ci;
01106   ci = _contexts.find(prepared_objects);
01107   if (ci != _contexts.end()) {
01108     return true;
01109   }
01110   return prepared_objects->is_geom_queued(this);
01111 }
01112 
01113 ////////////////////////////////////////////////////////////////////
01114 //     Function: Geom::release
01115 //       Access: Published
01116 //  Description: Frees the geom context only on the indicated object,
01117 //               if it exists there.  Returns true if it was released,
01118 //               false if it had not been prepared.
01119 ////////////////////////////////////////////////////////////////////
01120 bool Geom::
01121 release(PreparedGraphicsObjects *prepared_objects) {
01122   Contexts::iterator ci;
01123   ci = _contexts.find(prepared_objects);
01124   if (ci != _contexts.end()) {
01125     GeomContext *gc = (*ci).second;
01126     prepared_objects->release_geom(gc);
01127     return true;
01128   }
01129 
01130   // Maybe it wasn't prepared yet, but it's about to be.
01131   return prepared_objects->dequeue_geom(this);
01132 }
01133 
01134 ////////////////////////////////////////////////////////////////////
01135 //     Function: Geom::release_all
01136 //       Access: Published
01137 //  Description: Frees the context allocated on all objects for which
01138 //               the geom has been declared.  Returns the number of
01139 //               contexts which have been freed.
01140 ////////////////////////////////////////////////////////////////////
01141 int Geom::
01142 release_all() {
01143   // We have to traverse a copy of the _contexts list, because the
01144   // PreparedGraphicsObjects object will call clear_prepared() in response
01145   // to each release_geom(), and we don't want to be modifying the
01146   // _contexts list while we're traversing it.
01147   Contexts temp = _contexts;
01148   int num_freed = (int)_contexts.size();
01149 
01150   Contexts::const_iterator ci;
01151   for (ci = temp.begin(); ci != temp.end(); ++ci) {
01152     PreparedGraphicsObjects *prepared_objects = (*ci).first;
01153     GeomContext *gc = (*ci).second;
01154     prepared_objects->release_geom(gc);
01155   }
01156 
01157   // Now that we've called release_geom() on every known context,
01158   // the _contexts list should have completely emptied itself.
01159   nassertr(_contexts.empty(), num_freed);
01160 
01161   return num_freed;
01162 }
01163 
01164 ////////////////////////////////////////////////////////////////////
01165 //     Function: Geom::prepare_now
01166 //       Access: Public
01167 //  Description: Creates a context for the geom on the particular
01168 //               GSG, if it does not already exist.  Returns the new
01169 //               (or old) GeomContext.  This assumes that the
01170 //               GraphicsStateGuardian is the currently active
01171 //               rendering context and that it is ready to accept new
01172 //               geoms.  If this is not necessarily the case, you
01173 //               should use prepare() instead.
01174 //
01175 //               Normally, this is not called directly except by the
01176 //               GraphicsStateGuardian; a geom does not need to be
01177 //               explicitly prepared by the user before it may be
01178 //               rendered.
01179 ////////////////////////////////////////////////////////////////////
01180 GeomContext *Geom::
01181 prepare_now(PreparedGraphicsObjects *prepared_objects, 
01182             GraphicsStateGuardianBase *gsg) {
01183   Contexts::const_iterator ci;
01184   ci = _contexts.find(prepared_objects);
01185   if (ci != _contexts.end()) {
01186     return (*ci).second;
01187   }
01188 
01189   GeomContext *gc = prepared_objects->prepare_geom_now(this, gsg);
01190   if (gc != (GeomContext *)NULL) {
01191     _contexts[prepared_objects] = gc;
01192   }
01193   return gc;
01194 }
01195 
01196 ////////////////////////////////////////////////////////////////////
01197 //     Function: Geom::draw
01198 //       Access: Public
01199 //  Description: Actually draws the Geom with the indicated GSG, using
01200 //               the indicated vertex data (which might have been
01201 //               pre-munged to support the GSG's needs).
01202 //
01203 //               Returns true if all of the primitives were drawn
01204 //               normally, false if there was a problem (for instance,
01205 //               some of the data was nonresident).  If force is
01206 //               passed true, it will wait for the data to become
01207 //               resident if necessary.
01208 ////////////////////////////////////////////////////////////////////
01209 bool Geom::
01210 draw(GraphicsStateGuardianBase *gsg, const GeomMunger *munger,
01211      const GeomVertexData *vertex_data, bool force,
01212      Thread *current_thread) const {
01213   GeomPipelineReader geom_reader(this, current_thread);
01214   geom_reader.check_usage_hint();
01215 
01216   GeomVertexDataPipelineReader data_reader(vertex_data, current_thread);
01217   data_reader.check_array_readers();
01218 
01219   return geom_reader.draw(gsg, munger, &data_reader, force);
01220 }
01221 
01222 ////////////////////////////////////////////////////////////////////
01223 //     Function: Geom::get_next_modified
01224 //       Access: Public, Static
01225 //  Description: Returns a monotonically increasing sequence.  Each
01226 //               time this is called, a new sequence number is
01227 //               returned, higher than the previous value.
01228 //
01229 //               This is used to ensure that
01230 //               GeomVertexArrayData::get_modified() and
01231 //               GeomPrimitive::get_modified() update from the same
01232 //               space, so that Geom::get_modified() returns a
01233 //               meaningful value.
01234 ////////////////////////////////////////////////////////////////////
01235 UpdateSeq Geom::
01236 get_next_modified() {
01237   ++_next_modified;
01238   return _next_modified;
01239 }
01240 
01241 ////////////////////////////////////////////////////////////////////
01242 //     Function: Geom::compute_internal_bounds
01243 //       Access: Private
01244 //  Description: Recomputes the dynamic bounding volume for this Geom.
01245 //               This includes all of the vertices.
01246 ////////////////////////////////////////////////////////////////////
01247 void Geom::
01248 compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const {
01249   int num_vertices = 0;
01250 
01251   // Get the vertex data, after animation.
01252   CPT(GeomVertexData) vertex_data = cdata->_data.get_read_pointer();
01253   vertex_data = vertex_data->animate_vertices(true, current_thread);
01254 
01255   // Now actually compute the bounding volume.  We do this by using
01256   // calc_tight_bounds to determine our box first.
01257   LPoint3 min, max;
01258   bool found_any = false;
01259   do_calc_tight_bounds(min, max, found_any, vertex_data,
01260                        false, LMatrix4::ident_mat(), 
01261                        InternalName::get_vertex(),
01262                        cdata, current_thread);
01263 
01264   BoundingVolume::BoundsType btype = cdata->_bounds_type;
01265   if (btype == BoundingVolume::BT_default) {
01266     btype = bounds_type;
01267   }
01268 
01269   if (found_any) {
01270     // Then we put the bounding volume around both of those points.
01271     if (btype == BoundingVolume::BT_sphere) {
01272       // The user specifically requested a BoundingSphere, so oblige.
01273       BoundingBox box(min, max);
01274       box.local_object();
01275 
01276       PT(BoundingSphere) sphere = new BoundingSphere;
01277       sphere->extend_by(&box);
01278       cdata->_internal_bounds = sphere;
01279 
01280     } else {
01281       // The user requested a BoundingBox, or did not specify.
01282       cdata->_internal_bounds = new BoundingBox(min, max);
01283     }
01284 
01285     Primitives::const_iterator pi;
01286     for (pi = cdata->_primitives.begin(); 
01287          pi != cdata->_primitives.end();
01288          ++pi) {
01289       CPT(GeomPrimitive) prim = (*pi).get_read_pointer();
01290       num_vertices += prim->get_num_vertices();
01291     }
01292 
01293   } else {
01294     // No points; empty bounding volume.
01295     if (btype == BoundingVolume::BT_sphere) {
01296       cdata->_internal_bounds = new BoundingSphere;
01297     } else {
01298       cdata->_internal_bounds = new BoundingBox;
01299     }
01300   }
01301 
01302   cdata->_nested_vertices = num_vertices;
01303   cdata->_internal_bounds_stale = false;
01304 }
01305 
01306 ////////////////////////////////////////////////////////////////////
01307 //     Function: Geom::do_calc_tight_bounds
01308 //       Access: Private
01309 //  Description: The private implementation of calc_tight_bounds().
01310 ////////////////////////////////////////////////////////////////////
01311 void Geom::
01312 do_calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
01313                      bool &found_any, 
01314                      const GeomVertexData *vertex_data,
01315                      bool got_mat, const LMatrix4 &mat,
01316                      const InternalName *column_name,
01317                      const CData *cdata, Thread *current_thread) const {
01318   Primitives::const_iterator pi;
01319   for (pi = cdata->_primitives.begin(); 
01320        pi != cdata->_primitives.end();
01321        ++pi) {
01322     CPT(GeomPrimitive) prim = (*pi).get_read_pointer();
01323     prim->calc_tight_bounds(min_point, max_point, found_any, vertex_data,
01324                             got_mat, mat, column_name, current_thread);
01325   }
01326 }
01327 
01328 ////////////////////////////////////////////////////////////////////
01329 //     Function: Geom::clear_prepared
01330 //       Access: Private
01331 //  Description: Removes the indicated PreparedGraphicsObjects table
01332 //               from the Geom's table, without actually releasing
01333 //               the geom.  This is intended to be called only from
01334 //               PreparedGraphicsObjects::release_geom(); it should
01335 //               never be called by user code.
01336 ////////////////////////////////////////////////////////////////////
01337 void Geom::
01338 clear_prepared(PreparedGraphicsObjects *prepared_objects) {
01339   Contexts::iterator ci;
01340   ci = _contexts.find(prepared_objects);
01341   if (ci != _contexts.end()) {
01342     _contexts.erase(ci);
01343   } else {
01344     // If this assertion fails, clear_prepared() was given a
01345     // prepared_objects that the geom didn't know about.
01346     nassertv(false);
01347   }
01348 }
01349 
01350 ////////////////////////////////////////////////////////////////////
01351 //     Function: Geom::check_will_be_valid
01352 //       Access: Private
01353 //  Description: Verifies that the all of the primitives within the
01354 //               geom reference vertices that actually exist within
01355 //               the indicated GeomVertexData (presumably in
01356 //               preparation for assigning the geom to use this data).
01357 //               Returns true if the data appears to be valid, false
01358 //               otherwise.
01359 ////////////////////////////////////////////////////////////////////
01360 bool Geom::
01361 check_will_be_valid(const GeomVertexData *vertex_data) const {
01362   CDReader cdata(_cycler);
01363 
01364   Primitives::const_iterator pi;
01365   for (pi = cdata->_primitives.begin(); 
01366        pi != cdata->_primitives.end();
01367        ++pi) {
01368     if (!(*pi).get_read_pointer()->check_valid(vertex_data)) {
01369       return false;
01370     }
01371   }
01372 
01373   return true;
01374 }
01375 
01376 ////////////////////////////////////////////////////////////////////
01377 //     Function: Geom::reset_usage_hint
01378 //       Access: Private
01379 //  Description: Recomputes the minimum usage_hint.
01380 ////////////////////////////////////////////////////////////////////
01381 void Geom::
01382 reset_usage_hint(Geom::CData *cdata) {
01383   cdata->_usage_hint = UH_unspecified;
01384   Primitives::const_iterator pi;
01385   for (pi = cdata->_primitives.begin(); 
01386        pi != cdata->_primitives.end();
01387        ++pi) {
01388     cdata->_usage_hint = min(cdata->_usage_hint, 
01389                              (*pi).get_read_pointer()->get_usage_hint());
01390   }
01391   cdata->_got_usage_hint = true;
01392 }
01393 
01394 ////////////////////////////////////////////////////////////////////
01395 //     Function: Geom::reset_geom_rendering
01396 //       Access: Private
01397 //  Description: Rederives the _geom_rendering member.
01398 ////////////////////////////////////////////////////////////////////
01399 void Geom::
01400 reset_geom_rendering(Geom::CData *cdata) {
01401   cdata->_geom_rendering = 0;
01402   Primitives::const_iterator pi;
01403   for (pi = cdata->_primitives.begin(); 
01404        pi != cdata->_primitives.end();
01405        ++pi) {
01406     cdata->_geom_rendering |= (*pi).get_read_pointer()->get_geom_rendering();
01407   }
01408 
01409   if ((cdata->_geom_rendering & GR_point) != 0) {
01410     CPT(GeomVertexData) data = cdata->_data.get_read_pointer();
01411     if (data->has_column(InternalName::get_size())) {
01412       cdata->_geom_rendering |= GR_per_point_size;
01413     }
01414     if (data->has_column(InternalName::get_aspect_ratio())) {
01415       cdata->_geom_rendering |= GR_point_aspect_ratio;
01416     }
01417     if (data->has_column(InternalName::get_rotate())) {
01418       cdata->_geom_rendering |= GR_point_rotate;
01419     }
01420   }
01421 
01422   switch (get_shade_model()) {
01423   case SM_flat_first_vertex:
01424     cdata->_geom_rendering |= GR_flat_first_vertex;
01425     break;
01426 
01427   case SM_flat_last_vertex:
01428     cdata->_geom_rendering |= GR_flat_last_vertex;
01429     break;
01430 
01431   default:
01432     break;
01433   }
01434 }
01435 
01436 ////////////////////////////////////////////////////////////////////
01437 //     Function: Geom::combine_primitives
01438 //       Access: Private
01439 //  Description: Combines two primitives of the same type into a
01440 //               single primitive.  a_prim is modified to append the
01441 //               vertices from b_prim, which is unmodified.
01442 ////////////////////////////////////////////////////////////////////
01443 void Geom::
01444 combine_primitives(GeomPrimitive *a_prim, const GeomPrimitive *b_prim,
01445                    Thread *current_thread) {
01446   nassertv(a_prim != b_prim);
01447   nassertv(a_prim->get_type() == b_prim->get_type());
01448 
01449   CPT(GeomPrimitive) b_prim2 = b_prim;
01450 
01451   if (a_prim->get_index_type() != b_prim2->get_index_type()) {
01452     GeomPrimitive::NumericType index_type = max(a_prim->get_index_type(), b_prim2->get_index_type());
01453     a_prim->set_index_type(index_type);
01454     if (b_prim2->get_index_type() != index_type) {
01455       PT(GeomPrimitive) b_prim_copy = b_prim2->make_copy();
01456       b_prim_copy->set_index_type(index_type);
01457       b_prim2 = b_prim_copy;
01458     }
01459   }
01460 
01461   if (!b_prim2->is_indexed()) {
01462     PT(GeomPrimitive) b_prim_copy = b_prim2->make_copy();
01463     b_prim_copy->make_indexed();
01464     b_prim2 = b_prim_copy;
01465   }
01466 
01467   PT(GeomVertexArrayData) a_vertices = a_prim->modify_vertices();
01468   CPT(GeomVertexArrayData) b_vertices = b_prim2->get_vertices();
01469 
01470   if (a_prim->requires_unused_vertices()) {
01471     GeomVertexReader index(b_vertices, 0);
01472     int b_vertex = index.get_data1i();
01473     a_prim->append_unused_vertices(a_vertices, b_vertex);
01474   }
01475 
01476   PT(GeomVertexArrayDataHandle) a_handle = a_vertices->modify_handle(current_thread);
01477   CPT(GeomVertexArrayDataHandle) b_handle = b_vertices->get_handle(current_thread);
01478 
01479   size_t orig_a_vertices = a_handle->get_num_rows();
01480 
01481   a_handle->copy_subdata_from(a_handle->get_data_size_bytes(), 0,
01482                               b_handle, 0, b_handle->get_data_size_bytes());
01483   a_prim->clear_minmax();
01484   if (a_prim->is_composite()) {
01485     // Also copy the ends array.
01486     PTA_int a_ends = a_prim->modify_ends();
01487     CPTA_int b_ends = b_prim2->get_ends();
01488     for (size_t i = 0; i < b_ends.size(); ++i) {
01489       a_ends.push_back(b_ends[i] + orig_a_vertices);
01490     }
01491   }
01492 }
01493 
01494 ////////////////////////////////////////////////////////////////////
01495 //     Function: Geom::register_with_read_factory
01496 //       Access: Public, Static
01497 //  Description: Tells the BamReader how to create objects of type
01498 //               Geom.
01499 ////////////////////////////////////////////////////////////////////
01500 void Geom::
01501 register_with_read_factory() {
01502   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
01503 }
01504 
01505 ////////////////////////////////////////////////////////////////////
01506 //     Function: Geom::write_datagram
01507 //       Access: Public, Virtual
01508 //  Description: Writes the contents of this object to the datagram
01509 //               for shipping out to a Bam file.
01510 ////////////////////////////////////////////////////////////////////
01511 void Geom::
01512 write_datagram(BamWriter *manager, Datagram &dg) {
01513   TypedWritable::write_datagram(manager, dg);
01514 
01515   manager->write_cdata(dg, _cycler);
01516 }
01517 
01518 ////////////////////////////////////////////////////////////////////
01519 //     Function: Geom::make_from_bam
01520 //       Access: Protected, Static
01521 //  Description: This function is called by the BamReader's factory
01522 //               when a new object of type Geom is encountered
01523 //               in the Bam file.  It should create the Geom
01524 //               and extract its information from the file.
01525 ////////////////////////////////////////////////////////////////////
01526 TypedWritable *Geom::
01527 make_from_bam(const FactoryParams &params) {
01528   Geom *object = new Geom(NULL);
01529   DatagramIterator scan;
01530   BamReader *manager;
01531 
01532   parse_params(params, scan, manager);
01533   object->fillin(scan, manager);
01534   manager->register_finalize(object);
01535 
01536   return object;
01537 }
01538 
01539 ////////////////////////////////////////////////////////////////////
01540 //     Function: Geom::finalize
01541 //       Access: Public, Virtual
01542 //  Description: Called by the BamReader to perform any final actions
01543 //               needed for setting up the object after all objects
01544 //               have been read and all pointers have been completed.
01545 ////////////////////////////////////////////////////////////////////
01546 void Geom::
01547 finalize(BamReader *manager) {
01548   CDWriter cdata(_cycler, true);
01549 
01550   // Make sure our GeomVertexData is finalized first.  This may result
01551   // in the data getting finalized multiple times, but it doesn't mind
01552   // that.
01553   if (!cdata->_data.is_null()) {
01554     // We shouldn't call get_write_pointer(), which might replicate
01555     // the GeomVertexData unnecessarily.
01556     cdata->_data.get_unsafe_pointer()->finalize(manager);
01557   }
01558 
01559   reset_geom_rendering(cdata);
01560 }
01561 
01562 ////////////////////////////////////////////////////////////////////
01563 //     Function: Geom::fillin
01564 //       Access: Protected
01565 //  Description: This internal function is called by make_from_bam to
01566 //               read in all of the relevant data from the BamFile for
01567 //               the new Geom.
01568 ////////////////////////////////////////////////////////////////////
01569 void Geom::
01570 fillin(DatagramIterator &scan, BamReader *manager) {
01571   TypedWritable::fillin(scan, manager);
01572 
01573   manager->read_cdata(scan, _cycler);
01574 }
01575 
01576 ////////////////////////////////////////////////////////////////////
01577 //     Function: Geom::CDataCache::Destructor
01578 //       Access: Public, Virtual
01579 //  Description: 
01580 ////////////////////////////////////////////////////////////////////
01581 Geom::CDataCache::
01582 ~CDataCache() {
01583   set_result(NULL, NULL);
01584 }
01585 
01586 ////////////////////////////////////////////////////////////////////
01587 //     Function: Geom::CDataCache::make_copy
01588 //       Access: Public, Virtual
01589 //  Description:
01590 ////////////////////////////////////////////////////////////////////
01591 CycleData *Geom::CDataCache::
01592 make_copy() const {
01593   return new CDataCache(*this);
01594 }
01595 
01596 ////////////////////////////////////////////////////////////////////
01597 //     Function: Geom::CacheEntry::evict_callback
01598 //       Access: Public, Virtual
01599 //  Description: Called when the entry is evicted from the cache, this
01600 //               should clean up the owning object appropriately.
01601 ////////////////////////////////////////////////////////////////////
01602 void Geom::CacheEntry::
01603 evict_callback() {
01604   LightMutexHolder holder(_source->_cache_lock);
01605   Cache::iterator ci = _source->_cache.find(&_key);
01606   nassertv(ci != _source->_cache.end());
01607   nassertv((*ci).second == this);
01608   _source->_cache.erase(ci);
01609 }
01610 
01611 ////////////////////////////////////////////////////////////////////
01612 //     Function: Geom::CacheEntry::output
01613 //       Access: Public, Virtual
01614 //  Description: 
01615 ////////////////////////////////////////////////////////////////////
01616 void Geom::CacheEntry::
01617 output(ostream &out) const {
01618   out << "geom " << (void *)_source << ", " 
01619       << (const void *)_key._modifier;
01620 }
01621 
01622 
01623 ////////////////////////////////////////////////////////////////////
01624 //     Function: Geom::CData::make_copy
01625 //       Access: Public, Virtual
01626 //  Description:
01627 ////////////////////////////////////////////////////////////////////
01628 CycleData *Geom::CData::
01629 make_copy() const {
01630   return new CData(*this);
01631 }
01632 
01633 ////////////////////////////////////////////////////////////////////
01634 //     Function: Geom::CData::write_datagram
01635 //       Access: Public, Virtual
01636 //  Description: Writes the contents of this object to the datagram
01637 //               for shipping out to a Bam file.
01638 ////////////////////////////////////////////////////////////////////
01639 void Geom::CData::
01640 write_datagram(BamWriter *manager, Datagram &dg) const {
01641   manager->write_pointer(dg, _data.get_read_pointer());
01642 
01643   dg.add_uint16(_primitives.size());
01644   Primitives::const_iterator pi;
01645   for (pi = _primitives.begin(); pi != _primitives.end(); ++pi) {
01646     manager->write_pointer(dg, (*pi).get_read_pointer());
01647   }
01648 
01649   dg.add_uint8(_primitive_type);
01650   dg.add_uint8(_shade_model);
01651 
01652   // Actually, we shouldn't bother writing out _geom_rendering; we'll
01653   // just throw it away anyway.
01654   dg.add_uint16(_geom_rendering);
01655 
01656   dg.add_uint8(_bounds_type);
01657 }
01658 
01659 ////////////////////////////////////////////////////////////////////
01660 //     Function: Geom::CData::complete_pointers
01661 //       Access: Public, Virtual
01662 //  Description: Receives an array of pointers, one for each time
01663 //               manager->read_pointer() was called in fillin().
01664 //               Returns the number of pointers processed.
01665 ////////////////////////////////////////////////////////////////////
01666 int Geom::CData::
01667 complete_pointers(TypedWritable **p_list, BamReader *manager) {
01668   int pi = CycleData::complete_pointers(p_list, manager);
01669 
01670   _data = DCAST(GeomVertexData, p_list[pi++]);
01671 
01672   Primitives::iterator pri;
01673   for (pri = _primitives.begin(); pri != _primitives.end(); ++pri) {
01674     (*pri) = DCAST(GeomPrimitive, p_list[pi++]);
01675   }
01676 
01677   return pi;
01678 }
01679 
01680 ////////////////////////////////////////////////////////////////////
01681 //     Function: Geom::CData::fillin
01682 //       Access: Public, Virtual
01683 //  Description: This internal function is called by make_from_bam to
01684 //               read in all of the relevant data from the BamFile for
01685 //               the new Geom.
01686 ////////////////////////////////////////////////////////////////////
01687 void Geom::CData::
01688 fillin(DatagramIterator &scan, BamReader *manager) {
01689   manager->read_pointer(scan);
01690 
01691   int num_primitives = scan.get_uint16();
01692   _primitives.reserve(num_primitives);
01693   for (int i = 0; i < num_primitives; ++i) {
01694     manager->read_pointer(scan);
01695     _primitives.push_back(NULL);
01696   }
01697 
01698   _primitive_type = (PrimitiveType)scan.get_uint8();
01699   _shade_model = (ShadeModel)scan.get_uint8();
01700 
01701   // To be removed: we no longer read _geom_rendering from the bam
01702   // file; instead, we rederive it in finalize().
01703   scan.get_uint16();
01704 
01705   _got_usage_hint = false;
01706   _modified = Geom::get_next_modified();
01707 
01708   _bounds_type = BoundingVolume::BT_default;
01709   if (manager->get_file_minor_ver() >= 19) {
01710     _bounds_type = (BoundingVolume::BoundsType)scan.get_uint8();
01711   }
01712 }
01713 
01714 ////////////////////////////////////////////////////////////////////
01715 //     Function: GeomPipelineReader::check_usage_hint
01716 //       Access: Public
01717 //  Description: Ensures that the Geom's usage_hint cache has been
01718 //               computed.
01719 ////////////////////////////////////////////////////////////////////
01720 void GeomPipelineReader::
01721 check_usage_hint() const {
01722   if (!_cdata->_got_usage_hint) {
01723     // We'll need to get a fresh pointer, since another thread might
01724     // already have modified the pointer on the object since we
01725     // queried it.
01726     {
01727 #ifdef DO_PIPELINING
01728       unref_delete((CycleData *)_cdata);
01729 #endif
01730       Geom::CDWriter fresh_cdata(((Geom *)_object.p())->_cycler, 
01731                                  false, _current_thread);
01732       ((GeomPipelineReader *)this)->_cdata = fresh_cdata;
01733 #ifdef DO_PIPELINING
01734       _cdata->ref();
01735 #endif
01736       if (!fresh_cdata->_got_usage_hint) {
01737         // The cache is still stale.  We have to do the work of
01738         // freshening it.
01739         ((Geom *)_object.p())->reset_usage_hint(fresh_cdata);
01740         nassertv(fresh_cdata->_got_usage_hint);
01741       }
01742 
01743       // When fresh_cdata goes out of scope, its write lock is
01744       // released, and _cdata reverts to our usual convention of an
01745       // unlocked copy of the data.
01746     }
01747   }
01748 
01749   nassertv(_cdata->_got_usage_hint);
01750 }
01751 
01752 ////////////////////////////////////////////////////////////////////
01753 //     Function: GeomPipelineReader::check_valid
01754 //       Access: Public
01755 //  Description: 
01756 ////////////////////////////////////////////////////////////////////
01757 bool GeomPipelineReader::
01758 check_valid(const GeomVertexDataPipelineReader *data_reader) const {
01759   Geom::Primitives::const_iterator pi;
01760   for (pi = _cdata->_primitives.begin(); 
01761        pi != _cdata->_primitives.end();
01762        ++pi) {
01763     CPT(GeomPrimitive) primitive = (*pi).get_read_pointer();
01764     GeomPrimitivePipelineReader reader(primitive, _current_thread);
01765     reader.check_minmax();
01766     if (!reader.check_valid(data_reader)) {
01767       return false;
01768     }
01769   }
01770 
01771   return true;
01772 }
01773   
01774 ////////////////////////////////////////////////////////////////////
01775 //     Function: GeomPipelineReader::draw
01776 //       Access: Public
01777 //  Description: The implementation of Geom::draw().
01778 ////////////////////////////////////////////////////////////////////
01779 bool GeomPipelineReader::
01780 draw(GraphicsStateGuardianBase *gsg, const GeomMunger *munger,
01781      const GeomVertexDataPipelineReader *data_reader, bool force) const {
01782   PStatTimer timer(Geom::_draw_primitive_setup_pcollector);
01783   bool all_ok = gsg->begin_draw_primitives(this, munger, data_reader, force);
01784   if (all_ok) {
01785     Geom::Primitives::const_iterator pi;
01786     for (pi = _cdata->_primitives.begin(); 
01787          pi != _cdata->_primitives.end();
01788          ++pi) {
01789       CPT(GeomPrimitive) primitive = (*pi).get_read_pointer();
01790       GeomPrimitivePipelineReader reader(primitive, _current_thread);
01791       if (reader.get_num_vertices() != 0) {
01792         reader.check_minmax();
01793         nassertr(reader.check_valid(data_reader), false);
01794         if (!primitive->draw(gsg, &reader, force)) {
01795           all_ok = false;
01796         }
01797       }
01798     }
01799     gsg->end_draw_primitives();
01800   }
01801 
01802   return all_ok;
01803 }
 All Classes Functions Variables Enumerations