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