Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/egg/eggVertexPool.cxx

Go to the documentation of this file.
00001 // Filename: eggVertexPool.cxx
00002 // Created by:  drose (16Jan99)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "eggVertexPool.h"
00020 #include "eggPrimitive.h"
00021 #include "eggUtilities.h"
00022 
00023 #include <indent.h>
00024 
00025 TypeHandle EggVertexPool::_type_handle;
00026 
00027 ////////////////////////////////////////////////////////////////////
00028 //     Function: EggVertexPool::Constructor
00029 //       Access: Public
00030 //  Description:
00031 ////////////////////////////////////////////////////////////////////
00032 EggVertexPool::
00033 EggVertexPool(const string &name) : EggNode(name) {
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   iterator i;
00066   for (i = begin(); i != end(); ++i) {
00067     // Sanity checks on our internal data structures.
00068     nassertv((*i)->_pool == this);
00069     nassertv(get_vertex((*i)->_index) == (*i));
00070 
00071     (*i)->_pool = NULL;
00072     (*i)->_index = -1;
00073   }
00074 
00075   _index_vertices.erase(_index_vertices.begin(), _index_vertices.end());
00076   _unique_vertices.erase(_unique_vertices.begin(), _unique_vertices.end());
00077 }
00078 
00079 
00080 ////////////////////////////////////////////////////////////////////
00081 //     Function: EggVertexPool::get_vertex
00082 //       Access: Public
00083 //  Description: Returns the vertex in the pool with the indicated
00084 //               index number, or NULL if no vertices have that index
00085 //               number.
00086 ////////////////////////////////////////////////////////////////////
00087 EggVertex *EggVertexPool::
00088 get_vertex(int index) const {
00089   IndexVertices::const_iterator ivi = _index_vertices.find(index);
00090 
00091   if (ivi == _index_vertices.end()) {
00092     return NULL;
00093   } else {
00094     return (*ivi).second;
00095   }
00096 }
00097 
00098 ////////////////////////////////////////////////////////////////////
00099 //     Function: EggVertexPool::get_highest_index
00100 //       Access: Public
00101 //  Description: Returns the highest index number used by any vertex
00102 //               in the pool.
00103 ////////////////////////////////////////////////////////////////////
00104 int EggVertexPool::
00105 get_highest_index() const {
00106   if (_index_vertices.empty()) {
00107     return 0;
00108   }
00109   IndexVertices::const_reverse_iterator ivi = _index_vertices.rbegin();
00110   nassertr((*ivi).first == (*ivi).second->get_index(), 0);
00111   return (*ivi).first;
00112 }
00113 
00114 ////////////////////////////////////////////////////////////////////
00115 //     Function: EggVertexPool::begin()
00116 //       Access: Public
00117 //  Description: Returns an iterator that can be used to traverse
00118 //               through all the vertices in the pool.
00119 ////////////////////////////////////////////////////////////////////
00120 EggVertexPool::iterator EggVertexPool::
00121 begin() const {
00122   nassertr(_index_vertices.size() == _unique_vertices.size(),
00123            iterator(_index_vertices.begin()));
00124   return iterator(_index_vertices.begin());
00125 }
00126 
00127 ////////////////////////////////////////////////////////////////////
00128 //     Function: EggVertexPool::end()
00129 //       Access: Public
00130 //  Description: Returns an iterator that can be used to traverse
00131 //               through all the vertices in the pool.
00132 ////////////////////////////////////////////////////////////////////
00133 EggVertexPool::iterator EggVertexPool::
00134 end() const {
00135   return iterator(_index_vertices.end());
00136 }
00137 
00138 ////////////////////////////////////////////////////////////////////
00139 //     Function: EggVertexPool::empty()
00140 //       Access: Public
00141 //  Description: Returns true if the pool is empty.
00142 ////////////////////////////////////////////////////////////////////
00143 bool EggVertexPool::
00144 empty() const {
00145   return _index_vertices.empty();
00146 }
00147 
00148 ////////////////////////////////////////////////////////////////////
00149 //     Function: EggVertexPool::size()
00150 //       Access: Public
00151 //  Description: Returns the number of vertices in the pool.
00152 ////////////////////////////////////////////////////////////////////
00153 EggVertexPool::size_type EggVertexPool::
00154 size() const {
00155   nassertr(_index_vertices.size() == _unique_vertices.size(), 0);
00156   return _index_vertices.size();
00157 }
00158 
00159 ////////////////////////////////////////////////////////////////////
00160 //     Function: EggVertexPool::add_vertex
00161 //       Access: Public
00162 //  Description: Adds the indicated vertex to the pool.  It is an
00163 //               error if the vertex is already a member of this or
00164 //               any other pool.  The vertex must have been allocated
00165 //               from the free store; its pointer will now be owned by
00166 //               the vertex pool.  If the index number is supplied,
00167 //               tries to assign that index number; it is an error if
00168 //               the index number is already in use.
00169 ////////////////////////////////////////////////////////////////////
00170 void EggVertexPool::
00171 add_vertex(EggVertex *vertex, int index) {
00172   // Don't try to add a vertex while it still belongs to another pool.
00173   nassertv(vertex->_pool == NULL);
00174 
00175   if (index == -1) {
00176     index = get_highest_index() + 1;
00177   }
00178   // Always supply an index number >= 0.
00179   nassertv(index >= 0);
00180 
00181   // Don't try to duplicate index numbers within a vertex pool.
00182   nassertv(_index_vertices.find(index) == _index_vertices.end());
00183 
00184   _unique_vertices.insert(vertex);
00185   _index_vertices[index] = vertex;
00186 
00187   vertex->_pool = this;
00188   vertex->_index = index;
00189 }
00190 
00191 
00192 ////////////////////////////////////////////////////////////////////
00193 //     Function: EggVertexPool::create_unique_vertex
00194 //       Access: Public
00195 //  Description: Creates a new vertex in the pool that is a copy of
00196 //               the indicated one and returns it.  If there is
00197 //               already a vertex in the pool like the indicated one,
00198 //               simply returns that one.
00199 ////////////////////////////////////////////////////////////////////
00200 EggVertex *EggVertexPool::
00201 create_unique_vertex(const EggVertex &copy) {
00202   UniqueVertices::iterator uvi;
00203   uvi = _unique_vertices.find((EggVertex *)&copy);
00204 
00205   if (uvi != _unique_vertices.end()) {
00206     // There was already such a vertex.  Return it.
00207     return (*uvi);
00208   }
00209 
00210   // Create a new vertex.
00211   EggVertex *vtx = new EggVertex(copy);
00212   add_vertex(vtx);
00213   return vtx;
00214 }
00215 
00216 
00217 ////////////////////////////////////////////////////////////////////
00218 //     Function: EggVertexPool::remove_vertex
00219 //       Access: Public
00220 //  Description: Removes the vertex from the pool.  It is an error if
00221 //               the vertex is not already a member of the pool.
00222 ////////////////////////////////////////////////////////////////////
00223 void EggVertexPool::
00224 remove_vertex(EggVertex *vertex) {
00225   // Make sure the vertex is already a member of this pool.
00226   nassertv(vertex->_pool == this);
00227 
00228   // Sanity check.  Is the vertex actually in the pool?
00229   nassertv(get_vertex(vertex->_index) == vertex);
00230 
00231   // Removing the vertex from the indexed list is simple.
00232   _index_vertices.erase(vertex->_index);
00233 
00234   // Removing the vertex from the unique list is a bit trickier--there
00235   // might be several other vertices that are considered identical to
00236   // this one, and so we have to walk through all the identical
00237   // vertices until we find the right one.
00238   UniqueVertices::iterator uvi;
00239   uvi = _unique_vertices.find(vertex);
00240 
00241   // Sanity check.  Is the vertex actually in the pool?
00242   nassertv(uvi != _unique_vertices.end());
00243 
00244   while ((*uvi) != vertex) {
00245     ++uvi;
00246     // Sanity check.  Is the vertex actually in the pool?
00247     nassertv(uvi != _unique_vertices.end());
00248   }
00249 
00250   _unique_vertices.erase(uvi);
00251 
00252   vertex->_pool = NULL;
00253 }
00254 
00255 ////////////////////////////////////////////////////////////////////
00256 //     Function: EggVertexPool::remove_unused_vertices
00257 //       Access: Public
00258 //  Description: Removes all vertices from the pool that are not
00259 //               referenced by at least one primitive.  Also renumbers
00260 //               all vertices after the operation so their indices are
00261 //               consecutive, beginning at zero.  Returns the number
00262 //               of vertices removed.
00263 ////////////////////////////////////////////////////////////////////
00264 int EggVertexPool::
00265 remove_unused_vertices() {
00266   int num_removed = 0;
00267 
00268   UniqueVertices new_unique_vertices;
00269   IndexVertices new_index_vertices;
00270 
00271   IndexVertices::const_iterator ivi;
00272   for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
00273     EggVertex *vertex = (*ivi).second;
00274     if (vertex->pref_size() == 0) {
00275       // This vertex is not used.  Don't add it to the new lists.
00276       vertex->clear_grefs();
00277       vertex->_pool = NULL;
00278       num_removed++;
00279 
00280     } else {
00281       // The vertex *is* used somewhere.  Renumber it and add it to
00282       // the new lists.
00283       vertex->_index = new_index_vertices.size();
00284       new_index_vertices.insert(IndexVertices::value_type(vertex->_index, vertex));
00285       new_unique_vertices.insert(vertex);
00286     }
00287   }
00288 
00289   // All done.  Lose the old lists.
00290   _unique_vertices.swap(new_unique_vertices);
00291   _index_vertices.swap(new_index_vertices);
00292 
00293   nassertr(_index_vertices.size() == _unique_vertices.size(), num_removed);
00294 
00295   return num_removed;
00296 }
00297 
00298 // A function object for split_vertex(), used in transform(), below.
00299 class IsLocalVertexSplitter {
00300 public:
00301   int operator () (const EggPrimitive *prim) const {
00302     return (prim->is_local_coord() ? 1 : 0);
00303   }
00304 };
00305 
00306 ////////////////////////////////////////////////////////////////////
00307 //     Function: EggVertexPool::transform
00308 //       Access: Public
00309 //  Description: Applies the indicated transformation matrix to all
00310 //               the vertices.  However, vertices that are attached to
00311 //               primitives that believe their vertices are in a local
00312 //               coordinate system are transformed only by the scale
00313 //               and rotation component.  If a vertex happens to be
00314 //               attached both to a local and a global primitive, and
00315 //               the transformation includes a translation component,
00316 //               the vertex will be split.
00317 ////////////////////////////////////////////////////////////////////
00318 void EggVertexPool::
00319 transform(const LMatrix4d &mat) {
00320   LVector3d translation = mat.get_row3(3);
00321 
00322   if (translation == LVector3d(0.0, 0.0, 0.0)) {
00323     // If the matrix does not have a translation component, we can
00324     // treat the local and global vertices the same.  This makes
00325     // things much easier.
00326     iterator i;
00327     for (i = begin(); i != end(); ++i) {
00328       EggVertex *vert = *i;
00329       vert->transform(mat);
00330     }
00331 
00332   } else {
00333     // The matrix does have a translation component.  That means we
00334     // have to treat the global and local vertices differently.
00335     // Yucky.
00336 
00337     // First, transform the global vertices.  Get a copy of the list
00338     // of vertices in this pool.  We must have a copy because we might
00339     // be modifying the list as we traverse it.
00340 
00341     typedef pvector<EggVertex *> Verts;
00342     Verts verts;
00343     verts.reserve(size());
00344     copy(begin(), end(), back_inserter(verts));
00345 
00346     Verts::const_iterator vi;
00347     for (vi = verts.begin(); vi != verts.end(); ++vi) {
00348       EggVertex *vert = *vi;
00349       int num_local_coord = vert->get_num_local_coord();
00350       int num_global_coord = vert->get_num_global_coord();
00351 
00352       if (num_global_coord != 0) {
00353         // This vertex will be transformed.
00354         if (num_local_coord != 0) {
00355           // It also needs to be split!  Yuck.
00356           split_vertex(vert, IsLocalVertexSplitter());
00357         }
00358 
00359         vert->transform(mat);
00360       }
00361     }
00362 
00363     // Now transform the local vertices.  We can walk through the list
00364     // directly now, because we won't be modifying the list this time.
00365     LMatrix4d local_mat = mat;
00366     local_mat.set_row(3, LVector3d(0.0, 0.0, 0.0));
00367 
00368     iterator i;
00369     for (i = begin(); i != end(); ++i) {
00370       EggVertex *vert = *i;
00371       if (vert->get_num_local_coord() != 0) {
00372 
00373         // This should be guaranteed by the vertex-splitting logic
00374         // above.
00375         nassertv(vert->get_num_global_coord() == 0);
00376         vert->transform(local_mat);
00377       }
00378     }
00379   }
00380 }
00381 
00382 
00383 ////////////////////////////////////////////////////////////////////
00384 //     Function: EggVertexPool::write
00385 //       Access: Public
00386 //  Description: Writes the vertex pool to the indicated output stream
00387 //               in Egg format.
00388 ////////////////////////////////////////////////////////////////////
00389 void EggVertexPool::
00390 write(ostream &out, int indent_level) const {
00391   write_header(out, indent_level, "<VertexPool>");
00392 
00393   iterator i;
00394   for (i = begin(); i != end(); ++i) {
00395     (*i)->write(out, indent_level+2);
00396   }
00397 
00398   indent(out, indent_level)
00399     << "}\n";
00400 }
00401 
00402 
00403 ////////////////////////////////////////////////////////////////////
00404 //     Function: EggVertexPool::r_transform
00405 //       Access: Protected, Virtual
00406 //  Description: This is called from within the egg code by
00407 //               transform().  It applies a transformation matrix
00408 //               to the current node in some sensible way, then
00409 //               continues down the tree.
00410 //
00411 //               The first matrix is the transformation to apply; the
00412 //               second is its inverse.  The third parameter is the
00413 //               coordinate system we are changing to, or CS_default
00414 //               if we are not changing coordinate systems.
00415 ////////////////////////////////////////////////////////////////////
00416 void EggVertexPool::
00417 r_transform(const LMatrix4d &mat, const LMatrix4d &, CoordinateSystem) {
00418   transform(mat);
00419 }
00420 
00421 ////////////////////////////////////////////////////////////////////
00422 //     Function: EggVertexPool::r_transform_vertices
00423 //       Access: Protected, Virtual
00424 //  Description: This is called from within the egg code by
00425 //               transform_vertices_only()().  It applies a
00426 //               transformation matrix to the current node in some
00427 //               sensible way (if the current node is a vertex pool
00428 //               with vertices), then continues down the tree.
00429 ////////////////////////////////////////////////////////////////////
00430 void EggVertexPool::
00431 r_transform_vertices(const LMatrix4d &mat) {
00432   transform(mat);
00433 }

Generated on Fri May 2 00:38:03 2003 for Panda by doxygen1.3