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

panda/src/egg/eggVertex.cxx

Go to the documentation of this file.
00001 // Filename: eggVertex.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 "eggVertex.h"
00020 #include "eggVertexPool.h"
00021 #include "eggParameters.h"
00022 #include "eggGroup.h"
00023 #include "eggMiscFuncs.h"
00024 #include "eggPrimitive.h"
00025 
00026 #include <indent.h>
00027 #include <luse.h>
00028 #include <lmatrix.h>
00029 #include <pandabase.h>
00030 
00031 #include <math.h>
00032 #include <algorithm>
00033 
00034 TypeHandle EggVertex::_type_handle;
00035 
00036 
00037 ////////////////////////////////////////////////////////////////////
00038 //     Function: EggVertex::Constructor
00039 //       Access: Public
00040 //  Description:
00041 ////////////////////////////////////////////////////////////////////
00042 EggVertex::
00043 EggVertex() {
00044   _pool = NULL;
00045   _index = -1;
00046   _external_index = -1;
00047   set_pos(LPoint3d(0.0, 0.0, 0.0));
00048   test_pref_integrity();
00049   test_gref_integrity();
00050 }
00051 
00052 ////////////////////////////////////////////////////////////////////
00053 //     Function: EggVertex::Copy constructor
00054 //       Access: Public
00055 //  Description: Copies all properties of the vertex except its vertex
00056 //               pool, index number, and group membership.
00057 ////////////////////////////////////////////////////////////////////
00058 EggVertex::
00059 EggVertex(const EggVertex &copy)
00060   : EggObject(copy), EggAttributes(copy),
00061     _dxyzs(copy._dxyzs),
00062     _external_index(copy._external_index),
00063     _pos(copy._pos),
00064     _num_dimensions(copy._num_dimensions)
00065 {
00066   _pool = NULL;
00067   _index = -1;
00068   test_pref_integrity();
00069   test_gref_integrity();
00070 }
00071 
00072 
00073 ////////////////////////////////////////////////////////////////////
00074 //     Function: EggVertex::Copy assignment operator
00075 //       Access: Public
00076 //  Description: Copies all properties of the vertex except its vertex
00077 //               pool, index number, and group membership.
00078 ////////////////////////////////////////////////////////////////////
00079 EggVertex &EggVertex::
00080 operator = (const EggVertex &copy) {
00081   EggObject::operator = (copy);
00082   EggAttributes::operator = (copy);
00083   _external_index = copy._external_index;
00084   _pos = copy._pos;
00085   _num_dimensions = copy._num_dimensions;
00086   _dxyzs = copy._dxyzs;
00087 
00088   test_pref_integrity();
00089   test_gref_integrity();
00090 
00091   return *this;
00092 }
00093 
00094 ////////////////////////////////////////////////////////////////////
00095 //     Function: EggVertex::Destructor
00096 //       Access: Public, Virtual
00097 //  Description:
00098 ////////////////////////////////////////////////////////////////////
00099 EggVertex::
00100 ~EggVertex() {
00101   // We should never destruct a vertex while it still thinks it
00102   // belongs to a VertexPool.  If we do, we've probably lost a
00103   // reference count somewhere.
00104   nassertv(_pool == NULL);
00105 
00106   // Also, a vertex shouldn't be destructed while it's being
00107   // referenced by a group or a primitive, for the same reason.
00108   nassertv(_gref.empty());
00109   nassertv(_pref.empty());
00110 }
00111 
00112 
00113 
00114 ///////////////////////////////////////////////////////////////////
00115 //       Class : GroupRefEntry
00116 // Description : A temporary class used in EggVertex::write(), below,
00117 //               to hold the groups that reference each vertex prior
00118 //               to outputting them as a formatted list.
00119 ////////////////////////////////////////////////////////////////////
00120 class GroupRefEntry {
00121 public:
00122   GroupRefEntry(EggGroup *group, double membership)
00123     : _group(group), _membership(membership) { }
00124 
00125   bool operator < (const GroupRefEntry &other) const {
00126     return _group->get_name() < other._group->get_name();
00127   }
00128   void output(ostream &out) const {
00129     out << _group->get_name() << ":" << _membership;
00130   }
00131 
00132   EggGroup *_group;
00133   double _membership;
00134 };
00135 
00136 INLINE ostream &operator << (ostream &out, const GroupRefEntry &gre) {
00137   gre.output(out);
00138   return out;
00139 }
00140 
00141 ////////////////////////////////////////////////////////////////////
00142 //     Function: EggVertex::write
00143 //       Access: Public
00144 //  Description: Writes the vertex to the indicated output stream in
00145 //               Egg format.
00146 ////////////////////////////////////////////////////////////////////
00147 void EggVertex::
00148 write(ostream &out, int indent_level) const {
00149   test_pref_integrity();
00150   test_gref_integrity();
00151 
00152   indent(out, indent_level)
00153     << "<Vertex> " << _index << " {\n";
00154 
00155   // Now output the position.  This might have any number of
00156   // dimensions up to 4.
00157   indent(out, indent_level+1);
00158   for (int i = 0; i < _num_dimensions; i++) {
00159     out << " " << _pos[i];
00160   }
00161   out << "\n";
00162 
00163   EggAttributes::write(out, indent_level+2);
00164 
00165   _dxyzs.write(out, indent_level+2);
00166 
00167   // If the vertex is referenced by one or more groups, write that as
00168   // a helpful comment.
00169   if (!_gref.empty()) {
00170     // We need to build a list of group entries.
00171     pset<GroupRefEntry> gre;
00172 
00173     GroupRef::const_iterator gi;
00174     for (gi = _gref.begin(); gi != _gref.end(); ++gi) {
00175       gre.insert(GroupRefEntry(*gi, (*gi)->get_vertex_membership(this)));
00176     }
00177 
00178     // Now output the list.
00179     write_long_list(out, indent_level + 2, gre.begin(), gre.end(), "// ",
00180                     "", 72);
00181   }
00182 
00183   indent(out, indent_level)
00184     << "}\n";
00185 }
00186 
00187 
00188 ////////////////////////////////////////////////////////////////////
00189 //     Function: EggVertex::sorts_less_than
00190 //       Access: Public
00191 //  Description: An ordering operator to compare two vertices for
00192 //               sorting order.  This imposes an arbitrary ordering
00193 //               useful to identify unique vertices.
00194 //
00195 //               Group membership is not considered in this
00196 //               comparison.  This is somewhat problematic, but cannot
00197 //               easily be helped, because considering group
00198 //               membership would make it difficult to add and remove
00199 //               groups from vertices.  It also makes it impossible to
00200 //               meaningfully compare with a concrete EggVertex object
00201 //               (which cannot have group memberships).
00202 //
00203 //               However, this is not altogether bad, because two
00204 //               vertices that are identical in all other properties
00205 //               should generally also be identical in group
00206 //               memberships, else the vertices will tend to fly apart
00207 //               when the joints animate.
00208 ////////////////////////////////////////////////////////////////////
00209 bool EggVertex::
00210 sorts_less_than(const EggVertex &other) const {
00211   if (_external_index != other._external_index) {
00212     return _external_index < other._external_index;
00213   }
00214   if (_num_dimensions != other._num_dimensions) {
00215     return _num_dimensions < other._num_dimensions;
00216   }
00217 
00218   int compare =
00219     _pos.compare_to(other._pos, egg_parameters->_pos_threshold);
00220   if (compare != 0) {
00221     return compare < 0;
00222   }
00223   if (_dxyzs != other._dxyzs) {
00224     return _dxyzs < other._dxyzs;
00225   }
00226 
00227   return EggAttributes::sorts_less_than(other);
00228 }
00229 
00230 ////////////////////////////////////////////////////////////////////
00231 //     Function: EggVertex::get_num_local_coord
00232 //       Access: Public
00233 //  Description: Returns the number of primitives that own this vertex
00234 //               whose vertices are interpreted to be in a local
00235 //               coordinate system.
00236 ////////////////////////////////////////////////////////////////////
00237 int EggVertex::
00238 get_num_local_coord() const {
00239   test_pref_integrity();
00240 
00241   PrimitiveRef::const_iterator pri;
00242 
00243   int count = 0;
00244   for (pri = pref_begin(); pri != pref_end(); ++pri) {
00245     EggPrimitive *prim = *pri;
00246     count += (prim->is_local_coord() ? 1 : 0);
00247   }
00248   return count;
00249 }
00250 
00251 ////////////////////////////////////////////////////////////////////
00252 //     Function: EggVertex::get_num_global_coord
00253 //       Access: Public
00254 //  Description: Returns the number of primitives that own this vertex
00255 //               whose vertices are interpreted in the global
00256 //               coordinate system.
00257 ////////////////////////////////////////////////////////////////////
00258 int EggVertex::
00259 get_num_global_coord() const {
00260   test_pref_integrity();
00261 
00262   PrimitiveRef::const_iterator pri;
00263 
00264   int count = 0;
00265   for (pri = pref_begin(); pri != pref_end(); ++pri) {
00266     EggPrimitive *prim = *pri;
00267     count += (prim->is_local_coord() ? 0 : 1);
00268   }
00269   return count;
00270 }
00271 
00272 
00273 ////////////////////////////////////////////////////////////////////
00274 //     Function: EggVertex::transform
00275 //       Access: Public, Virtual
00276 //  Description: Applies the indicated transformation matrix to the
00277 //               vertex.
00278 ////////////////////////////////////////////////////////////////////
00279 void EggVertex::
00280 transform(const LMatrix4d &mat) {
00281   _pos = _pos * mat;
00282 
00283   EggMorphVertexList::iterator mi;
00284   for (mi = _dxyzs.begin(); mi != _dxyzs.end(); ++mi) {
00285     // We can safely cast the morph object to a non-const, because
00286     // we're not changing its name, which is the only thing the set
00287     // cares about preserving.
00288     EggMorphVertex &morph = (EggMorphVertex &)(*mi);
00289 
00290     morph.set_offset((*mi).get_offset() * mat);
00291   }
00292 
00293   EggAttributes::transform(mat);
00294 }
00295 
00296 
00297 ////////////////////////////////////////////////////////////////////
00298 //     Function: EggVertex::has_gref
00299 //       Access: Public
00300 //  Description: Returns true if the indicated group references this
00301 //               vertex, false otherwise.
00302 ////////////////////////////////////////////////////////////////////
00303 bool EggVertex::
00304 has_gref(const EggGroup *group) const {
00305   return _gref.count((EggGroup *)group) != 0;
00306 }
00307 
00308 ////////////////////////////////////////////////////////////////////
00309 //     Function: EggVertex::copy_grefs_from
00310 //       Access: Public
00311 //  Description: Copies all the group references from the other vertex
00312 //               onto this one.  This assigns the current vertex to
00313 //               exactly the same groups, with exactly the same
00314 //               memberships, as the given one.
00315 //
00316 //               Warning: only an EggVertex allocated from the free
00317 //               store may have groups assigned to it.  Do not attempt
00318 //               to call this on a temporary concrete EggVertex
00319 //               object; a core dump will certainly result.
00320 ////////////////////////////////////////////////////////////////////
00321 void EggVertex::
00322 copy_grefs_from(const EggVertex &other) {
00323   if (&other == this) {
00324     return;
00325   }
00326   test_gref_integrity();
00327   other.test_gref_integrity();
00328 
00329   clear_grefs();
00330   test_gref_integrity();
00331 
00332   GroupRef::const_iterator gri;
00333 
00334   for (gri = other.gref_begin(); gri != other.gref_end(); ++gri) {
00335     EggGroup *group = *gri;
00336     nassertv(group != NULL);
00337 
00338     group->ref_vertex(this, group->get_vertex_membership(&other));
00339   }
00340 }
00341 
00342 ////////////////////////////////////////////////////////////////////
00343 //     Function: EggVertex::clear_grefs
00344 //       Access: Public
00345 //  Description: Removes all group references from the vertex, so that
00346 //               it is not assigned to any group.
00347 ////////////////////////////////////////////////////////////////////
00348 void EggVertex::
00349 clear_grefs() {
00350   GroupRef gref_copy = _gref;
00351   GroupRef::const_iterator gri;
00352   for (gri = gref_copy.begin(); gri != gref_copy.end(); ++gri) {
00353     EggGroup *group = *gri;
00354     nassertv(group != NULL);
00355     group->unref_vertex(this);
00356   }
00357 
00358   // Now we should have no more refs.
00359   nassertv(_gref.empty());
00360 }
00361 
00362 ////////////////////////////////////////////////////////////////////
00363 //     Function: EggVertex::has_pref
00364 //       Access: Public
00365 //  Description: Returns the number of times the vertex appears in the
00366 //               indicated primitive, or 0 if it does not appear.
00367 ////////////////////////////////////////////////////////////////////
00368 int EggVertex::
00369 has_pref(const EggPrimitive *prim) const {
00370   return _pref.count((EggPrimitive *)prim);
00371 }
00372 
00373 #ifndef NDEBUG
00374 
00375 ////////////////////////////////////////////////////////////////////
00376 //     Function: EggVertex::test_gref_integrity
00377 //       Access: Public
00378 //  Description: Verifies that the gref list is correct and that all
00379 //               the groups included actually exist and do reference
00380 //               the vertex.
00381 ////////////////////////////////////////////////////////////////////
00382 void EggVertex::
00383 test_gref_integrity() const {
00384   test_ref_count_integrity();
00385 
00386   GroupRef::const_iterator gri;
00387 
00388   for (gri = gref_begin(); gri != gref_end(); ++gri) {
00389     EggGroup *group = *gri;
00390     nassertv(group != NULL);
00391     group->test_ref_count_integrity();
00392 
00393     double membership = group->get_vertex_membership(this);
00394     nassertv(membership != 0.0);
00395   }
00396 }
00397 
00398 ////////////////////////////////////////////////////////////////////
00399 //     Function: EggVertex::test_pref_integrity
00400 //       Access: Public
00401 //  Description: Verifies that the pref list is correct and that all
00402 //               the primitives included actually exist and do
00403 //               reference the vertex.
00404 ////////////////////////////////////////////////////////////////////
00405 void EggVertex::
00406 test_pref_integrity() const {
00407   test_ref_count_integrity();
00408 
00409   PrimitiveRef::const_iterator pri;
00410 
00411   for (pri = pref_begin(); pri != pref_end(); ++pri) {
00412     EggPrimitive *prim = *pri;
00413     nassertv(prim != NULL);
00414     prim->test_ref_count_integrity();
00415 
00416     EggPrimitive::iterator vi;
00417     vi = find(prim->begin(), prim->end(), this);
00418     nassertv(vi != prim->end());
00419   }
00420 }
00421 
00422 #endif  // NDEBUG
00423 
00424 ////////////////////////////////////////////////////////////////////
00425 //     Function: EggVertex::output
00426 //       Access: Public
00427 //  Description:
00428 ////////////////////////////////////////////////////////////////////
00429 void EggVertex::
00430 output(ostream &out) const {
00431   if (get_pool() == NULL) {
00432     out << "(null):" << get_index();
00433   } else {
00434     out << get_pool()->get_name() << ":" << get_index();
00435   }
00436 }

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