Panda3D

eggVertexPool.cxx

00001 // Filename: eggVertexPool.cxx
00002 // Created by:  drose (16Jan99)
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 "eggVertexPool.h"
00016 #include "eggPrimitive.h"
00017 #include "eggUtilities.h"
00018 #include <iterator>
00019 
00020 #include "indent.h"
00021 
00022 #include <iterator>
00023 
00024 TypeHandle EggVertexPool::_type_handle;
00025 
00026 ////////////////////////////////////////////////////////////////////
00027 //     Function: EggVertexPool::Constructor
00028 //       Access: Public
00029 //  Description:
00030 ////////////////////////////////////////////////////////////////////
00031 EggVertexPool::
00032 EggVertexPool(const string &name) : EggNode(name) {
00033   _highest_index = -1;
00034 }
00035 
00036 ////////////////////////////////////////////////////////////////////
00037 //     Function: EggVertexPool::Copy Constructor
00038 //       Access: Public
00039 //  Description: Copying a vertex pool is of questionable value, since
00040 //               it will copy all of the vertices and assign new
00041 //               pointers to them all. There will be no polygons
00042 //               referring to the new vertices.
00043 ////////////////////////////////////////////////////////////////////
00044 EggVertexPool::
00045 EggVertexPool(const EggVertexPool &copy) : EggNode(copy) {
00046   iterator i;
00047   for (i = copy.begin(); i != copy.end(); ++i) {
00048     add_vertex(new EggVertex(*(*i)), (*i)->get_index());
00049   }
00050 }
00051 
00052 
00053 ////////////////////////////////////////////////////////////////////
00054 //     Function: EggVertexPool::Destructor
00055 //       Access: Public
00056 //  Description:
00057 ////////////////////////////////////////////////////////////////////
00058 EggVertexPool::
00059 ~EggVertexPool() {
00060   // Remove all vertices from the pool when it destructs.
00061 
00062   // Sanity check.
00063   nassertv(_index_vertices.size() == _unique_vertices.size());
00064 
00065   IndexVertices::iterator ivi;
00066   for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
00067     int index = (*ivi).first;
00068     EggVertex *vertex = (*ivi).second;
00069 
00070     // Sanity checks on our internal data structures.
00071     nassertv(vertex->_pool == this);
00072     nassertv(vertex->get_index() == index);
00073 
00074     vertex->_pool = NULL;
00075     vertex->_index = -1;
00076   }
00077 
00078   _index_vertices.clear();
00079   _unique_vertices.clear();
00080 }
00081 
00082 ////////////////////////////////////////////////////////////////////
00083 //     Function: EggVertexPool::has_forward_vertices
00084 //       Access: Published
00085 //  Description: Returns true if any vertices in the pool are
00086 //               undefined forward-reference vertices, false if all
00087 //               vertices are defined.
00088 ////////////////////////////////////////////////////////////////////
00089 bool EggVertexPool::
00090 has_forward_vertices() const {
00091   IndexVertices::const_iterator ivi;
00092   for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
00093     EggVertex *vertex = (*ivi).second;
00094     if (vertex->is_forward_reference()) {
00095       return true;
00096     }
00097   }
00098 
00099   return false;
00100 }
00101 
00102 ////////////////////////////////////////////////////////////////////
00103 //     Function: EggVertexPool::has_defined_vertices
00104 //       Access: Published
00105 //  Description: Returns true if any vertices in the pool are
00106 //               fully defined vertices, false if all vertices are
00107 //               forward references.
00108 ////////////////////////////////////////////////////////////////////
00109 bool EggVertexPool::
00110 has_defined_vertices() const {
00111   IndexVertices::const_iterator ivi;
00112   for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
00113     EggVertex *vertex = (*ivi).second;
00114     if (!vertex->is_forward_reference()) {
00115       return true;
00116     }
00117   }
00118 
00119   return false;
00120 }
00121 
00122 ////////////////////////////////////////////////////////////////////
00123 //     Function: EggVertexPool::get_vertex
00124 //       Access: Public
00125 //  Description: Returns the vertex in the pool with the indicated
00126 //               index number, or NULL if no vertices have that index
00127 //               number.
00128 ////////////////////////////////////////////////////////////////////
00129 EggVertex *EggVertexPool::
00130 get_vertex(int index) const {
00131   IndexVertices::const_iterator ivi = _index_vertices.find(index);
00132 
00133   if (ivi == _index_vertices.end()) {
00134     return NULL;
00135   } else {
00136     EggVertex *vertex = (*ivi).second;
00137     if (vertex->is_forward_reference()) {
00138       return NULL;
00139     }
00140     return vertex;
00141   }
00142 }
00143 
00144 ////////////////////////////////////////////////////////////////////
00145 //     Function: EggVertexPool::get_forward_vertex
00146 //       Access: Public
00147 //  Description: Returns the vertex in the pool with the indicated
00148 //               index number.  If there is not a vertex in the pool
00149 //               with the indicated index number, creates a special
00150 //               forward-reference EggVertex that has no data, on the
00151 //               assumption that the vertex pool has not yet been
00152 //               fully read and more data will be available later.
00153 ////////////////////////////////////////////////////////////////////
00154 EggVertex *EggVertexPool::
00155 get_forward_vertex(int index) {
00156   nassertr(index >= 0, NULL);
00157 
00158   IndexVertices::const_iterator ivi = _index_vertices.find(index);
00159 
00160   if (ivi == _index_vertices.end()) {
00161     PT(EggVertex) forward = new EggVertex;
00162     forward->_forward_reference = true;
00163     return add_vertex(forward, index);
00164   } else {
00165     return (*ivi).second;
00166   }
00167 }
00168 
00169 ////////////////////////////////////////////////////////////////////
00170 //     Function: EggVertexPool::get_highest_index
00171 //       Access: Public
00172 //  Description: Returns the highest index number used by any vertex
00173 //               in the pool (except forward references).  Returns -1
00174 //               if the pool is empty.
00175 ////////////////////////////////////////////////////////////////////
00176 int EggVertexPool::
00177 get_highest_index() const {
00178   return _highest_index;
00179 }
00180 
00181 ////////////////////////////////////////////////////////////////////
00182 //     Function: EggVertexPool::set_highest_index
00183 //       Access: Public
00184 //  Description: Artificially changes the "highest index number", so
00185 //               that a newly created vertex will begin at this number
00186 //               plus 1.  This can be used to default a vertex pool to
00187 //               start counting at 1 (or any other index number),
00188 //               instead of the default of 0.  Use with caution.
00189 ////////////////////////////////////////////////////////////////////
00190 void EggVertexPool::
00191 set_highest_index(int highest_index) {
00192   _highest_index = highest_index;
00193 }
00194 
00195 ////////////////////////////////////////////////////////////////////
00196 //     Function: EggVertexPool::get_num_dimensions
00197 //       Access: Public
00198 //  Description: Returns the maximum number of dimensions used by any
00199 //               vertex in the pool.
00200 ////////////////////////////////////////////////////////////////////
00201 int EggVertexPool::
00202 get_num_dimensions() const {
00203   int num_dimensions = 0;
00204 
00205   IndexVertices::const_iterator ivi;
00206   for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
00207     EggVertex *vertex = (*ivi).second;
00208     num_dimensions = max(num_dimensions, vertex->get_num_dimensions());
00209   }
00210 
00211   return num_dimensions;
00212 }
00213 
00214 ////////////////////////////////////////////////////////////////////
00215 //     Function: EggVertexPool::has_normals
00216 //       Access: Public
00217 //  Description: Returns true if any vertex in the pool has a normal
00218 //               defined, false if none of them do.
00219 ////////////////////////////////////////////////////////////////////
00220 bool EggVertexPool::
00221 has_normals() const {
00222   IndexVertices::const_iterator ivi;
00223   for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
00224     EggVertex *vertex = (*ivi).second;
00225     if (vertex->has_normal()) {
00226       return true;
00227     }
00228   }
00229 
00230   return false;
00231 }
00232 
00233 ////////////////////////////////////////////////////////////////////
00234 //     Function: EggVertexPool::has_colors
00235 //       Access: Public
00236 //  Description: Returns true if any vertex in the pool has a color
00237 //               defined, false if none of them do.
00238 ////////////////////////////////////////////////////////////////////
00239 bool EggVertexPool::
00240 has_colors() const {
00241   IndexVertices::const_iterator ivi;
00242   for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
00243     EggVertex *vertex = (*ivi).second;
00244     if (vertex->has_color()) {
00245       return true;
00246     }
00247   }
00248 
00249   return false;
00250 }
00251 
00252 ////////////////////////////////////////////////////////////////////
00253 //     Function: EggVertexPool::has_nonwhite_colors
00254 //       Access: Public
00255 //  Description: Returns true if any vertex in the pool has a color
00256 //               defined other than white, false if no vertices have
00257 //               colors, or if all colors are white.
00258 ////////////////////////////////////////////////////////////////////
00259 bool EggVertexPool::
00260 has_nonwhite_colors() const {
00261   IndexVertices::const_iterator ivi;
00262   for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
00263     EggVertex *vertex = (*ivi).second;
00264     if (vertex->has_color() && 
00265         (vertex->get_color() != LColor(1.0, 1.0, 1.0, 1.0) ||
00266          !vertex->_drgbas.empty())) {
00267       return true;
00268     }
00269   }
00270 
00271   return false;
00272 }
00273 
00274 ////////////////////////////////////////////////////////////////////
00275 //     Function: EggVertexPool::check_overall_color
00276 //       Access: Public
00277 //  Description: Scans the vertex pool for different colors on
00278 //               different vertices.  If all vertices are the same
00279 //               color, sets has_overall_color to true and fills the
00280 //               color into overall_color.  If no vertices have any
00281 //               color, set has_overall_color to true and fills white
00282 //               into overall_color.  If at least two vertices have
00283 //               different colors, sets has_overall_color to false.
00284 ////////////////////////////////////////////////////////////////////
00285 void EggVertexPool::
00286 check_overall_color(bool &has_overall_color, LColor &overall_color) const {
00287   if (empty()) {
00288     has_overall_color = true;
00289     overall_color.set(1.0f, 1.0f, 1.0f, 1.0f);
00290     return;
00291   }
00292 
00293   IndexVertices::const_iterator ivi;
00294   ivi = _index_vertices.begin();
00295   EggVertex *vertex = (*ivi).second;
00296   overall_color = vertex->get_color();
00297 
00298   ++ivi;
00299   while (ivi != _index_vertices.end()) {
00300     vertex = (*ivi).second;
00301     if (!vertex->get_color().almost_equal(overall_color)) {
00302       has_overall_color = false;
00303       return;
00304     }
00305     ++ivi;
00306   }
00307 
00308   has_overall_color = true;
00309 }
00310 
00311 ////////////////////////////////////////////////////////////////////
00312 //     Function: EggVertexPool::has_uvs
00313 //       Access: Public
00314 //  Description: Returns true if any vertex in the pool has a uv
00315 //               defined, false if none of them do.
00316 ////////////////////////////////////////////////////////////////////
00317 bool EggVertexPool::
00318 has_uvs() const {
00319   IndexVertices::const_iterator ivi;
00320   for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
00321     EggVertex *vertex = (*ivi).second;
00322     if (vertex->has_uv()) {
00323       return true;
00324     }
00325   }
00326 
00327   return false;
00328 }
00329 
00330 ////////////////////////////////////////////////////////////////////
00331 //     Function: EggVertexPool::has_aux
00332 //       Access: Public
00333 //  Description: Returns true if any vertex in the pool has
00334 //               auxiliary data defined, false if none of them do.
00335 ////////////////////////////////////////////////////////////////////
00336 bool EggVertexPool::
00337 has_aux() const {
00338   IndexVertices::const_iterator ivi;
00339   for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
00340     EggVertex *vertex = (*ivi).second;
00341     if (vertex->has_aux()) {
00342       return true;
00343     }
00344   }
00345 
00346   return false;
00347 }
00348 
00349 ////////////////////////////////////////////////////////////////////
00350 //     Function: EggVertexPool::get_uv_names
00351 //       Access: Public
00352 //  Description: Returns the list of UV names that are defined by any
00353 //               vertices in the pool, as well as the subset of UV
00354 //               names that actually define 3-d texture coordinates
00355 //               ("uvw_names").  Also returns the subset of UV/UVW
00356 //               names that define a tangent and binormal.  It is the
00357 //               user's responsibility to clear both vectors before
00358 //               calling this method.
00359 ////////////////////////////////////////////////////////////////////
00360 void EggVertexPool::
00361 get_uv_names(vector_string &uv_names, vector_string &uvw_names, 
00362              vector_string &tbn_names) const {
00363   pset<string> uv_names_set, uvw_names_set, tbn_names_set;
00364   IndexVertices::const_iterator ivi;
00365   for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
00366     EggVertex *vertex = (*ivi).second;
00367     EggVertex::const_uv_iterator uvi;
00368     for (uvi = vertex->uv_begin(); uvi != vertex->uv_end(); ++uvi) {
00369       EggVertexUV *uv_obj = (*uvi);
00370       uv_names_set.insert(uv_obj->get_name());
00371       if (uv_obj->has_w()) {
00372         uvw_names_set.insert(uv_obj->get_name());
00373       }
00374       if (uv_obj->has_tangent() && uv_obj->has_binormal()) {
00375         tbn_names_set.insert(uv_obj->get_name());
00376       }
00377     }
00378   }
00379 
00380   pset<string>::const_iterator si;
00381   for (si = uv_names_set.begin(); si != uv_names_set.end(); ++si) {
00382     uv_names.push_back(*si);
00383   }
00384   for (si = uvw_names_set.begin(); si != uvw_names_set.end(); ++si) {
00385     uvw_names.push_back(*si);
00386   }
00387   for (si = tbn_names_set.begin(); si != tbn_names_set.end(); ++si) {
00388     tbn_names.push_back(*si);
00389   }
00390 }
00391 
00392 ////////////////////////////////////////////////////////////////////
00393 //     Function: EggVertexPool::get_aux_names
00394 //       Access: Public
00395 //  Description: Returns the list of auxiliary data names that are
00396 //               defined by any vertices in the pool.
00397 ////////////////////////////////////////////////////////////////////
00398 void EggVertexPool::
00399 get_aux_names(vector_string &aux_names) const {
00400   pset<string> aux_names_set;
00401   IndexVertices::const_iterator ivi;
00402   for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
00403     EggVertex *vertex = (*ivi).second;
00404     EggVertex::const_aux_iterator uvi;
00405     for (uvi = vertex->aux_begin(); uvi != vertex->aux_end(); ++uvi) {
00406       EggVertexAux *aux_obj = (*uvi);
00407       aux_names_set.insert(aux_obj->get_name());
00408     }
00409   }
00410 
00411   pset<string>::const_iterator si;
00412   for (si = aux_names_set.begin(); si != aux_names_set.end(); ++si) {
00413     aux_names.push_back(*si);
00414   }
00415 }
00416 
00417 ////////////////////////////////////////////////////////////////////
00418 //     Function: EggVertexPool::begin()
00419 //       Access: Public
00420 //  Description: Returns an iterator that can be used to traverse
00421 //               through all the vertices in the pool.
00422 ////////////////////////////////////////////////////////////////////
00423 EggVertexPool::iterator EggVertexPool::
00424 begin() const {
00425   nassertr(_index_vertices.size() == _unique_vertices.size(),
00426            iterator(_index_vertices.begin()));
00427   return iterator(_index_vertices.begin());
00428 }
00429 
00430 ////////////////////////////////////////////////////////////////////
00431 //     Function: EggVertexPool::end()
00432 //       Access: Public
00433 //  Description: Returns an iterator that can be used to traverse
00434 //               through all the vertices in the pool.
00435 ////////////////////////////////////////////////////////////////////
00436 EggVertexPool::iterator EggVertexPool::
00437 end() const {
00438   return iterator(_index_vertices.end());
00439 }
00440 
00441 ////////////////////////////////////////////////////////////////////
00442 //     Function: EggVertexPool::empty()
00443 //       Access: Public
00444 //  Description: Returns true if the pool is empty.
00445 ////////////////////////////////////////////////////////////////////
00446 bool EggVertexPool::
00447 empty() const {
00448   return _index_vertices.empty();
00449 }
00450 
00451 ////////////////////////////////////////////////////////////////////
00452 //     Function: EggVertexPool::size()
00453 //       Access: Public
00454 //  Description: Returns the number of vertices in the pool.
00455 ////////////////////////////////////////////////////////////////////
00456 EggVertexPool::size_type EggVertexPool::
00457 size() const {
00458   nassertr(_index_vertices.size() == _unique_vertices.size(), 0);
00459   return _index_vertices.size();
00460 }
00461 
00462 ////////////////////////////////////////////////////////////////////
00463 //     Function: EggVertexPool::add_vertex
00464 //       Access: Public
00465 //  Description: Adds the indicated vertex to the pool.  It is an
00466 //               error if the vertex is already a member of this or
00467 //               any other pool.  The vertex must have been allocated
00468 //               from the free store; its pointer will now be owned by
00469 //               the vertex pool.  If the index number is supplied,
00470 //               tries to assign that index number; it is an error if
00471 //               the index number is already in use.
00472 //
00473 //               It is possible that a forward reference to this
00474 //               vertex was requested in the past; if so, the data
00475 //               from the supplied vertex is copied onto the forward
00476 //               reference, which becomes the actual vertex.  In this
00477 //               case, a different pointer is saved (and returned)
00478 //               than the one actually passed in.  In the usual case,
00479 //               however, the vertex pointer passed in is the one that
00480 //               is saved in the vertex pool and returned from this
00481 //               method.
00482 ////////////////////////////////////////////////////////////////////
00483 EggVertex *EggVertexPool::
00484 add_vertex(EggVertex *vertex, int index) {
00485   // Save a pointer to the vertex.
00486   PT(EggVertex) vertex_keep = vertex;
00487 
00488   // Don't try to add a vertex while it still belongs to another pool.
00489   nassertr(vertex->_pool == NULL, NULL);
00490 
00491   if (index == -1) {
00492     index = get_highest_index() + 1;
00493   }
00494   // Always supply an index number >= 0.
00495   nassertr(index >= 0, NULL);
00496 
00497   // Check for a forward reference.
00498   IndexVertices::const_iterator ivi = _index_vertices.find(index);
00499 
00500   if (ivi != _index_vertices.end()) {
00501     EggVertex *orig_vertex = (*ivi).second;
00502     if (orig_vertex->is_forward_reference() &&
00503         !vertex->is_forward_reference()) {
00504       (*orig_vertex) = (*vertex);
00505       orig_vertex->_forward_reference = false;
00506       _highest_index = max(_highest_index, index);
00507       return orig_vertex;
00508     }
00509 
00510     // Oops, you duplicated a vertex index.
00511     nassertr(false, NULL);
00512   }
00513   
00514   _unique_vertices.insert(vertex);
00515   _index_vertices[index] = vertex;
00516 
00517   if (!vertex->is_forward_reference()) {
00518     _highest_index = max(_highest_index, index);
00519   }
00520 
00521   vertex->_pool = this;
00522   vertex->_index = index;
00523 
00524   return vertex;
00525 }
00526 
00527 
00528 ////////////////////////////////////////////////////////////////////
00529 //     Function: EggVertexPool::create_unique_vertex
00530 //       Access: Public
00531 //  Description: Creates a new vertex in the pool that is a copy of
00532 //               the indicated one and returns it.  If there is
00533 //               already a vertex in the pool like the indicated one,
00534 //               simply returns that one.
00535 ////////////////////////////////////////////////////////////////////
00536 EggVertex *EggVertexPool::
00537 create_unique_vertex(const EggVertex &copy) {
00538   UniqueVertices::iterator uvi;
00539   uvi = _unique_vertices.find((EggVertex *)&copy);
00540 
00541   if (uvi != _unique_vertices.end()) {
00542     // There was already such a vertex.  Return it.
00543     return (*uvi);
00544   }
00545 
00546   // Create a new vertex.
00547   return add_vertex(new EggVertex(copy));
00548 }
00549 
00550 ////////////////////////////////////////////////////////////////////
00551 //     Function: EggVertexPool::find_matching_vertex
00552 //       Access: Public
00553 //  Description: If the EggVertexPool already has a vertex matching
00554 //               the indicated vertex, returns it; otherwise, returns
00555 //               NULL.  This is similar to create_unique_vertex()
00556 //               except that a new vertex is never created.
00557 ////////////////////////////////////////////////////////////////////
00558 EggVertex *EggVertexPool::
00559 find_matching_vertex(const EggVertex &copy) {
00560   UniqueVertices::iterator uvi;
00561   uvi = _unique_vertices.find((EggVertex *)&copy);
00562 
00563   if (uvi != _unique_vertices.end()) {
00564     // There was already such a vertex.  Return it.
00565     return (*uvi);
00566   }
00567 
00568   // No matching vertex.
00569   return NULL;
00570 }
00571 
00572 
00573 ////////////////////////////////////////////////////////////////////
00574 //     Function: EggVertexPool::remove_vertex
00575 //       Access: Public
00576 //  Description: Removes the vertex from the pool.  It is an error if
00577 //               the vertex is not already a member of the pool.
00578 ////////////////////////////////////////////////////////////////////
00579 void EggVertexPool::
00580 remove_vertex(EggVertex *vertex) {
00581   // Make sure the vertex is already a member of this pool.
00582   nassertv(vertex->_pool == this);
00583 
00584   // Sanity check.  Is the vertex actually in the pool?
00585   nassertv(get_vertex(vertex->_index) == vertex);
00586 
00587   // Removing the vertex from the indexed list is simple.
00588   _index_vertices.erase(vertex->_index);
00589 
00590   if (_highest_index == vertex->_index) {
00591     // Find the new highest vertex index.
00592     if (_index_vertices.empty()) {
00593       _highest_index = -1;
00594     } else {
00595       IndexVertices::reverse_iterator ivi = _index_vertices.rbegin();
00596       while (ivi != _index_vertices.rend() &&
00597              (*ivi).second->is_forward_reference()) {
00598         ++ivi;
00599       }
00600       if (ivi != _index_vertices.rend()) {
00601         _highest_index = (*ivi).first;
00602       } else {
00603         _highest_index = -1;
00604       }
00605     }
00606   }
00607 
00608   // Removing the vertex from the unique list is a bit trickier--there
00609   // might be several other vertices that are considered identical to
00610   // this one, and so we have to walk through all the identical
00611   // vertices until we find the right one.
00612   UniqueVertices::iterator uvi;
00613   uvi = _unique_vertices.find(vertex);
00614 
00615   // Sanity check.  Is the vertex actually in the pool?
00616   nassertv(uvi != _unique_vertices.end());
00617 
00618   while ((*uvi) != vertex) {
00619     ++uvi;
00620     // Sanity check.  Is the vertex actually in the pool?
00621     nassertv(uvi != _unique_vertices.end());
00622   }
00623 
00624   _unique_vertices.erase(uvi);
00625 
00626   vertex->_pool = NULL;
00627 }
00628 
00629 ////////////////////////////////////////////////////////////////////
00630 //     Function: EggVertexPool::remove_unused_vertices
00631 //       Access: Public
00632 //  Description: Removes all vertices from the pool that are not
00633 //               referenced by at least one primitive.  Also collapses
00634 //               together equivalent vertices, and renumbers all
00635 //               vertices after the operation so their indices are
00636 //               consecutive, beginning at zero.  Returns the number
00637 //               of vertices removed.
00638 ////////////////////////////////////////////////////////////////////
00639 int EggVertexPool::
00640 remove_unused_vertices() {
00641   int num_removed = 0;
00642 
00643   UniqueVertices new_unique_vertices;
00644   IndexVertices new_index_vertices;
00645 
00646   IndexVertices::const_iterator ivi;
00647   for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
00648     EggVertex *vertex = (*ivi).second;
00649     if (vertex->pref_size() == 0) {
00650       // This vertex is not used.  Don't add it to the new lists.
00651       vertex->clear_grefs();
00652       vertex->_pool = NULL;
00653       num_removed++;
00654 
00655     } else {
00656       // The vertex *is* used somewhere.  Is it identical to an
00657       // existing vertex?
00658       UniqueVertices::iterator uvi;
00659       uvi = new_unique_vertices.find(vertex);
00660       if (uvi != new_unique_vertices.end()) {
00661         // Yes, there's already another vertex just like this one.
00662         // Redirect all the primitives currently referencing this
00663         // vertex to reference the other one instead.
00664         EggVertex *orig_vertex = (*uvi);
00665 
00666         EggVertex::PrimitiveRef pref = vertex->_pref;
00667         EggVertex::PrimitiveRef::iterator pi;
00668         for (pi = pref.begin(); pi != pref.end(); ++pi) {
00669           EggPrimitive *prim = (*pi);
00670           EggPrimitive::iterator pvi = prim->find(vertex);
00671           nassertr(pvi != prim->end(), 0);
00672           prim->replace(pvi, orig_vertex);
00673         }
00674         vertex->test_pref_integrity();
00675         orig_vertex->test_pref_integrity();
00676         nassertr(vertex->pref_size() == 0, 0);
00677         vertex->clear_grefs();
00678         vertex->_pool = NULL;
00679         num_removed++;
00680 
00681       } else {
00682         // It's a unique vertex.  Renumber it and add it to the new
00683         // lists.
00684         vertex->_index = new_index_vertices.size();
00685         new_index_vertices.insert(IndexVertices::value_type(vertex->_index, vertex));
00686         new_unique_vertices.insert(vertex);
00687       }
00688     }
00689   }
00690 
00691   // All done.  Lose the old lists.
00692   _unique_vertices.swap(new_unique_vertices);
00693   _index_vertices.swap(new_index_vertices);
00694   _highest_index = (int)_index_vertices.size() - 1;
00695 
00696   nassertr(_index_vertices.size() == _unique_vertices.size(), num_removed);
00697 
00698   return num_removed;
00699 }
00700 
00701 ////////////////////////////////////////////////////////////////////
00702 //     Function: EggVertexPool::add_unused_vertices_to_prim
00703 //       Access: Public
00704 //  Description: Adds all of the unused vertices in this vertex pool
00705 //               to the indicated primitive, in ascending order.
00706 ////////////////////////////////////////////////////////////////////
00707 void EggVertexPool::
00708 add_unused_vertices_to_prim(EggPrimitive *prim) {
00709   IndexVertices::iterator ivi;
00710   for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
00711     EggVertex *vertex = (*ivi).second;
00712     if (vertex->pref_size() == 0) {
00713       prim->add_vertex(vertex);
00714     }
00715   }
00716 }
00717 
00718 // A function object for split_vertex(), used in transform(), below.
00719 class IsLocalVertexSplitter {
00720 public:
00721   int operator () (const EggPrimitive *prim) const {
00722     return (prim->is_local_coord() ? 1 : 0);
00723   }
00724 };
00725 
00726 ////////////////////////////////////////////////////////////////////
00727 //     Function: EggVertexPool::transform
00728 //       Access: Public
00729 //  Description: Applies the indicated transformation matrix to all
00730 //               the vertices.  However, vertices that are attached to
00731 //               primitives that believe their vertices are in a local
00732 //               coordinate system are transformed only by the scale
00733 //               and rotation component.  If a vertex happens to be
00734 //               attached both to a local and a global primitive, and
00735 //               the transformation includes a translation component,
00736 //               the vertex will be split.
00737 ////////////////////////////////////////////////////////////////////
00738 void EggVertexPool::
00739 transform(const LMatrix4d &mat) {
00740   LVector3d translation = mat.get_row3(3);
00741 
00742   if (translation == LVector3d(0.0, 0.0, 0.0)) {
00743     // If the matrix does not have a translation component, we can
00744     // treat the local and global vertices the same.  This makes
00745     // things much easier.
00746     iterator i;
00747     for (i = begin(); i != end(); ++i) {
00748       EggVertex *vert = *i;
00749       vert->transform(mat);
00750     }
00751 
00752   } else {
00753     // The matrix does have a translation component.  That means we
00754     // have to treat the global and local vertices differently.
00755     // Yucky.
00756 
00757     // First, transform the global vertices.  Get a copy of the list
00758     // of vertices in this pool.  We must have a copy because we might
00759     // be modifying the list as we traverse it.
00760 
00761     typedef pvector<EggVertex *> Verts;
00762     Verts verts;
00763     verts.reserve(size());
00764     copy(begin(), end(), back_inserter(verts));
00765 
00766     Verts::const_iterator vi;
00767     for (vi = verts.begin(); vi != verts.end(); ++vi) {
00768       EggVertex *vert = *vi;
00769       int num_local_coord = vert->get_num_local_coord();
00770       int num_global_coord = vert->get_num_global_coord();
00771 
00772       if (num_global_coord != 0) {
00773         // This vertex will be transformed.
00774         if (num_local_coord != 0) {
00775           // It also needs to be split!  Yuck.
00776           split_vertex(vert, IsLocalVertexSplitter());
00777         }
00778 
00779         vert->transform(mat);
00780       }
00781     }
00782 
00783     // Now transform the local vertices.  We can walk through the list
00784     // directly now, because we won't be modifying the list this time.
00785     LMatrix4d local_mat = mat;
00786     local_mat.set_row(3, LVector3d(0.0, 0.0, 0.0));
00787 
00788     iterator i;
00789     for (i = begin(); i != end(); ++i) {
00790       EggVertex *vert = *i;
00791       if (vert->get_num_local_coord() != 0) {
00792 
00793         // This should be guaranteed by the vertex-splitting logic
00794         // above.
00795         nassertv(vert->get_num_global_coord() == 0);
00796         vert->transform(local_mat);
00797       }
00798     }
00799   }
00800 }
00801 
00802 
00803 // A function object for sort_by_external_index(), below.
00804 class SortByExternalIndex {
00805 public:
00806   bool operator () (EggVertex *a, EggVertex *b) const {
00807     int ai = a->get_external_index();
00808     int bi = b->get_external_index();
00809     if (ai != bi) {
00810       return ai < bi;
00811     }
00812     return a->get_index() < b->get_index();
00813   }
00814 };
00815 
00816 ////////////////////////////////////////////////////////////////////
00817 //     Function: EggVertexPool::sort_by_external_index
00818 //       Access: Published
00819 //  Description: Re-orders (and re-numbers) the vertices in this
00820 //               vertex pool so that they appear in increasing order
00821 //               by the optional external_index that has been assigned
00822 //               to each vertex.
00823 ////////////////////////////////////////////////////////////////////
00824 void EggVertexPool::
00825 sort_by_external_index() {
00826   // Copy the vertices into a vector for sorting.
00827   typedef pvector<EggVertex *> SortedVertices;
00828   SortedVertices sorted_vertices;
00829   sorted_vertices.reserve(size());
00830   iterator i;
00831   for (i = begin(); i != end(); ++i) {
00832     sorted_vertices.push_back(*i);
00833   }
00834 
00835   ::sort(sorted_vertices.begin(), sorted_vertices.end(), SortByExternalIndex());
00836 
00837   // Now reassign the indices, and copy them into a new index map.
00838   IndexVertices new_index_vertices;
00839   int vi;
00840   for (vi = 0; vi < (int)sorted_vertices.size(); ++vi) {
00841     EggVertex *vertex = sorted_vertices[vi];
00842     vertex->_index = vi;
00843     new_index_vertices[vi] = vertex;
00844   }
00845 
00846   // Finally, assign the new index map.
00847   _index_vertices.swap(new_index_vertices);
00848 }
00849 
00850 ////////////////////////////////////////////////////////////////////
00851 //     Function: EggVertexPool::write
00852 //       Access: Public
00853 //  Description: Writes the vertex pool to the indicated output stream
00854 //               in Egg format.
00855 ////////////////////////////////////////////////////////////////////
00856 void EggVertexPool::
00857 write(ostream &out, int indent_level) const {
00858   write_header(out, indent_level, "<VertexPool>");
00859 
00860   iterator i;
00861   for (i = begin(); i != end(); ++i) {
00862     (*i)->write(out, indent_level+2);
00863   }
00864 
00865   indent(out, indent_level)
00866     << "}\n";
00867 }
00868 
00869 
00870 ////////////////////////////////////////////////////////////////////
00871 //     Function: EggVertexPool::r_transform
00872 //       Access: Protected, Virtual
00873 //  Description: This is called from within the egg code by
00874 //               transform().  It applies a transformation matrix
00875 //               to the current node in some sensible way, then
00876 //               continues down the tree.
00877 //
00878 //               The first matrix is the transformation to apply; the
00879 //               second is its inverse.  The third parameter is the
00880 //               coordinate system we are changing to, or CS_default
00881 //               if we are not changing coordinate systems.
00882 ////////////////////////////////////////////////////////////////////
00883 void EggVertexPool::
00884 r_transform(const LMatrix4d &mat, const LMatrix4d &, CoordinateSystem) {
00885 }
00886 
00887 ////////////////////////////////////////////////////////////////////
00888 //     Function: EggVertexPool::r_transform_vertices
00889 //       Access: Protected, Virtual
00890 //  Description: This is called from within the egg code by
00891 //               transform_vertices_only()().  It applies a
00892 //               transformation matrix to the current node in some
00893 //               sensible way (if the current node is a vertex pool
00894 //               with vertices), then continues down the tree.
00895 ////////////////////////////////////////////////////////////////////
00896 void EggVertexPool::
00897 r_transform_vertices(const LMatrix4d &mat) {
00898   transform(mat);
00899 }
 All Classes Functions Variables Enumerations