Panda3D

geomPrimitive.cxx

00001 // Filename: geomPrimitive.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 "geomPrimitive.h"
00016 #include "geom.h"
00017 #include "geomVertexData.h"
00018 #include "geomVertexArrayFormat.h"
00019 #include "geomVertexColumn.h"
00020 #include "geomVertexReader.h"
00021 #include "geomVertexWriter.h"
00022 #include "geomVertexRewriter.h"
00023 #include "geomPoints.h"
00024 #include "preparedGraphicsObjects.h"
00025 #include "internalName.h"
00026 #include "bamReader.h"
00027 #include "bamWriter.h"
00028 #include "ioPtaDatagramInt.h"
00029 #include "indent.h"
00030 #include "pStatTimer.h"
00031 
00032 TypeHandle GeomPrimitive::_type_handle;
00033 TypeHandle GeomPrimitive::CData::_type_handle;
00034 TypeHandle GeomPrimitivePipelineReader::_type_handle;
00035 
00036 PStatCollector GeomPrimitive::_decompose_pcollector("*:Munge:Decompose");
00037 PStatCollector GeomPrimitive::_doubleside_pcollector("*:Munge:Doubleside");
00038 PStatCollector GeomPrimitive::_reverse_pcollector("*:Munge:Reverse");
00039 PStatCollector GeomPrimitive::_rotate_pcollector("*:Munge:Rotate");
00040 
00041 ////////////////////////////////////////////////////////////////////
00042 //     Function: GeomPrimitive::Default Constructor
00043 //       Access: Protected
00044 //  Description: Constructs an invalid object.  Only used when reading
00045 //               from bam.
00046 ////////////////////////////////////////////////////////////////////
00047 GeomPrimitive::
00048 GeomPrimitive() {
00049 }
00050 
00051 ////////////////////////////////////////////////////////////////////
00052 //     Function: GeomPrimitive::make_cow_copy
00053 //       Access: Protected, Virtual
00054 //  Description: Required to implement CopyOnWriteObject.
00055 ////////////////////////////////////////////////////////////////////
00056 PT(CopyOnWriteObject) GeomPrimitive::
00057 make_cow_copy() {
00058   return make_copy().p();
00059 }
00060 
00061 ////////////////////////////////////////////////////////////////////
00062 //     Function: GeomPrimitive::Constructor
00063 //       Access: Published
00064 //  Description: 
00065 ////////////////////////////////////////////////////////////////////
00066 GeomPrimitive::
00067 GeomPrimitive(GeomPrimitive::UsageHint usage_hint) {
00068   CDWriter cdata(_cycler, true);
00069   cdata->_usage_hint = usage_hint;
00070 }
00071  
00072 ////////////////////////////////////////////////////////////////////
00073 //     Function: GeomPrimitive::Copy Constructor
00074 //       Access: Published
00075 //  Description: 
00076 ////////////////////////////////////////////////////////////////////
00077 GeomPrimitive::
00078 GeomPrimitive(const GeomPrimitive &copy) :
00079   CopyOnWriteObject(copy),
00080   _cycler(copy._cycler)
00081 {
00082 }
00083   
00084 ////////////////////////////////////////////////////////////////////
00085 //     Function: GeomPrimitive::Copy Assignment Operator
00086 //       Access: Published
00087 //  Description: The copy assignment operator is not pipeline-safe.
00088 //               This will completely obliterate all stages of the
00089 //               pipeline, so don't do it for a GeomPrimitive that is
00090 //               actively being used for rendering.
00091 ////////////////////////////////////////////////////////////////////
00092 void GeomPrimitive::
00093 operator = (const GeomPrimitive &copy) {
00094   CopyOnWriteObject::operator = (copy);
00095   _cycler = copy._cycler;
00096 }
00097 
00098 ////////////////////////////////////////////////////////////////////
00099 //     Function: GeomPrimitive::Destructor
00100 //       Access: Published, Virtual
00101 //  Description: 
00102 ////////////////////////////////////////////////////////////////////
00103 GeomPrimitive::
00104 ~GeomPrimitive() {
00105   release_all();
00106 }
00107 
00108 ////////////////////////////////////////////////////////////////////
00109 //     Function: GeomPrimitive::get_geom_rendering
00110 //       Access: Published, Virtual
00111 //  Description: Returns the set of GeomRendering bits that represent
00112 //               the rendering properties required to properly render
00113 //               this primitive.
00114 ////////////////////////////////////////////////////////////////////
00115 int GeomPrimitive::
00116 get_geom_rendering() const {
00117   if (is_indexed()) {
00118     return GR_indexed_other;
00119   } else {
00120     return 0;
00121   }
00122 }
00123 
00124 ////////////////////////////////////////////////////////////////////
00125 //     Function: GeomPrimitive::set_usage_hint
00126 //       Access: Published
00127 //  Description: Changes the UsageHint hint for this primitive.  See
00128 //               get_usage_hint().
00129 //
00130 //               Don't call this in a downstream thread unless you
00131 //               don't mind it blowing away other changes you might
00132 //               have recently made in an upstream thread.
00133 ////////////////////////////////////////////////////////////////////
00134 void GeomPrimitive::
00135 set_usage_hint(GeomPrimitive::UsageHint usage_hint) {
00136   CDWriter cdata(_cycler, true);
00137   cdata->_usage_hint = usage_hint;
00138 
00139   if (!cdata->_vertices.is_null()) {
00140     cdata->_modified = Geom::get_next_modified();
00141     cdata->_usage_hint = usage_hint;
00142   }
00143 }
00144 
00145 ////////////////////////////////////////////////////////////////////
00146 //     Function: GeomPrimitive::set_index_type
00147 //       Access: Published
00148 //  Description: Changes the numeric type of the index column.
00149 //               Normally, this should be either NT_uint16 or
00150 //               NT_uint32.
00151 //
00152 //               The index type must be large enough to include all of
00153 //               the index values in the primitive.  It may be
00154 //               automatically elevated, if necessary, to a larger
00155 //               index type, by a subsequent call to add_index() that
00156 //               names an index value that does not fit in the index
00157 //               type you specify.
00158 //
00159 //               Don't call this in a downstream thread unless you
00160 //               don't mind it blowing away other changes you might
00161 //               have recently made in an upstream thread.
00162 ////////////////////////////////////////////////////////////////////
00163 void GeomPrimitive::
00164 set_index_type(GeomPrimitive::NumericType index_type) {
00165   nassertv(get_max_vertex() <= get_highest_index_value(index_type));
00166 
00167   CDWriter cdata(_cycler, true);
00168   if (cdata->_index_type != index_type) {
00169     do_set_index_type(cdata, index_type);
00170   }
00171 }
00172 
00173 ////////////////////////////////////////////////////////////////////
00174 //     Function: GeomPrimitive::add_vertex
00175 //       Access: Published
00176 //  Description: Adds the indicated vertex to the list of vertex
00177 //               indices used by the graphics primitive type.  To
00178 //               define a primitive, you must call add_vertex() for
00179 //               each vertex of the new primitive, and then call
00180 //               close_primitive() after you have specified the last
00181 //               vertex of each primitive.
00182 //
00183 //               Don't call this in a downstream thread unless you
00184 //               don't mind it blowing away other changes you might
00185 //               have recently made in an upstream thread.
00186 ////////////////////////////////////////////////////////////////////
00187 void GeomPrimitive::
00188 add_vertex(int vertex) {
00189   CDWriter cdata(_cycler, true);
00190 
00191   if (gobj_cat.is_spam()) {
00192     gobj_cat.spam()
00193       << this << ".add_vertex(" << vertex << ")\n";
00194   }
00195 
00196   consider_elevate_index_type(cdata, vertex);
00197 
00198   int num_primitives = get_num_primitives();
00199   if (num_primitives > 0 &&
00200       requires_unused_vertices() && 
00201       get_num_vertices() == get_primitive_end(num_primitives - 1)) {
00202     // If we are beginning a new primitive, give the derived class a
00203     // chance to insert some degenerate vertices.
00204     if (cdata->_vertices.is_null()) {
00205       do_make_indexed(cdata);
00206     }
00207     append_unused_vertices(cdata->_vertices.get_write_pointer(), vertex);
00208   }
00209 
00210   if (cdata->_vertices.is_null()) {
00211     // The nonindexed case.  We can keep the primitive nonindexed only
00212     // if the vertex number happens to be the next available vertex.
00213     nassertv(cdata->_num_vertices != -1);
00214     if (cdata->_num_vertices == 0) {
00215       cdata->_first_vertex = vertex;
00216       cdata->_num_vertices = 1;
00217       cdata->_modified = Geom::get_next_modified();
00218       cdata->_got_minmax = false;
00219       return;
00220 
00221     } else if (vertex == cdata->_first_vertex + cdata->_num_vertices) {
00222       ++cdata->_num_vertices;
00223       cdata->_modified = Geom::get_next_modified();
00224       cdata->_got_minmax = false;
00225       return;
00226     }
00227     
00228     // Otherwise, we need to suddenly become an indexed primitive.
00229     do_make_indexed(cdata);
00230   }
00231 
00232   PT(GeomVertexArrayData) array_obj = cdata->_vertices.get_write_pointer();
00233   GeomVertexWriter index(array_obj, 0);
00234   index.set_row_unsafe(array_obj->get_num_rows());
00235 
00236   index.add_data1i(vertex);
00237 
00238   cdata->_modified = Geom::get_next_modified();
00239   cdata->_got_minmax = false;
00240 }
00241 
00242 ////////////////////////////////////////////////////////////////////
00243 //     Function: GeomPrimitive::add_consecutive_vertices
00244 //       Access: Published
00245 //  Description: Adds a consecutive sequence of vertices, beginning at
00246 //               start, to the primitive.
00247 //
00248 //               Don't call this in a downstream thread unless you
00249 //               don't mind it blowing away other changes you might
00250 //               have recently made in an upstream thread.
00251 ////////////////////////////////////////////////////////////////////
00252 void GeomPrimitive::
00253 add_consecutive_vertices(int start, int num_vertices) {
00254   if (num_vertices == 0) {
00255     return;
00256   }
00257   int end = (start + num_vertices) - 1;
00258 
00259   CDWriter cdata(_cycler, true);
00260 
00261   consider_elevate_index_type(cdata, end);
00262 
00263   int num_primitives = get_num_primitives();
00264   if (num_primitives > 0 &&
00265       get_num_vertices() == get_primitive_end(num_primitives - 1)) {
00266     // If we are beginning a new primitive, give the derived class a
00267     // chance to insert some degenerate vertices.
00268     if (cdata->_vertices.is_null()) {
00269       do_make_indexed(cdata);
00270     }
00271     append_unused_vertices(cdata->_vertices.get_write_pointer(), start);
00272   }
00273 
00274   if (cdata->_vertices.is_null()) {
00275     // The nonindexed case.  We can keep the primitive nonindexed only
00276     // if the vertex number happens to be the next available vertex.
00277     nassertv(cdata->_num_vertices != -1);
00278     if (cdata->_num_vertices == 0) {
00279       cdata->_first_vertex = start;
00280       cdata->_num_vertices = num_vertices;
00281       cdata->_modified = Geom::get_next_modified();
00282       cdata->_got_minmax = false;
00283       return;
00284 
00285     } else if (start == cdata->_first_vertex + cdata->_num_vertices) {
00286       cdata->_num_vertices += num_vertices;
00287       cdata->_modified = Geom::get_next_modified();
00288       cdata->_got_minmax = false;
00289       return;
00290     }
00291     
00292     // Otherwise, we need to suddenly become an indexed primitive.
00293     do_make_indexed(cdata);
00294   }
00295 
00296   PT(GeomVertexArrayData) array_obj = cdata->_vertices.get_write_pointer();
00297   GeomVertexWriter index(array_obj, 0);
00298   index.set_row_unsafe(array_obj->get_num_rows());
00299 
00300   for (int v = start; v <= end; ++v) {
00301     index.add_data1i(v);
00302   }
00303 
00304   cdata->_modified = Geom::get_next_modified();
00305   cdata->_got_minmax = false;
00306 }
00307 
00308 ////////////////////////////////////////////////////////////////////
00309 //     Function: GeomPrimitive::add_next_vertices
00310 //       Access: Published
00311 //  Description: Adds the next n vertices in sequence, beginning from
00312 //               the last vertex added to the primitive + 1.
00313 //
00314 //               This is most useful when you are building up a
00315 //               primitive and a GeomVertexData at the same time, and
00316 //               you just want the primitive to reference the first n
00317 //               vertices from the data, then the next n, and so on.
00318 ////////////////////////////////////////////////////////////////////
00319 void GeomPrimitive::
00320 add_next_vertices(int num_vertices) {
00321   if (get_num_vertices() == 0) {
00322     add_consecutive_vertices(0, num_vertices);
00323   } else {
00324     add_consecutive_vertices(get_vertex(get_num_vertices() - 1) + 1, num_vertices);
00325   }
00326 }
00327 
00328 ////////////////////////////////////////////////////////////////////
00329 //     Function: GeomPrimitive::reserve_num_vertices
00330 //       Access: Published
00331 //  Description: This ensures that enough memory space for n vertices
00332 //               is allocated, so that you may increase the number of
00333 //               vertices to n without causing a new memory
00334 //               allocation.  This is a performance optimization only;
00335 //               it is especially useful when you know ahead of time
00336 //               that you will be adding n vertices to the primitive.
00337 //
00338 //               Note that the total you specify here should also
00339 //               include implicit vertices which may be added at each
00340 //               close_primitive() call, according to
00341 //               get_num_unused_vertices_per_primitive().
00342 //
00343 //               Note also that making this call will implicitly make
00344 //               the primitive indexed if it is not already, which
00345 //               could result in a performance *penalty*.  If you
00346 //               would prefer not to lose the nonindexed nature of
00347 //               your existing GeomPrimitives, check is_indexed()
00348 //               before making this call.
00349 ////////////////////////////////////////////////////////////////////
00350 void GeomPrimitive::
00351 reserve_num_vertices(int num_vertices) {
00352   if (gobj_cat.is_debug()) {
00353     gobj_cat.debug()
00354       << this << ".reserve_num_vertices(" << num_vertices << ")\n";
00355   }
00356 
00357   CDWriter cdata(_cycler, true);
00358   consider_elevate_index_type(cdata, num_vertices);
00359   do_make_indexed(cdata);
00360   PT(GeomVertexArrayData) array_obj = cdata->_vertices.get_write_pointer();
00361   array_obj->reserve_num_rows(num_vertices);
00362 }
00363 
00364 ////////////////////////////////////////////////////////////////////
00365 //     Function: GeomPrimitive::close_primitive
00366 //       Access: Published
00367 //  Description: Indicates that the previous n calls to add_vertex(),
00368 //               since the last call to close_primitive(), have fully
00369 //               defined a new primitive.  Returns true if successful,
00370 //               false otherwise.
00371 //
00372 //               Don't call this in a downstream thread unless you
00373 //               don't mind it blowing away other changes you might
00374 //               have recently made in an upstream thread.
00375 ////////////////////////////////////////////////////////////////////
00376 bool GeomPrimitive::
00377 close_primitive() {
00378   int num_vertices_per_primitive = get_num_vertices_per_primitive();
00379 
00380   CDWriter cdata(_cycler, true);
00381   if (num_vertices_per_primitive == 0) {
00382     // This is a complex primitive type like a triangle strip: each
00383     // primitive uses a different number of vertices.
00384 #ifndef NDEBUG
00385     int num_added;
00386     if (cdata->_ends.empty()) {
00387       num_added = get_num_vertices();
00388     } else {
00389       num_added = get_num_vertices() - cdata->_ends.back();
00390       num_added -= get_num_unused_vertices_per_primitive();
00391     }
00392     nassertr(num_added >= get_min_num_vertices_per_primitive(), false);
00393 #endif
00394     if (cdata->_ends.get_ref_count() > 1) {
00395       PTA_int new_ends;
00396       new_ends.v() = cdata->_ends.v();
00397       cdata->_ends = new_ends;
00398     }
00399     cdata->_ends.push_back(get_num_vertices());
00400 
00401   } else {
00402 #ifndef NDEBUG
00403     // This is a simple primitive type like a triangle: each primitive
00404     // uses the same number of vertices.  Assert that we added the
00405     // correct number of vertices.
00406     int num_vertices_per_primitive = get_num_vertices_per_primitive();
00407     int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
00408 
00409     int num_vertices = get_num_vertices();
00410     nassertr((num_vertices + num_unused_vertices_per_primitive) % (num_vertices_per_primitive + num_unused_vertices_per_primitive) == 0, false)
00411 #endif
00412   }
00413 
00414   cdata->_modified = Geom::get_next_modified();
00415 
00416   return true;
00417 }
00418 
00419 ////////////////////////////////////////////////////////////////////
00420 //     Function: GeomPrimitive::clear_vertices
00421 //       Access: Published
00422 //  Description: Removes all of the vertices and primitives from the
00423 //               object, so they can be re-added.
00424 //
00425 //               Don't call this in a downstream thread unless you
00426 //               don't mind it blowing away other changes you might
00427 //               have recently made in an upstream thread.
00428 ////////////////////////////////////////////////////////////////////
00429 void GeomPrimitive::
00430 clear_vertices() {
00431   CDWriter cdata(_cycler, true);
00432   cdata->_first_vertex = 0;
00433   cdata->_num_vertices = 0;
00434 
00435   // Since we might have automatically elevated the index type by
00436   // adding vertices, we should automatically lower it again when we
00437   // call clear_vertices().
00438   cdata->_index_type = NT_uint16;
00439 
00440   cdata->_vertices.clear();
00441   cdata->_ends.clear();
00442   cdata->_mins.clear();
00443   cdata->_maxs.clear();
00444   cdata->_modified = Geom::get_next_modified();
00445   cdata->_got_minmax = false;
00446 }
00447 
00448 ////////////////////////////////////////////////////////////////////
00449 //     Function: GeomPrimitive::offset_vertices
00450 //       Access: Published
00451 //  Description: Adds the indicated offset to all vertices used by the
00452 //               primitive.
00453 //
00454 //               Don't call this in a downstream thread unless you
00455 //               don't mind it blowing away other changes you might
00456 //               have recently made in an upstream thread.
00457 ////////////////////////////////////////////////////////////////////
00458 void GeomPrimitive::
00459 offset_vertices(int offset) {
00460   if (is_indexed()) {
00461     CDWriter cdata(_cycler, true);
00462 
00463     if (!cdata->_got_minmax) {
00464       recompute_minmax(cdata);
00465       nassertv(cdata->_got_minmax);
00466     }
00467     
00468     consider_elevate_index_type(cdata, cdata->_max_vertex + offset);
00469 
00470     GeomVertexRewriter index(do_modify_vertices(cdata), 0);
00471     while (!index.is_at_end()) {
00472       index.set_data1i(index.get_data1i() + offset);
00473     }
00474 
00475   } else {
00476     CDWriter cdata(_cycler, true);
00477 
00478     cdata->_first_vertex += offset;
00479     cdata->_modified = Geom::get_next_modified();
00480     cdata->_got_minmax = false;
00481 
00482     consider_elevate_index_type(cdata, 
00483                                 cdata->_first_vertex + cdata->_num_vertices - 1);
00484   }
00485 }
00486 
00487 ////////////////////////////////////////////////////////////////////
00488 //     Function: GeomPrimitive::make_nonindexed
00489 //       Access: Published
00490 //  Description: Converts the primitive from indexed to nonindexed by
00491 //               duplicating vertices as necessary into the indicated
00492 //               dest GeomVertexData.
00493 ////////////////////////////////////////////////////////////////////
00494 void GeomPrimitive::
00495 make_nonindexed(GeomVertexData *dest, const GeomVertexData *source) {
00496   Thread *current_thread = Thread::get_current_thread();
00497   int num_vertices = get_num_vertices();
00498   int dest_start = dest->get_num_rows();
00499 
00500   dest->set_num_rows(dest_start + num_vertices);
00501   for (int i = 0; i < num_vertices; ++i) {
00502     int v = get_vertex(i);
00503     dest->copy_row_from(dest_start + i, source, v, current_thread);
00504   }
00505 
00506   set_nonindexed_vertices(dest_start, num_vertices);
00507 }
00508 
00509 ////////////////////////////////////////////////////////////////////
00510 //     Function: GeomPrimitive::pack_vertices
00511 //       Access: Published
00512 //  Description: Packs the vertices used by the primitive from the
00513 //               indicated source array onto the end of the indicated
00514 //               destination array.
00515 ////////////////////////////////////////////////////////////////////
00516 void GeomPrimitive::
00517 pack_vertices(GeomVertexData *dest, const GeomVertexData *source) {
00518   Thread *current_thread = Thread::get_current_thread();
00519   if (!is_indexed()) {
00520     // If the primitive is nonindexed, packing is the same as
00521     // converting (again) to nonindexed.
00522     make_nonindexed(dest, source);
00523 
00524   } else {
00525     // The indexed case: build up a new index as we go.
00526     CPT(GeomVertexArrayData) orig_vertices = get_vertices();
00527     PT(GeomVertexArrayData) new_vertices = make_index_data();
00528     GeomVertexWriter index(new_vertices, 0);
00529     typedef pmap<int, int> CopiedIndices;
00530     CopiedIndices copied_indices;
00531 
00532     int num_vertices = get_num_vertices();
00533     int dest_start = dest->get_num_rows();
00534 
00535     for (int i = 0; i < num_vertices; ++i) {
00536       int v = get_vertex(i);
00537 
00538       // Try to add the relation { v : size() }.  If that succeeds,
00539       // great; if it doesn't, look up whatever we previously added
00540       // for v.
00541       pair<CopiedIndices::iterator, bool> result = 
00542         copied_indices.insert(CopiedIndices::value_type(v, (int)copied_indices.size()));
00543       int v2 = (*result.first).second + dest_start;
00544       index.add_data1i(v2);
00545 
00546       if (result.second) {
00547         // This is the first time we've seen vertex v.
00548         dest->copy_row_from(v2, source, v, current_thread);
00549       }
00550     }
00551     
00552     set_vertices(new_vertices);
00553   }
00554 }
00555 
00556 ////////////////////////////////////////////////////////////////////
00557 //     Function: GeomPrimitive::make_indexed
00558 //       Access: Published
00559 //  Description: Converts the primitive from nonindexed form to
00560 //               indexed form.  This will simply create an index table
00561 //               that is numbered consecutively from
00562 //               get_first_vertex(); it does not automatically
00563 //               collapse together identical vertices that may have
00564 //               been split apart by a previous call to
00565 //               make_nonindexed().
00566 //
00567 //               Don't call this in a downstream thread unless you
00568 //               don't mind it blowing away other changes you might
00569 //               have recently made in an upstream thread.
00570 ////////////////////////////////////////////////////////////////////
00571 void GeomPrimitive::
00572 make_indexed() {
00573   CDWriter cdata(_cycler, true);
00574   do_make_indexed(cdata);
00575 }
00576 
00577 ////////////////////////////////////////////////////////////////////
00578 //     Function: GeomPrimitive::get_primitive_start
00579 //       Access: Published
00580 //  Description: Returns the element within the _vertices list at which
00581 //               the nth primitive starts.  
00582 //
00583 //               If i is one more than the highest valid primitive
00584 //               vertex, the return value will be one more than the
00585 //               last valid vertex.  Thus, it is generally true that
00586 //               the vertices used by a particular primitive i are the
00587 //               set get_primitive_start(n) <= vi <
00588 //               get_primitive_start(n + 1) (although this range also
00589 //               includes the unused vertices between primitives).
00590 ////////////////////////////////////////////////////////////////////
00591 int GeomPrimitive::
00592 get_primitive_start(int n) const {
00593   int num_vertices_per_primitive = get_num_vertices_per_primitive();
00594   int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
00595 
00596   if (num_vertices_per_primitive == 0) {
00597     // This is a complex primitive type like a triangle strip: each
00598     // primitive uses a different number of vertices.
00599     CDReader cdata(_cycler);
00600     nassertr(n >= 0 && n <= (int)cdata->_ends.size(), -1);
00601     if (n == 0) {
00602       return 0;
00603     } else {
00604       return cdata->_ends[n - 1] + num_unused_vertices_per_primitive;
00605     }
00606 
00607   } else {
00608     // This is a simple primitive type like a triangle: each primitive
00609     // uses the same number of vertices.
00610     return n * (num_vertices_per_primitive + num_unused_vertices_per_primitive);
00611   }
00612 }
00613 
00614 ////////////////////////////////////////////////////////////////////
00615 //     Function: GeomPrimitive::get_primitive_end
00616 //       Access: Published
00617 //  Description: Returns the element within the _vertices list at which
00618 //               the nth primitive ends.  This is one past the last
00619 //               valid element for the nth primitive.
00620 ////////////////////////////////////////////////////////////////////
00621 int GeomPrimitive::
00622 get_primitive_end(int n) const {
00623   int num_vertices_per_primitive = get_num_vertices_per_primitive();
00624 
00625   if (num_vertices_per_primitive == 0) {
00626     // This is a complex primitive type like a triangle strip: each
00627     // primitive uses a different number of vertices.
00628     CDReader cdata(_cycler);
00629     nassertr(n >= 0 && n < (int)cdata->_ends.size(), -1);
00630     return cdata->_ends[n];
00631 
00632   } else {
00633     // This is a simple primitive type like a triangle: each primitive
00634     // uses the same number of vertices.
00635     int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
00636     return n * (num_vertices_per_primitive + num_unused_vertices_per_primitive) + num_vertices_per_primitive;
00637   }
00638 }
00639 
00640 ////////////////////////////////////////////////////////////////////
00641 //     Function: GeomPrimitive::get_primitive_num_vertices
00642 //       Access: Published
00643 //  Description: Returns the number of vertices used by the nth
00644 //               primitive.  This is the same thing as
00645 //               get_primitive_end(n) - get_primitive_start(n).
00646 ////////////////////////////////////////////////////////////////////
00647 int GeomPrimitive::
00648 get_primitive_num_vertices(int n) const {
00649   int num_vertices_per_primitive = get_num_vertices_per_primitive();
00650 
00651   if (num_vertices_per_primitive == 0) {
00652     // This is a complex primitive type like a triangle strip: each
00653     // primitive uses a different number of vertices.
00654     CDReader cdata(_cycler);
00655     nassertr(n >= 0 && n < (int)cdata->_ends.size(), 0);
00656     if (n == 0) {
00657       return cdata->_ends[0];
00658     } else {
00659       int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
00660       return cdata->_ends[n] - cdata->_ends[n - 1] - num_unused_vertices_per_primitive;
00661     }      
00662 
00663   } else {
00664     // This is a simple primitive type like a triangle: each primitive
00665     // uses the same number of vertices.
00666     return num_vertices_per_primitive;
00667   }
00668 }
00669 
00670 ////////////////////////////////////////////////////////////////////
00671 //     Function: GeomPrimitive::get_primitive_min_vertex
00672 //       Access: Published
00673 //  Description: Returns the minimum vertex index number used by the
00674 //               nth primitive in this object.
00675 ////////////////////////////////////////////////////////////////////
00676 int GeomPrimitive::
00677 get_primitive_min_vertex(int n) const {
00678   if (is_indexed()) {
00679     CPT(GeomVertexArrayData) mins = get_mins();
00680     nassertr(n >= 0 && n < mins->get_num_rows(), -1);
00681 
00682     GeomVertexReader index(mins, 0);
00683     index.set_row_unsafe(n);
00684     return index.get_data1i();
00685   } else {
00686     return get_primitive_start(n);
00687   }
00688 }
00689 
00690 ////////////////////////////////////////////////////////////////////
00691 //     Function: GeomPrimitive::get_primitive_max_vertex
00692 //       Access: Published
00693 //  Description: Returns the maximum vertex index number used by the
00694 //               nth primitive in this object.
00695 ////////////////////////////////////////////////////////////////////
00696 int GeomPrimitive::
00697 get_primitive_max_vertex(int n) const {
00698   if (is_indexed()) {
00699     CPT(GeomVertexArrayData) maxs = get_maxs();
00700     nassertr(n >= 0 && n < maxs->get_num_rows(), -1);
00701 
00702     GeomVertexReader index(maxs, 0);
00703     index.set_row_unsafe(n);
00704     return index.get_data1i();
00705   } else {
00706     return get_primitive_end(n) - 1;
00707   }
00708 }
00709 
00710 ////////////////////////////////////////////////////////////////////
00711 //     Function: GeomPrimitive::decompose
00712 //       Access: Published
00713 //  Description: Decomposes a complex primitive type into a simpler
00714 //               primitive type, for instance triangle strips to
00715 //               triangles, and returns a pointer to the new primitive
00716 //               definition.  If the decomposition cannot be
00717 //               performed, this might return the original object.
00718 //
00719 //               This method is useful for application code that wants
00720 //               to iterate through the set of triangles on the
00721 //               primitive without having to write handlers for each
00722 //               possible kind of primitive type.
00723 ////////////////////////////////////////////////////////////////////
00724 CPT(GeomPrimitive) GeomPrimitive::
00725 decompose() const {
00726   if (gobj_cat.is_debug()) {
00727     gobj_cat.debug()
00728       << "Decomposing " << get_type() << ": " << (void *)this << "\n";
00729   }
00730 
00731   PStatTimer timer(_decompose_pcollector);
00732   return decompose_impl();
00733 }
00734 
00735 ////////////////////////////////////////////////////////////////////
00736 //     Function: GeomPrimitive::rotate
00737 //       Access: Published
00738 //  Description: Returns a new primitive with the shade_model reversed
00739 //               (if it is flat shaded), if possible.  If the
00740 //               primitive type cannot be rotated, returns the
00741 //               original primitive, unrotated.
00742 //
00743 //               If the current shade_model indicates
00744 //               flat_vertex_last, this should bring the last vertex
00745 //               to the first position; if it indicates
00746 //               flat_vertex_first, this should bring the first vertex
00747 //               to the last position.
00748 ////////////////////////////////////////////////////////////////////
00749 CPT(GeomPrimitive) GeomPrimitive::
00750 rotate() const {
00751   if (gobj_cat.is_debug()) {
00752     gobj_cat.debug()
00753       << "Rotating " << get_type() << ": " << (void *)this << "\n";
00754   }
00755 
00756   PStatTimer timer(_rotate_pcollector);
00757   CPT(GeomVertexArrayData) rotated_vertices = rotate_impl();
00758 
00759   if (rotated_vertices == (GeomVertexArrayData *)NULL) {
00760     // This primitive type can't be rotated.
00761     return this;
00762   }
00763 
00764   PT(GeomPrimitive) new_prim = make_copy();
00765   new_prim->set_vertices(rotated_vertices);
00766 
00767   switch (get_shade_model()) {
00768   case SM_flat_first_vertex:
00769     new_prim->set_shade_model(SM_flat_last_vertex);
00770     break;
00771 
00772   case SM_flat_last_vertex:
00773     new_prim->set_shade_model(SM_flat_first_vertex);
00774     break;
00775 
00776   default:
00777     break;
00778   }
00779 
00780   return new_prim;
00781 }
00782 
00783 ////////////////////////////////////////////////////////////////////
00784 //     Function: GeomPrimitive::doubleside
00785 //       Access: Published
00786 //  Description: Duplicates triangles in the primitive so that each
00787 //               triangle is back-to-back with another triangle facing
00788 //               in the opposite direction.  Note that this doesn't
00789 //               affect vertex normals, so this operation alone won't
00790 //               work in the presence of lighting (but see
00791 //               SceneGraphReducer::doubleside()).
00792 //
00793 //               Also see CullFaceAttrib, which can enable rendering
00794 //               of both sides of a triangle without having to
00795 //               duplicate it (but which doesn't necessarily work in
00796 //               the presence of lighting).
00797 ////////////////////////////////////////////////////////////////////
00798 CPT(GeomPrimitive) GeomPrimitive::
00799 doubleside() const {
00800   if (gobj_cat.is_debug()) {
00801     gobj_cat.debug()
00802       << "Doublesiding " << get_type() << ": " << (void *)this << "\n";
00803   }
00804 
00805   PStatTimer timer(_doubleside_pcollector);
00806   return doubleside_impl();
00807 }
00808 
00809 ////////////////////////////////////////////////////////////////////
00810 //     Function: GeomPrimitive::reverse
00811 //       Access: Published
00812 //  Description: Reverses the winding order in the primitive so that
00813 //               each triangle is facing in the opposite direction it
00814 //               was originally.  Note that this doesn't affect vertex
00815 //               normals, so this operation alone won't work in the
00816 //               presence of lighting (but see
00817 //               SceneGraphReducer::reverse()).
00818 //
00819 //               Also see CullFaceAttrib, which can change the visible
00820 //               direction of a triangle without having to duplicate
00821 //               it (but which doesn't necessarily work in the
00822 //               presence of lighting).
00823 ////////////////////////////////////////////////////////////////////
00824 CPT(GeomPrimitive) GeomPrimitive::
00825 reverse() const {
00826   if (gobj_cat.is_debug()) {
00827     gobj_cat.debug()
00828       << "Reversing " << get_type() << ": " << (void *)this << "\n";
00829   }
00830 
00831   PStatTimer timer(_reverse_pcollector);
00832   return reverse_impl();
00833 }
00834 
00835 ////////////////////////////////////////////////////////////////////
00836 //     Function: GeomPrimitive::match_shade_model
00837 //       Access: Published
00838 //  Description: Returns a new primitive that is compatible with the
00839 //               indicated shade model, if possible, or NULL if this
00840 //               is not possible.
00841 //
00842 //               In most cases, this will return either NULL or the
00843 //               original primitive.  In the case of a
00844 //               SM_flat_first_vertex vs. a SM_flat_last_vertex (or
00845 //               vice-versa), however, it will return a rotated
00846 //               primitive.
00847 ////////////////////////////////////////////////////////////////////
00848 CPT(GeomPrimitive) GeomPrimitive::
00849 match_shade_model(GeomPrimitive::ShadeModel shade_model) const {
00850   ShadeModel this_shade_model = get_shade_model();
00851   if (this_shade_model == shade_model) {
00852     // Trivially compatible.
00853     return this;
00854   }
00855 
00856   if (this_shade_model == SM_uniform || shade_model == SM_uniform) {
00857     // SM_uniform is compatible with anything.
00858     return this;
00859   }
00860 
00861   if ((this_shade_model == SM_flat_first_vertex && shade_model == SM_flat_last_vertex) ||
00862       (this_shade_model == SM_flat_last_vertex && shade_model == SM_flat_first_vertex)) {
00863     // Needs to be rotated.
00864     CPT(GeomPrimitive) rotated = rotate();
00865     if (rotated.p() == this) {
00866       // Oops, can't be rotated, sorry.
00867       return NULL;
00868     }
00869     return rotated;
00870   }
00871 
00872   // Not compatible, sorry.
00873   return NULL;
00874 }
00875 
00876 ////////////////////////////////////////////////////////////////////
00877 //     Function: GeomPrimitive::make_points
00878 //       Access: Published
00879 //  Description: Returns a new GeomPoints primitive that represents
00880 //               each of the vertices in the original primitive,
00881 //               rendered exactly once.  If the original primitive is
00882 //               already a GeomPoints primitive, returns the original
00883 //               primitive unchanged.
00884 ////////////////////////////////////////////////////////////////////
00885 CPT(GeomPrimitive) GeomPrimitive::
00886 make_points() const {
00887   if (is_exact_type(GeomPoints::get_class_type())) {
00888     return this;
00889   }
00890 
00891   // First, get a list of all of the vertices referenced by the
00892   // original primitive.
00893   BitArray bits;
00894   int num_vertices = get_num_vertices();
00895   if (is_indexed()) {
00896     CPT(GeomVertexArrayData) vertices = get_vertices();
00897     GeomVertexReader index(vertices, 0);
00898     for (int vi = 0; vi < num_vertices; ++vi) {
00899       nassertr(!index.is_at_end(), NULL);
00900       bits.set_bit(index.get_data1i());
00901     }
00902   } else {
00903     int first_vertex = get_first_vertex();
00904     bits.set_range(first_vertex, num_vertices);
00905   }
00906 
00907   // Now construct a new index array with just those bits.
00908   PT(GeomVertexArrayData) new_vertices = make_index_data();
00909   GeomVertexWriter new_index(new_vertices, 0);
00910   int p = bits.get_lowest_on_bit();
00911   while (p != -1) {
00912     while (bits.get_bit(p)) {
00913       new_index.add_data1i(p);
00914       ++p;
00915     }
00916     int q = bits.get_next_higher_different_bit(p);
00917     if (q == p) {
00918       break;
00919     }
00920     p = q;
00921   }
00922 
00923   PT(GeomPrimitive) points = new GeomPoints(UH_dynamic);
00924   points->set_vertices(new_vertices);
00925 
00926   return points;
00927 }
00928 
00929 ////////////////////////////////////////////////////////////////////
00930 //     Function: GeomPrimitive::get_num_bytes
00931 //       Access: Published
00932 //  Description: Returns the number of bytes consumed by the primitive
00933 //               and its index table(s).
00934 ////////////////////////////////////////////////////////////////////
00935 int GeomPrimitive::
00936 get_num_bytes() const {
00937   CDReader cdata(_cycler);
00938   int num_bytes = cdata->_ends.size() * sizeof(int) + sizeof(GeomPrimitive);
00939   if (!cdata->_vertices.is_null()) {
00940     num_bytes += cdata->_vertices.get_read_pointer()->get_data_size_bytes();
00941   }
00942 
00943   return num_bytes;
00944 }
00945 
00946 ////////////////////////////////////////////////////////////////////
00947 //     Function: GeomPrimitive::request_resident
00948 //       Access: Published
00949 //  Description: Returns true if the primitive data is currently
00950 //               resident in memory.  If this returns false, the
00951 //               primitive data will be brought back into memory
00952 //               shortly; try again later.
00953 ////////////////////////////////////////////////////////////////////
00954 bool GeomPrimitive::
00955 request_resident() const {
00956   CDReader cdata(_cycler);
00957 
00958   bool resident = true;
00959 
00960   if (!cdata->_vertices.is_null() &&
00961       !cdata->_vertices.get_read_pointer()->request_resident()) {
00962     resident = false;
00963   }
00964 
00965   if (is_composite() && cdata->_got_minmax) {
00966     if (!cdata->_mins.is_null() &&
00967         !cdata->_mins.get_read_pointer()->request_resident()) {
00968       resident = false;
00969     }
00970     if (!cdata->_maxs.is_null() &&
00971         !cdata->_maxs.get_read_pointer()->request_resident()) {
00972       resident = false;
00973     }
00974   }
00975 
00976   return resident;
00977 }
00978 
00979 ////////////////////////////////////////////////////////////////////
00980 //     Function: GeomPrimitive::output
00981 //       Access: Published, Virtual
00982 //  Description: 
00983 ////////////////////////////////////////////////////////////////////
00984 void GeomPrimitive::
00985 output(ostream &out) const {
00986   out << get_type() << ", " << get_num_primitives()
00987       << ", " << get_num_vertices();
00988 }
00989 
00990 ////////////////////////////////////////////////////////////////////
00991 //     Function: GeomPrimitive::write
00992 //       Access: Published, Virtual
00993 //  Description: 
00994 ////////////////////////////////////////////////////////////////////
00995 void GeomPrimitive::
00996 write(ostream &out, int indent_level) const {
00997   indent(out, indent_level)
00998     << get_type();
00999   if (is_indexed()) {
01000     out << " (indexed)";
01001   } else {
01002     out << " (nonindexed)";
01003   }
01004   out << ":\n";
01005   int num_primitives = get_num_primitives();
01006   int num_vertices = get_num_vertices();
01007   int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
01008   for (int i = 0; i < num_primitives; ++i) {
01009     indent(out, indent_level + 2)
01010       << "[";
01011     int begin = get_primitive_start(i);
01012     int end = get_primitive_end(i);
01013     for (int vi = begin; vi < end; vi++) {
01014       out << " " << get_vertex(vi);
01015     }
01016     out << " ]";
01017     if (end < num_vertices) {
01018       for (int ui = 0; ui < num_unused_vertices_per_primitive; ++ui) {
01019         if (end + ui < num_vertices) {
01020           out << " " << get_vertex(end + ui);
01021         } else {
01022           out << " ?";
01023         }
01024       }
01025     }
01026     out << "\n";
01027   }
01028 }
01029 
01030 ////////////////////////////////////////////////////////////////////
01031 //     Function: GeomPrimitive::modify_vertices
01032 //       Access: Published
01033 //  Description: Returns a modifiable pointer to the vertex index
01034 //               list, so application code can directly fiddle with
01035 //               this data.  Use with caution, since there are no
01036 //               checks that the data will be left in a stable state.
01037 //
01038 //               If this is called on a nonindexed primitive, it will
01039 //               implicitly be converted to an indexed primitive.
01040 //
01041 //               If num_vertices is not -1, it specifies an artificial
01042 //               limit to the number of vertices in the array.
01043 //               Otherwise, all of the vertices in the array will be
01044 //               used.
01045 //
01046 //               Don't call this in a downstream thread unless you
01047 //               don't mind it blowing away other changes you might
01048 //               have recently made in an upstream thread.
01049 //
01050 //               This method is intended for low-level usage only.
01051 //               There are higher-level methods for more common usage.
01052 //               We recommend you do not use this method directly.  If
01053 //               you do, be sure you know what you are doing!
01054 ////////////////////////////////////////////////////////////////////
01055 PT(GeomVertexArrayData) GeomPrimitive::
01056 modify_vertices(int num_vertices) {
01057   CDWriter cdata(_cycler, true);
01058   PT(GeomVertexArrayData) vertices = do_modify_vertices(cdata);
01059   cdata->_num_vertices = num_vertices;
01060   return vertices;
01061 }
01062 
01063 ////////////////////////////////////////////////////////////////////
01064 //     Function: GeomPrimitive::set_vertices
01065 //       Access: Published
01066 //  Description: Completely replaces the vertex index list with a new
01067 //               table.  Chances are good that you should also replace
01068 //               the ends list with set_ends() at the same time.
01069 //
01070 //               If num_vertices is not -1, it specifies an artificial
01071 //               limit to the number of vertices in the array.
01072 //               Otherwise, all of the vertices in the array will be
01073 //               used.
01074 //
01075 //               Don't call this in a downstream thread unless you
01076 //               don't mind it blowing away other changes you might
01077 //               have recently made in an upstream thread.
01078 //
01079 //               This method is intended for low-level usage only.
01080 //               There are higher-level methods for more common usage.
01081 //               We recommend you do not use this method directly.  If
01082 //               you do, be sure you know what you are doing!
01083 ////////////////////////////////////////////////////////////////////
01084 void GeomPrimitive::
01085 set_vertices(const GeomVertexArrayData *vertices, int num_vertices) {
01086   CDWriter cdata(_cycler, true);
01087   cdata->_vertices = (GeomVertexArrayData *)vertices;
01088   cdata->_num_vertices = num_vertices;
01089 
01090   cdata->_modified = Geom::get_next_modified();
01091   cdata->_got_minmax = false;
01092 }
01093 
01094 ////////////////////////////////////////////////////////////////////
01095 //     Function: GeomPrimitive::set_nonindexed_vertices
01096 //       Access: Published
01097 //  Description: Sets the primitive up as a nonindexed primitive,
01098 //               using the indicated vertex range.
01099 //
01100 //               Don't call this in a downstream thread unless you
01101 //               don't mind it blowing away other changes you might
01102 //               have recently made in an upstream thread.
01103 //
01104 //               This method is intended for low-level usage only.
01105 //               There are higher-level methods for more common usage.
01106 //               We recommend you do not use this method directly.  If
01107 //               you do, be sure you know what you are doing!
01108 ////////////////////////////////////////////////////////////////////
01109 void GeomPrimitive::
01110 set_nonindexed_vertices(int first_vertex, int num_vertices) {
01111   nassertv(num_vertices != -1);
01112   CDWriter cdata(_cycler, true);
01113   cdata->_vertices = (GeomVertexArrayData *)NULL;
01114   cdata->_first_vertex = first_vertex;
01115   cdata->_num_vertices = num_vertices;
01116 
01117   cdata->_modified = Geom::get_next_modified();
01118   cdata->_got_minmax = false;
01119 
01120   // Force the minmax to be recomputed.
01121   recompute_minmax(cdata);
01122 }
01123 
01124 ////////////////////////////////////////////////////////////////////
01125 //     Function: GeomPrimitive::modify_ends
01126 //       Access: Published
01127 //  Description: Returns a modifiable pointer to the primitive ends
01128 //               array, so application code can directly fiddle with
01129 //               this data.  Use with caution, since there are no
01130 //               checks that the data will be left in a stable state.
01131 //
01132 //               Note that simple primitive types, like triangles, do
01133 //               not have a ends array: since all the primitives
01134 //               have the same number of vertices, it is not needed.
01135 //
01136 //               Don't call this in a downstream thread unless you
01137 //               don't mind it blowing away other changes you might
01138 //               have recently made in an upstream thread.
01139 //
01140 //               This method is intended for low-level usage only.
01141 //               There are higher-level methods for more common usage.
01142 //               We recommend you do not use this method directly.  If
01143 //               you do, be sure you know what you are doing!
01144 ////////////////////////////////////////////////////////////////////
01145 PTA_int GeomPrimitive::
01146 modify_ends() {
01147   CDWriter cdata(_cycler, true);
01148 
01149   cdata->_modified = Geom::get_next_modified();
01150   cdata->_got_minmax = false;
01151 
01152   if (cdata->_ends.get_ref_count() > 1) {
01153     PTA_int new_ends;
01154     new_ends.v() = cdata->_ends.v();
01155     cdata->_ends = new_ends;
01156   }
01157   return cdata->_ends;
01158 }
01159 
01160 ////////////////////////////////////////////////////////////////////
01161 //     Function: GeomPrimitive::set_ends
01162 //       Access: Published
01163 //  Description: Completely replaces the primitive ends array with
01164 //               a new table.  Chances are good that you should also
01165 //               replace the vertices list with set_vertices() at the
01166 //               same time.
01167 //
01168 //               Note that simple primitive types, like triangles, do
01169 //               not have a ends array: since all the primitives
01170 //               have the same number of vertices, it is not needed.
01171 //
01172 //               Don't call this in a downstream thread unless you
01173 //               don't mind it blowing away other changes you might
01174 //               have recently made in an upstream thread.
01175 //
01176 //               This method is intended for low-level usage only.
01177 //               There are higher-level methods for more common usage.
01178 //               We recommend you do not use this method directly.  If
01179 //               you do, be sure you know what you are doing!
01180 ////////////////////////////////////////////////////////////////////
01181 void GeomPrimitive::
01182 set_ends(CPTA_int ends) {
01183   CDWriter cdata(_cycler, true);
01184   cdata->_ends = (PTA_int &)ends;
01185 
01186   cdata->_modified = Geom::get_next_modified();
01187   cdata->_got_minmax = false;
01188 }
01189 
01190 ////////////////////////////////////////////////////////////////////
01191 //     Function: GeomPrimitive::set_minmax
01192 //       Access: Published
01193 //  Description: Explicitly specifies the minimum and maximum
01194 //               vertices, as well as the lists of per-component min
01195 //               and max.
01196 //
01197 //               Use this method with extreme caution.  It's generally
01198 //               better to let the GeomPrimitive compute these
01199 //               explicitly, unless for some reason you can do it
01200 //               faster and you absolutely need the speed improvement.
01201 //
01202 //               Note that any modification to the vertex array will
01203 //               normally cause this to be recomputed, unless you set
01204 //               it immediately again.
01205 //
01206 //               This method is intended for low-level usage only.
01207 //               There are higher-level methods for more common usage.
01208 //               We recommend you do not use this method directly.  If
01209 //               you do, be sure you know what you are doing!
01210 ////////////////////////////////////////////////////////////////////
01211 void GeomPrimitive::
01212 set_minmax(int min_vertex, int max_vertex,
01213            GeomVertexArrayData *mins, GeomVertexArrayData *maxs) {
01214   CDWriter cdata(_cycler, true);
01215   cdata->_min_vertex = min_vertex;
01216   cdata->_max_vertex = max_vertex;
01217   cdata->_mins = mins;
01218   cdata->_maxs = maxs;
01219 
01220   cdata->_modified = Geom::get_next_modified();
01221   cdata->_got_minmax = true;
01222 }
01223 
01224 ////////////////////////////////////////////////////////////////////
01225 //     Function: GeomPrimitive::clear_minmax
01226 //       Access: Published
01227 //  Description: Undoes a previous call to set_minmax(), and allows
01228 //               the minimum and maximum values to be recomputed
01229 //               normally.
01230 //
01231 //               This method is intended for low-level usage only.
01232 //               There are higher-level methods for more common usage.
01233 //               We recommend you do not use this method directly.  If
01234 //               you do, be sure you know what you are doing!
01235 ////////////////////////////////////////////////////////////////////
01236 void GeomPrimitive::
01237 clear_minmax() {
01238   CDWriter cdata(_cycler, true);
01239   cdata->_got_minmax = false;
01240 }
01241 
01242 ////////////////////////////////////////////////////////////////////
01243 //     Function: GeomPrimitive::get_num_vertices_per_primitive
01244 //       Access: Published, Virtual
01245 //  Description: If the primitive type is a simple type in which all
01246 //               primitives have the same number of vertices, like
01247 //               triangles, returns the number of vertices per
01248 //               primitive.  If the primitive type is a more complex
01249 //               type in which different primitives might have
01250 //               different numbers of vertices, for instance a
01251 //               triangle strip, returns 0.
01252 //
01253 //               This method is intended for low-level usage only.
01254 //               There are higher-level methods for more common usage.
01255 //               We recommend you do not use this method directly.  If
01256 //               you do, be sure you know what you are doing!
01257 ////////////////////////////////////////////////////////////////////
01258 int GeomPrimitive::
01259 get_num_vertices_per_primitive() const {
01260   return 0;
01261 }
01262 
01263 ////////////////////////////////////////////////////////////////////
01264 //     Function: GeomPrimitive::get_min_num_vertices_per_primitive
01265 //       Access: Published, Virtual
01266 //  Description: Returns the minimum number of vertices that must be
01267 //               added before close_primitive() may legally be called.
01268 //
01269 //               This method is intended for low-level usage only.
01270 //               There are higher-level methods for more common usage.
01271 //               We recommend you do not use this method directly.  If
01272 //               you do, be sure you know what you are doing!
01273 ////////////////////////////////////////////////////////////////////
01274 int GeomPrimitive::
01275 get_min_num_vertices_per_primitive() const {
01276   return 3;
01277 }
01278 
01279 ////////////////////////////////////////////////////////////////////
01280 //     Function: GeomPrimitive::get_num_unused_vertices_per_primitive
01281 //       Access: Published, Virtual
01282 //  Description: Returns the number of vertices that are added between
01283 //               primitives that aren't, strictly speaking, part of
01284 //               the primitives themselves.  This is used, for
01285 //               instance, to define degenerate triangles to connect
01286 //               otherwise disconnected triangle strips.
01287 //
01288 //               This method is intended for low-level usage only.
01289 //               There are higher-level methods for more common usage.
01290 //               We recommend you do not use this method directly.  If
01291 //               you do, be sure you know what you are doing!
01292 ////////////////////////////////////////////////////////////////////
01293 int GeomPrimitive::
01294 get_num_unused_vertices_per_primitive() const {
01295   return 0;
01296 }
01297 
01298 ////////////////////////////////////////////////////////////////////
01299 //     Function: GeomPrimitive::prepare
01300 //       Access: Public
01301 //  Description: Indicates that the data should be enqueued to be
01302 //               prepared in the indicated prepared_objects at the
01303 //               beginning of the next frame.  This will ensure the
01304 //               data is already loaded into the GSG if it is expected
01305 //               to be rendered soon.
01306 //
01307 //               Use this function instead of prepare_now() to preload
01308 //               datas from a user interface standpoint.
01309 ////////////////////////////////////////////////////////////////////
01310 void GeomPrimitive::
01311 prepare(PreparedGraphicsObjects *prepared_objects) {
01312   if (is_indexed()) {
01313     prepared_objects->enqueue_index_buffer(this);
01314   }
01315 }
01316 
01317 ////////////////////////////////////////////////////////////////////
01318 //     Function: GeomPrimitive::is_prepared
01319 //       Access: Published
01320 //  Description: Returns true if the data has already been prepared
01321 //               or enqueued for preparation on the indicated GSG,
01322 //               false otherwise.
01323 ////////////////////////////////////////////////////////////////////
01324 bool GeomPrimitive::
01325 is_prepared(PreparedGraphicsObjects *prepared_objects) const {
01326   Contexts::const_iterator ci;
01327   ci = _contexts.find(prepared_objects);
01328   if (ci != _contexts.end()) {
01329     return true;
01330   }
01331   return prepared_objects->is_index_buffer_queued(this);
01332 }
01333 
01334 ////////////////////////////////////////////////////////////////////
01335 //     Function: GeomPrimitive::prepare_now
01336 //       Access: Public
01337 //  Description: Creates a context for the data on the particular
01338 //               GSG, if it does not already exist.  Returns the new
01339 //               (or old) IndexBufferContext.  This assumes that the
01340 //               GraphicsStateGuardian is the currently active
01341 //               rendering context and that it is ready to accept new
01342 //               datas.  If this is not necessarily the case, you
01343 //               should use prepare() instead.
01344 //
01345 //               Normally, this is not called directly except by the
01346 //               GraphicsStateGuardian; a data does not need to be
01347 //               explicitly prepared by the user before it may be
01348 //               rendered.
01349 ////////////////////////////////////////////////////////////////////
01350 IndexBufferContext *GeomPrimitive::
01351 prepare_now(PreparedGraphicsObjects *prepared_objects, 
01352             GraphicsStateGuardianBase *gsg) {
01353   nassertr(is_indexed(), NULL);
01354 
01355   Contexts::const_iterator ci;
01356   ci = _contexts.find(prepared_objects);
01357   if (ci != _contexts.end()) {
01358     return (*ci).second;
01359   }
01360 
01361   IndexBufferContext *ibc = prepared_objects->prepare_index_buffer_now(this, gsg);
01362   if (ibc != (IndexBufferContext *)NULL) {
01363     _contexts[prepared_objects] = ibc;
01364   }
01365   return ibc;
01366 }
01367 
01368 ////////////////////////////////////////////////////////////////////
01369 //     Function: GeomPrimitive::release
01370 //       Access: Public
01371 //  Description: Frees the data context only on the indicated object,
01372 //               if it exists there.  Returns true if it was released,
01373 //               false if it had not been prepared.
01374 ////////////////////////////////////////////////////////////////////
01375 bool GeomPrimitive::
01376 release(PreparedGraphicsObjects *prepared_objects) {
01377   Contexts::iterator ci;
01378   ci = _contexts.find(prepared_objects);
01379   if (ci != _contexts.end()) {
01380     IndexBufferContext *ibc = (*ci).second;
01381     prepared_objects->release_index_buffer(ibc);
01382     return true;
01383   }
01384 
01385   // Maybe it wasn't prepared yet, but it's about to be.
01386   return prepared_objects->dequeue_index_buffer(this);
01387 }
01388 
01389 ////////////////////////////////////////////////////////////////////
01390 //     Function: GeomPrimitive::release_all
01391 //       Access: Public
01392 //  Description: Frees the context allocated on all objects for which
01393 //               the data has been declared.  Returns the number of
01394 //               contexts which have been freed.
01395 ////////////////////////////////////////////////////////////////////
01396 int GeomPrimitive::
01397 release_all() {
01398   // We have to traverse a copy of the _contexts list, because the
01399   // PreparedGraphicsObjects object will call clear_prepared() in response
01400   // to each release_index_buffer(), and we don't want to be modifying the
01401   // _contexts list while we're traversing it.
01402   Contexts temp = _contexts;
01403   int num_freed = (int)_contexts.size();
01404 
01405   Contexts::const_iterator ci;
01406   for (ci = temp.begin(); ci != temp.end(); ++ci) {
01407     PreparedGraphicsObjects *prepared_objects = (*ci).first;
01408     IndexBufferContext *ibc = (*ci).second;
01409     prepared_objects->release_index_buffer(ibc);
01410   }
01411 
01412   // Now that we've called release_index_buffer() on every known context,
01413   // the _contexts list should have completely emptied itself.
01414   nassertr(_contexts.empty(), num_freed);
01415 
01416   return num_freed;
01417 }
01418 
01419 ////////////////////////////////////////////////////////////////////
01420 //     Function: GeomPrimitive::get_index_format
01421 //       Access: Public
01422 //  Description: Returns a registered format appropriate for using to
01423 //               store the index table.
01424 ////////////////////////////////////////////////////////////////////
01425 CPT(GeomVertexArrayFormat) GeomPrimitive::
01426 get_index_format() const {
01427   PT(GeomVertexArrayFormat) format = new GeomVertexArrayFormat;
01428   // It's important that the index format *not* respect the global
01429   // setting of vertex-column-alignment.  It needs to be tightly
01430   // packed, so we specify an explict column_alignment of 1.
01431   format->add_column(InternalName::get_index(), 1, get_index_type(), C_index, 0, 1);
01432   return GeomVertexArrayFormat::register_format(format);
01433 }
01434 
01435 ////////////////////////////////////////////////////////////////////
01436 //     Function: GeomPrimitive::clear_prepared
01437 //       Access: Private
01438 //  Description: Removes the indicated PreparedGraphicsObjects table
01439 //               from the data array's table, without actually
01440 //               releasing the data array.  This is intended to be
01441 //               called only from
01442 //               PreparedGraphicsObjects::release_index_buffer(); it should
01443 //               never be called by user code.
01444 ////////////////////////////////////////////////////////////////////
01445 void GeomPrimitive::
01446 clear_prepared(PreparedGraphicsObjects *prepared_objects) {
01447   Contexts::iterator ci;
01448   ci = _contexts.find(prepared_objects);
01449   if (ci != _contexts.end()) {
01450     _contexts.erase(ci);
01451   } else {
01452     // If this assertion fails, clear_prepared() was given a
01453     // prepared_objects which the data array didn't know about.
01454     nassertv(false);
01455   }
01456 }
01457 
01458 ////////////////////////////////////////////////////////////////////
01459 //     Function: GeomPrimitive::get_highest_index_value
01460 //       Access: Private, Static
01461 //  Description: Returns the largest index value that can be stored in
01462 //               an index of the indicated type.
01463 ////////////////////////////////////////////////////////////////////
01464 int GeomPrimitive::
01465 get_highest_index_value(NumericType index_type) {
01466   switch (index_type) {
01467   case NT_uint8:
01468     return 0xff;
01469 
01470   case NT_uint16:
01471     return 0xffff;
01472 
01473   case NT_uint32:
01474     // We don't actually allow use of the sign bit, since all of our
01475     // functions receive an "int" instead of an "unsigned int".
01476     return 0x7fffffff;
01477 
01478   default:
01479     return 0;
01480   }
01481 }
01482 
01483 ////////////////////////////////////////////////////////////////////
01484 //     Function: GeomPrimitive::calc_tight_bounds
01485 //       Access: Public, Virtual
01486 //  Description: Expands min_point and max_point to include all of the
01487 //               vertices in the Geom, if any (or the data of any
01488 //               point type, for instance, texture coordinates--based
01489 //               on the column name).  found_any is set true if any
01490 //               points are found.  It is the caller's responsibility
01491 //               to initialize min_point, max_point, and found_any
01492 //               before calling this function.
01493 ////////////////////////////////////////////////////////////////////
01494 void GeomPrimitive::
01495 calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
01496                   bool &found_any, 
01497                   const GeomVertexData *vertex_data,
01498                   bool got_mat, const LMatrix4 &mat,
01499                   const InternalName *column_name,
01500                   Thread *current_thread) const {
01501   GeomVertexReader reader(vertex_data, column_name, current_thread);
01502   if (!reader.has_column()) {
01503     // No vertex data.
01504     return;
01505   }
01506 
01507   CDReader cdata(_cycler, current_thread);
01508 
01509   if (cdata->_vertices.is_null()) {
01510     // Nonindexed case.
01511     nassertv(cdata->_num_vertices != -1);
01512     if (got_mat) {
01513       for (int i = 0; i < cdata->_num_vertices; i++) {
01514         reader.set_row_unsafe(cdata->_first_vertex + i);
01515         LPoint3 vertex = mat.xform_point(reader.get_data3());
01516         
01517         if (found_any) {
01518           min_point.set(min(min_point[0], vertex[0]),
01519                         min(min_point[1], vertex[1]),
01520                         min(min_point[2], vertex[2]));
01521           max_point.set(max(max_point[0], vertex[0]),
01522                         max(max_point[1], vertex[1]),
01523                         max(max_point[2], vertex[2]));
01524         } else {
01525           min_point = vertex;
01526           max_point = vertex;
01527           found_any = true;
01528         }
01529       }
01530     } else {
01531       for (int i = 0; i < cdata->_num_vertices; i++) {
01532         reader.set_row_unsafe(cdata->_first_vertex + i);
01533         const LVecBase3 &vertex = reader.get_data3();
01534         
01535         if (found_any) {
01536           min_point.set(min(min_point[0], vertex[0]),
01537                         min(min_point[1], vertex[1]),
01538                         min(min_point[2], vertex[2]));
01539           max_point.set(max(max_point[0], vertex[0]),
01540                         max(max_point[1], vertex[1]),
01541                         max(max_point[2], vertex[2]));
01542         } else {
01543           min_point = vertex;
01544           max_point = vertex;
01545           found_any = true;
01546         }
01547       }
01548     }
01549 
01550   } else {
01551     // Indexed case.
01552     GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0, current_thread);
01553 
01554     if (got_mat) {
01555       while (!index.is_at_end()) {
01556         int ii = index.get_data1i();
01557         reader.set_row_unsafe(ii);
01558         LPoint3 vertex = mat.xform_point(reader.get_data3());
01559         
01560         if (found_any) {
01561           min_point.set(min(min_point[0], vertex[0]),
01562                         min(min_point[1], vertex[1]),
01563                         min(min_point[2], vertex[2]));
01564           max_point.set(max(max_point[0], vertex[0]),
01565                         max(max_point[1], vertex[1]),
01566                         max(max_point[2], vertex[2]));
01567         } else {
01568           min_point = vertex;
01569           max_point = vertex;
01570           found_any = true;
01571         }
01572       }
01573     } else {
01574       while (!index.is_at_end()) {
01575         int ii = index.get_data1i();
01576         reader.set_row_unsafe(ii);
01577         const LVecBase3 &vertex = reader.get_data3();
01578         
01579         if (found_any) {
01580           min_point.set(min(min_point[0], vertex[0]),
01581                         min(min_point[1], vertex[1]),
01582                         min(min_point[2], vertex[2]));
01583           max_point.set(max(max_point[0], vertex[0]),
01584                         max(max_point[1], vertex[1]),
01585                         max(max_point[2], vertex[2]));
01586         } else {
01587           min_point = vertex;
01588           max_point = vertex;
01589           found_any = true;
01590         }
01591       }
01592     }
01593   }
01594 }
01595 
01596 ////////////////////////////////////////////////////////////////////
01597 //     Function: GeomPrimitive::decompose_impl
01598 //       Access: Protected, Virtual
01599 //  Description: Decomposes a complex primitive type into a simpler
01600 //               primitive type, for instance triangle strips to
01601 //               triangles, and returns a pointer to the new primitive
01602 //               definition.  If the decomposition cannot be
01603 //               performed, this might return the original object.
01604 //
01605 //               This method is useful for application code that wants
01606 //               to iterate through the set of triangles on the
01607 //               primitive without having to write handlers for each
01608 //               possible kind of primitive type.
01609 ////////////////////////////////////////////////////////////////////
01610 CPT(GeomPrimitive) GeomPrimitive::
01611 decompose_impl() const {
01612   return this;
01613 }
01614 
01615 ////////////////////////////////////////////////////////////////////
01616 //     Function: GeomPrimitive::rotate_impl
01617 //       Access: Protected, Virtual
01618 //  Description: The virtual implementation of rotate().
01619 ////////////////////////////////////////////////////////////////////
01620 CPT(GeomVertexArrayData) GeomPrimitive::
01621 rotate_impl() const {
01622   // The default implementation doesn't even try to do anything.
01623   nassertr(false, NULL);
01624   return NULL;
01625 }
01626 
01627 ////////////////////////////////////////////////////////////////////
01628 //     Function: GeomPrimitive::doubleside_impl
01629 //       Access: Protected, Virtual
01630 //  Description: The virtual implementation of doubleside().
01631 ////////////////////////////////////////////////////////////////////
01632 CPT(GeomPrimitive) GeomPrimitive::
01633 doubleside_impl() const {
01634   return this;
01635 }
01636 
01637 ////////////////////////////////////////////////////////////////////
01638 //     Function: GeomPrimitive::reverse_impl
01639 //       Access: Protected, Virtual
01640 //  Description: The virtual implementation of reverse().
01641 ////////////////////////////////////////////////////////////////////
01642 CPT(GeomPrimitive) GeomPrimitive::
01643 reverse_impl() const {
01644   return this;
01645 }
01646 
01647 ////////////////////////////////////////////////////////////////////
01648 //     Function: GeomPrimitive::requires_unused_vertices
01649 //       Access: Protected, Virtual
01650 //  Description: Should be redefined to return true in any primitive
01651 //               that implements append_unused_vertices().
01652 ////////////////////////////////////////////////////////////////////
01653 bool GeomPrimitive::
01654 requires_unused_vertices() const {
01655   return false;
01656 }
01657 
01658 ////////////////////////////////////////////////////////////////////
01659 //     Function: GeomPrimitive::append_unused_vertices
01660 //       Access: Protected, Virtual
01661 //  Description: Called when a new primitive is begun (other than the
01662 //               first primitive), this should add some degenerate
01663 //               vertices between primitives, if the primitive type
01664 //               requires that.  The second parameter is the first
01665 //               vertex that begins the new primitive.
01666 //
01667 //               This method is only called if
01668 //               requires_unused_vertices(), above, returns true.
01669 ////////////////////////////////////////////////////////////////////
01670 void GeomPrimitive::
01671 append_unused_vertices(GeomVertexArrayData *, int) {
01672 }
01673 
01674 ////////////////////////////////////////////////////////////////////
01675 //     Function: GeomPrimitive::recompute_minmax
01676 //       Access: Private
01677 //  Description: Recomputes the _min_vertex and _max_vertex values if
01678 //               necessary.
01679 ////////////////////////////////////////////////////////////////////
01680 void GeomPrimitive::
01681 recompute_minmax(GeomPrimitive::CData *cdata) {
01682   if (cdata->_vertices.is_null()) {
01683     // In the nonindexed case, we don't need to do much (the
01684     // minmax is trivial).
01685     nassertv(cdata->_num_vertices != -1);
01686     cdata->_min_vertex = cdata->_first_vertex;
01687     cdata->_max_vertex = cdata->_first_vertex + cdata->_num_vertices - 1;
01688     cdata->_mins.clear();
01689     cdata->_maxs.clear();
01690 
01691   } else {
01692     int num_vertices = cdata->_vertices.get_read_pointer()->get_num_rows();
01693 
01694     if (num_vertices == 0) {
01695       // Or if we don't have any vertices, the minmax is also trivial.
01696       cdata->_min_vertex = 0;
01697       cdata->_max_vertex = 0;
01698       cdata->_mins.clear();
01699       cdata->_maxs.clear();
01700       
01701     } else if (get_num_vertices_per_primitive() == 0) {
01702       // This is a complex primitive type like a triangle strip; compute
01703       // the minmax of each primitive (as well as the overall minmax).
01704       GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0);
01705       
01706       cdata->_mins = make_index_data();
01707       cdata->_maxs = make_index_data();
01708       
01709       GeomVertexWriter mins(cdata->_mins.get_write_pointer(), 0);
01710       mins.reserve_num_rows(cdata->_ends.size());
01711       GeomVertexWriter maxs(cdata->_maxs.get_write_pointer(), 0);
01712       maxs.reserve_num_rows(cdata->_ends.size());
01713       
01714       int pi = 0;
01715       
01716       unsigned int vertex = index.get_data1i();
01717       cdata->_min_vertex = vertex;
01718       cdata->_max_vertex = vertex;
01719       unsigned int min_prim = vertex;
01720       unsigned int max_prim = vertex;
01721       
01722       for (int vi = 1; vi < num_vertices; ++vi) {
01723         nassertv(!index.is_at_end());
01724         unsigned int vertex = index.get_data1i();
01725         cdata->_min_vertex = min(cdata->_min_vertex, vertex);
01726         cdata->_max_vertex = max(cdata->_max_vertex, vertex);
01727 
01728         nassertv(pi < (int)cdata->_ends.size());
01729         if (vi == cdata->_ends[pi]) {
01730           mins.add_data1i(min_prim);
01731           maxs.add_data1i(max_prim);
01732           min_prim = vertex;
01733           max_prim = vertex;
01734           ++pi;
01735           
01736         } else {
01737           min_prim = min(min_prim, vertex);
01738           max_prim = max(max_prim, vertex);
01739         }
01740       }
01741       mins.add_data1i(min_prim);
01742       maxs.add_data1i(max_prim);
01743       nassertv(mins.get_array_data()->get_num_rows() == (int)cdata->_ends.size());
01744       
01745     } else {
01746       // This is a simple primitive type like a triangle; just compute
01747       // the overall minmax.
01748       GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0);
01749       
01750       cdata->_mins.clear();
01751       cdata->_maxs.clear();
01752       
01753       unsigned int vertex = index.get_data1i();
01754       cdata->_min_vertex = vertex;
01755       cdata->_max_vertex = vertex;
01756       
01757       for (int vi = 1; vi < num_vertices; ++vi) {
01758         nassertv(!index.is_at_end());
01759         unsigned int vertex = index.get_data1i();
01760         cdata->_min_vertex = min(cdata->_min_vertex, vertex);
01761         cdata->_max_vertex = max(cdata->_max_vertex, vertex);
01762       }
01763     }
01764   }
01765     
01766   cdata->_got_minmax = true;
01767 }
01768 
01769 ////////////////////////////////////////////////////////////////////
01770 //     Function: GeomPrimitive::do_make_indexed
01771 //       Access: Private
01772 //  Description: The private implementation of make_indexed().
01773 ////////////////////////////////////////////////////////////////////
01774 void GeomPrimitive::
01775 do_make_indexed(CData *cdata) {
01776   if (cdata->_vertices.is_null()) {
01777     if (gobj_cat.is_debug()) {
01778       gobj_cat.debug()
01779         << this << ".make_indexed()\n";
01780     }
01781 
01782     nassertv(cdata->_num_vertices != -1);
01783     cdata->_vertices = make_index_data();
01784     GeomVertexWriter index(cdata->_vertices.get_write_pointer(), 0);
01785     index.reserve_num_rows(cdata->_num_vertices);
01786     for (int i = 0; i < cdata->_num_vertices; ++i) {
01787       index.add_data1i(i + cdata->_first_vertex);
01788     }
01789     cdata->_num_vertices = -1;
01790   }
01791 }
01792 
01793 ////////////////////////////////////////////////////////////////////
01794 //     Function: GeomPrimitive::consider_elevate_index_type
01795 //       Access: Private
01796 //  Description: If the indicated new vertex index won't fit in the
01797 //               specified index type, automatically elevates the
01798 //               index type to the next available size.
01799 ////////////////////////////////////////////////////////////////////
01800 void GeomPrimitive::
01801 consider_elevate_index_type(CData *cdata, int vertex) {
01802   switch (cdata->_index_type) {
01803   case NT_uint8:
01804     if (vertex > 0xff) {
01805       do_set_index_type(cdata, NT_uint16);
01806     }
01807     break;
01808 
01809   case NT_uint16:
01810     if (vertex > 0xffff) {
01811       do_set_index_type(cdata, NT_uint32);
01812     }
01813     break;
01814 
01815   case NT_uint32:
01816     // Not much we can do here.
01817     nassertv(vertex <= 0x7fffffff);
01818     break;
01819 
01820   default:
01821     break;
01822   }
01823 }
01824 
01825 ////////////////////////////////////////////////////////////////////
01826 //     Function: GeomPrimitive::do_set_index_type
01827 //       Access: Private
01828 //  Description: The private implementation of set_index_type().
01829 ////////////////////////////////////////////////////////////////////
01830 void GeomPrimitive::
01831 do_set_index_type(CData *cdata, GeomPrimitive::NumericType index_type) {
01832   cdata->_index_type = index_type;
01833 
01834   if (gobj_cat.is_debug()) {
01835     gobj_cat.debug()
01836       << this << ".set_index_type(" << index_type << ")\n";
01837   }
01838 
01839   if (!cdata->_vertices.is_null()) {
01840     CPT(GeomVertexArrayFormat) new_format = get_index_format();
01841     
01842     CPT(GeomVertexArrayData) array_obj = cdata->_vertices.get_read_pointer();
01843     if (array_obj->get_array_format() != new_format) {
01844       PT(GeomVertexArrayData) new_vertices = make_index_data();
01845       new_vertices->set_num_rows(array_obj->get_num_rows());
01846 
01847       GeomVertexReader from(array_obj, 0);
01848       GeomVertexWriter to(new_vertices, 0);
01849       
01850       while (!from.is_at_end()) {
01851         to.set_data1i(from.get_data1i());
01852       }
01853       cdata->_vertices = new_vertices;
01854       cdata->_got_minmax = false;
01855     }
01856   }
01857 }
01858 
01859 ////////////////////////////////////////////////////////////////////
01860 //     Function: GeomPrimitive::do_modify_vertices
01861 //       Access: Private
01862 //  Description: The private implementation of modify_vertices().
01863 ////////////////////////////////////////////////////////////////////
01864 PT(GeomVertexArrayData) GeomPrimitive::
01865 do_modify_vertices(GeomPrimitive::CData *cdata) {
01866   if (cdata->_vertices.is_null()) {
01867     do_make_indexed(cdata);
01868   }
01869 
01870   PT(GeomVertexArrayData) vertices = cdata->_vertices.get_write_pointer();
01871 
01872   cdata->_modified = Geom::get_next_modified();
01873   cdata->_got_minmax = false;
01874   return vertices;
01875 }
01876 
01877 ////////////////////////////////////////////////////////////////////
01878 //     Function: GeomPrimitive::write_datagram
01879 //       Access: Public, Virtual
01880 //  Description: Writes the contents of this object to the datagram
01881 //               for shipping out to a Bam file.
01882 ////////////////////////////////////////////////////////////////////
01883 void GeomPrimitive::
01884 write_datagram(BamWriter *manager, Datagram &dg) {
01885   TypedWritable::write_datagram(manager, dg);
01886 
01887   manager->write_cdata(dg, _cycler);
01888 }
01889 
01890 ////////////////////////////////////////////////////////////////////
01891 //     Function: GeomPrimitive::finalize
01892 //       Access: Public, Virtual
01893 //  Description: Called by the BamReader to perform any final actions
01894 //               needed for setting up the object after all objects
01895 //               have been read and all pointers have been completed.
01896 ////////////////////////////////////////////////////////////////////
01897 void GeomPrimitive::
01898 finalize(BamReader *manager) {
01899   const GeomVertexArrayData *vertices = get_vertices();
01900   if (vertices != (GeomVertexArrayData *)NULL) {
01901     set_usage_hint(vertices->get_usage_hint());
01902   }
01903 }
01904 
01905 ////////////////////////////////////////////////////////////////////
01906 //     Function: GeomPrimitive::fillin
01907 //       Access: Protected
01908 //  Description: This internal function is called by make_from_bam to
01909 //               read in all of the relevant data from the BamFile for
01910 //               the new GeomPrimitive.
01911 ////////////////////////////////////////////////////////////////////
01912 void GeomPrimitive::
01913 fillin(DatagramIterator &scan, BamReader *manager) {
01914   TypedWritable::fillin(scan, manager);
01915 
01916   manager->read_cdata(scan, _cycler);
01917   manager->register_finalize(this);
01918 }
01919 
01920 ////////////////////////////////////////////////////////////////////
01921 //     Function: GeomPrimitive::CData::make_copy
01922 //       Access: Public, Virtual
01923 //  Description:
01924 ////////////////////////////////////////////////////////////////////
01925 CycleData *GeomPrimitive::CData::
01926 make_copy() const {
01927   return new CData(*this);
01928 }
01929 
01930 ////////////////////////////////////////////////////////////////////
01931 //     Function: GeomPrimitive::CData::write_datagram
01932 //       Access: Public, Virtual
01933 //  Description: Writes the contents of this object to the datagram
01934 //               for shipping out to a Bam file.
01935 ////////////////////////////////////////////////////////////////////
01936 void GeomPrimitive::CData::
01937 write_datagram(BamWriter *manager, Datagram &dg) const {
01938   dg.add_uint8(_shade_model);
01939   dg.add_int32(_first_vertex);
01940   dg.add_int32(_num_vertices);
01941   dg.add_uint8(_index_type);
01942   dg.add_uint8(_usage_hint);
01943 
01944   manager->write_pointer(dg, _vertices.get_read_pointer());
01945   WRITE_PTA(manager, dg, IPD_int::write_datagram, _ends);
01946 }
01947 
01948 ////////////////////////////////////////////////////////////////////
01949 //     Function: GeomPrimitive::CData::complete_pointers
01950 //       Access: Public, Virtual
01951 //  Description: Receives an array of pointers, one for each time
01952 //               manager->read_pointer() was called in fillin().
01953 //               Returns the number of pointers processed.
01954 ////////////////////////////////////////////////////////////////////
01955 int GeomPrimitive::CData::
01956 complete_pointers(TypedWritable **p_list, BamReader *manager) {
01957   int pi = CycleData::complete_pointers(p_list, manager);
01958 
01959   _vertices = DCAST(GeomVertexArrayData, p_list[pi++]);    
01960 
01961   if (manager->get_file_minor_ver() < 6 && !_vertices.is_null()) {
01962     // Older bam files might have a meaningless number in
01963     // _num_vertices if the primitive is indexed.  Nowadays, this
01964     // number is always considered meaningful unless it is -1.
01965     _num_vertices = -1;
01966   }
01967 
01968   return pi;
01969 }
01970 
01971 ////////////////////////////////////////////////////////////////////
01972 //     Function: GeomPrimitive::CData::fillin
01973 //       Access: Public, Virtual
01974 //  Description: This internal function is called by make_from_bam to
01975 //               read in all of the relevant data from the BamFile for
01976 //               the new GeomPrimitive.
01977 ////////////////////////////////////////////////////////////////////
01978 void GeomPrimitive::CData::
01979 fillin(DatagramIterator &scan, BamReader *manager) {
01980   _shade_model = (ShadeModel)scan.get_uint8();
01981   _first_vertex = scan.get_int32();
01982   _num_vertices = scan.get_int32();
01983   _index_type = (NumericType)scan.get_uint8();
01984   _usage_hint = (UsageHint)scan.get_uint8();
01985 
01986   manager->read_pointer(scan);
01987   READ_PTA(manager, scan, IPD_int::read_datagram, _ends);
01988 
01989   _modified = Geom::get_next_modified();
01990   _got_minmax = false;
01991 }
01992 
01993 ////////////////////////////////////////////////////////////////////
01994 //     Function: GeomPrimitivePipelineReader::check_minmax
01995 //       Access: Public
01996 //  Description: Ensures that the primitive's minmax cache has been
01997 //               computed.
01998 ////////////////////////////////////////////////////////////////////
01999 void GeomPrimitivePipelineReader::
02000 check_minmax() const {
02001   if (!_cdata->_got_minmax) {
02002     // We'll need to get a fresh pointer, since another thread might
02003     // already have modified the pointer on the object since we
02004     // queried it.
02005     {
02006 #ifdef DO_PIPELINING
02007       unref_delete((CycleData *)_cdata);
02008 #endif
02009       GeomPrimitive::CDWriter fresh_cdata(((GeomPrimitive *)_object.p())->_cycler, 
02010                                           false, _current_thread);
02011       ((GeomPrimitivePipelineReader *)this)->_cdata = fresh_cdata;
02012 #ifdef DO_PIPELINING
02013       _cdata->ref();
02014 #endif
02015 
02016       if (!fresh_cdata->_got_minmax) {
02017         // The cache is still stale.  We have to do the work of
02018         // freshening it.
02019         ((GeomPrimitive *)_object.p())->recompute_minmax(fresh_cdata);
02020         nassertv(fresh_cdata->_got_minmax);
02021       }
02022 
02023       // When fresh_cdata goes out of scope, its write lock is
02024       // released, and _cdata reverts to our usual convention of an
02025       // unlocked copy of the data.
02026     }
02027   }
02028 
02029   nassertv(_cdata->_got_minmax);
02030 }
02031 
02032 ////////////////////////////////////////////////////////////////////
02033 //     Function: GeomPrimitivePipelineReader::get_first_vertex
02034 //       Access: Public
02035 //  Description: 
02036 ////////////////////////////////////////////////////////////////////
02037 int GeomPrimitivePipelineReader::
02038 get_first_vertex() const {
02039   if (_cdata->_vertices.is_null()) {
02040     return _cdata->_first_vertex;
02041   } else if (_vertices_reader->get_num_rows() == 0) {
02042     return 0;
02043   } else {
02044     GeomVertexReader index(_cdata->_vertices.get_read_pointer(), 0);
02045     return index.get_data1i();
02046   }
02047 }
02048 
02049 ////////////////////////////////////////////////////////////////////
02050 //     Function: GeomPrimitivePipelineReader::get_vertex
02051 //       Access: Public
02052 //  Description: Returns the ith vertex index in the table.
02053 ////////////////////////////////////////////////////////////////////
02054 int GeomPrimitivePipelineReader::
02055 get_vertex(int i) const {
02056   if (!_cdata->_vertices.is_null()) {
02057     // The indexed case.
02058     nassertr(i >= 0 && i < _vertices_reader->get_num_rows(), -1);
02059 
02060     GeomVertexReader index(_cdata->_vertices.get_read_pointer(), 0);
02061     index.set_row_unsafe(i);
02062     return index.get_data1i();
02063 
02064   } else {
02065     // The nonindexed case.
02066     return _cdata->_first_vertex + i;
02067   }
02068 }
02069 
02070 ////////////////////////////////////////////////////////////////////
02071 //     Function: GeomPrimitivePipelineReader::get_num_primitives
02072 //       Access: Public
02073 //  Description: 
02074 ////////////////////////////////////////////////////////////////////
02075 int GeomPrimitivePipelineReader::
02076 get_num_primitives() const {
02077   int num_vertices_per_primitive = _object->get_num_vertices_per_primitive();
02078 
02079   if (num_vertices_per_primitive == 0) {
02080     // This is a complex primitive type like a triangle strip: each
02081     // primitive uses a different number of vertices.
02082     return _cdata->_ends.size();
02083 
02084   } else {
02085     // This is a simple primitive type like a triangle: each primitive
02086     // uses the same number of vertices.
02087     return (get_num_vertices() / num_vertices_per_primitive);
02088   }
02089 }
02090 
02091 ////////////////////////////////////////////////////////////////////
02092 //     Function: GeomPrimitivePipelineReader::check_valid
02093 //       Access: Public
02094 //  Description:
02095 ////////////////////////////////////////////////////////////////////
02096 bool GeomPrimitivePipelineReader::
02097 check_valid(const GeomVertexDataPipelineReader *data_reader) const {
02098   return get_num_vertices() == 0 ||
02099     get_max_vertex() < data_reader->get_num_rows();
02100 }
 All Classes Functions Variables Enumerations