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