Panda3D

eggGroupNode.cxx

00001 // Filename: eggGroupNode.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 "eggGroupNode.h"
00016 #include "eggCoordinateSystem.h"
00017 #include "eggData.h"
00018 #include "eggFilenameNode.h"
00019 #include "eggExternalReference.h"
00020 #include "eggPrimitive.h"
00021 #include "eggPolygon.h"
00022 #include "eggCompositePrimitive.h"
00023 #include "eggMesher.h"
00024 #include "eggVertexPool.h"
00025 #include "eggVertex.h"
00026 #include "eggTextureCollection.h"
00027 #include "eggMaterialCollection.h"
00028 #include "pt_EggTexture.h"
00029 #include "pt_EggMaterial.h"
00030 #include "config_egg.h"
00031 
00032 #include "dSearchPath.h"
00033 #include "deg_2_rad.h"
00034 #include "dcast.h"
00035 #include "bamCacheRecord.h"
00036 
00037 #include <algorithm>
00038 
00039 TypeHandle EggGroupNode::_type_handle;
00040 
00041 
00042 ////////////////////////////////////////////////////////////////////
00043 //     Function: EggGroupNode::Copy constructor
00044 //       Access: Published
00045 //  Description:
00046 ////////////////////////////////////////////////////////////////////
00047 EggGroupNode::
00048 EggGroupNode(const EggGroupNode &copy) : EggNode(copy) {
00049   if (!copy.empty()) {
00050     egg_cat.warning()
00051       << "The EggGroupNode copy constructor does not copy children!\n";
00052   }
00053 }
00054 
00055 ////////////////////////////////////////////////////////////////////
00056 //     Function: EggGroupNode::Copy assignment operator
00057 //       Access: Published
00058 //  Description:
00059 ////////////////////////////////////////////////////////////////////
00060 EggGroupNode &EggGroupNode::
00061 operator =(const EggGroupNode &copy) {
00062   if (!copy.empty()) {
00063     egg_cat.warning()
00064       << "The EggGroupNode copy assignment does not copy children!\n";
00065   }
00066   EggNode::operator =(copy);
00067   return *this;
00068 }
00069 
00070 ////////////////////////////////////////////////////////////////////
00071 //     Function: EggGroupNode::Destructor
00072 //       Access: Published, Virtual
00073 //  Description:
00074 ////////////////////////////////////////////////////////////////////
00075 EggGroupNode::
00076 ~EggGroupNode() {
00077 }
00078 
00079 
00080 ////////////////////////////////////////////////////////////////////
00081 //     Function: EggGroupNode::write
00082 //       Access: Published, Virtual
00083 //  Description: Writes the group and all of its children to the
00084 //               indicated output stream in Egg format.
00085 ////////////////////////////////////////////////////////////////////
00086 void EggGroupNode::
00087 write(ostream &out, int indent_level) const {
00088   iterator i;
00089 
00090   // Since joints tend to reference vertex pools, which sometimes
00091   // appear later in the file, and since generally non-joints don't
00092   // reference joints, we try to maximize our chance of writing out a
00093   // one-pass readable egg file by writing joints at the end of the
00094   // list of children of a particular node.
00095 
00096   for (i = begin(); i != end(); ++i) {
00097     PT(EggNode) child = (*i);
00098     if (!child->is_joint()) {
00099       child->write(out, indent_level);
00100     }
00101   }
00102 
00103   for (i = begin(); i != end(); ++i) {
00104     PT(EggNode) child = (*i);
00105     if (child->is_joint()) {
00106       child->write(out, indent_level);
00107     }
00108   }
00109 }
00110 
00111 ////////////////////////////////////////////////////////////////////
00112 //     Function: EggGroupNode::begin
00113 //       Access: Published
00114 //  Description:
00115 ////////////////////////////////////////////////////////////////////
00116 EggGroupNode::iterator EggGroupNode::
00117 begin() const {
00118   return _children.begin();
00119 }
00120 
00121 ////////////////////////////////////////////////////////////////////
00122 //     Function: EggGroupNode::end
00123 //       Access: Published
00124 //  Description:
00125 ////////////////////////////////////////////////////////////////////
00126 EggGroupNode::iterator EggGroupNode::
00127 end() const {
00128   return _children.end();
00129 }
00130 
00131 ////////////////////////////////////////////////////////////////////
00132 //     Function: EggGroupNode::rbegin
00133 //       Access: Published
00134 //  Description:
00135 ////////////////////////////////////////////////////////////////////
00136 EggGroupNode::reverse_iterator EggGroupNode::
00137 rbegin() const {
00138   return _children.rbegin();
00139 }
00140 
00141 ////////////////////////////////////////////////////////////////////
00142 //     Function: EggGroupNode::rend
00143 //       Access: Published
00144 //  Description:
00145 ////////////////////////////////////////////////////////////////////
00146 EggGroupNode::reverse_iterator EggGroupNode::
00147 rend() const {
00148   return _children.rend();
00149 }
00150 
00151 ////////////////////////////////////////////////////////////////////
00152 //     Function: EggGroupNode::insert
00153 //       Access: Published
00154 //  Description:
00155 ////////////////////////////////////////////////////////////////////
00156 EggGroupNode::iterator EggGroupNode::
00157 insert(iterator position, PT(EggNode) x) {
00158   prepare_add_child(x);
00159   return _children.insert((Children::iterator &)position, x);
00160 }
00161 
00162 ////////////////////////////////////////////////////////////////////
00163 //     Function: EggGroupNode::erase
00164 //       Access: Published
00165 //  Description:
00166 ////////////////////////////////////////////////////////////////////
00167 EggGroupNode::iterator EggGroupNode::
00168 erase(iterator position) {
00169   prepare_remove_child(*position);
00170   return _children.erase((Children::iterator &)position);
00171 }
00172 
00173 ////////////////////////////////////////////////////////////////////
00174 //     Function: EggGroupNode::erase
00175 //       Access: Published
00176 //  Description:
00177 ////////////////////////////////////////////////////////////////////
00178 EggGroupNode::iterator EggGroupNode::
00179 erase(iterator first, iterator last) {
00180   iterator i;
00181   for (i = first; i != last; ++i) {
00182     prepare_remove_child(*i);
00183   }
00184   return _children.erase((Children::iterator &)first,
00185                          (Children::iterator &)last);
00186 }
00187 
00188 ////////////////////////////////////////////////////////////////////
00189 //     Function: EggGroupNode::replace
00190 //       Access: Published
00191 //  Description: Replaces the node at the indicated position with
00192 //               the indicated node.  It is an error to call this
00193 //               with an invalid position iterator (e.g. end()).
00194 ////////////////////////////////////////////////////////////////////
00195 void EggGroupNode::
00196 replace(iterator position, PT(EggNode) x) {
00197   nassertv(position != end());
00198 
00199   prepare_remove_child(*position);
00200   prepare_add_child(x);
00201   *(Children::iterator &)position = x;
00202 }
00203 
00204 ////////////////////////////////////////////////////////////////////
00205 //     Function: EggGroupNode::empty
00206 //       Access: Published
00207 //  Description:
00208 ////////////////////////////////////////////////////////////////////
00209 bool EggGroupNode::
00210 empty() const {
00211   return _children.empty();
00212 }
00213 
00214 ////////////////////////////////////////////////////////////////////
00215 //     Function: EggGroupNode::size
00216 //       Access: Published
00217 //  Description:
00218 ////////////////////////////////////////////////////////////////////
00219 EggGroupNode::size_type EggGroupNode::
00220 size() const {
00221   return _children.size();
00222 }
00223 
00224 ////////////////////////////////////////////////////////////////////
00225 //     Function: EggGroupNode::clear
00226 //       Access: Published
00227 //  Description:
00228 ////////////////////////////////////////////////////////////////////
00229 void EggGroupNode::
00230 clear() {
00231   erase(begin(), end());
00232 }
00233 
00234 ////////////////////////////////////////////////////////////////////
00235 //     Function: EggGroupNode::get_first_child
00236 //       Access: Published
00237 //  Description: Returns the first child in the group's list of
00238 //               children, or NULL if the list of children is empty.
00239 //               Can be used with get_next_child() to return the
00240 //               complete list of children without using the iterator
00241 //               class; however, this is non-thread-safe, and so is
00242 //               not recommended except for languages other than C++
00243 //               which cannot use the iterators.
00244 ////////////////////////////////////////////////////////////////////
00245 EggNode *EggGroupNode::
00246 get_first_child() {
00247   _gnc_iterator = begin();
00248   return get_next_child();
00249 }
00250 
00251 ////////////////////////////////////////////////////////////////////
00252 //     Function: EggGroupNode::get_next_child
00253 //       Access: Published
00254 //  Description: Returns the next child in the group's list of
00255 //               children since the last call to get_first_child() or
00256 //               get_next_child(), or NULL if the last child has been
00257 //               returned.  Can be used with get_first_child() to
00258 //               return the complete list of children without using
00259 //               the iterator class; however, this is non-thread-safe,
00260 //               and so is not recommended except for languages other
00261 //               than C++ which cannot use the iterators.
00262 //
00263 //               It is an error to call this without previously
00264 //               calling get_first_child().
00265 ////////////////////////////////////////////////////////////////////
00266 EggNode *EggGroupNode::
00267 get_next_child() {
00268   if (_gnc_iterator != end()) {
00269     return *_gnc_iterator++;
00270   }
00271   return NULL;
00272 }
00273 
00274 ////////////////////////////////////////////////////////////////////
00275 //     Function: EggGroupNode::add_child
00276 //       Access: Published
00277 //  Description: Adds the indicated child to the group and returns it.
00278 //               If the child node is already a child of some other
00279 //               node, removes it first.
00280 ////////////////////////////////////////////////////////////////////
00281 EggNode *EggGroupNode::
00282 add_child(EggNode *node) {
00283   test_ref_count_integrity();
00284   PT(EggNode) ptnode = node;
00285   if (node->_parent != NULL) {
00286     node->_parent->remove_child(node);
00287   }
00288   prepare_add_child(node);
00289   _children.push_back(node);
00290   return node;
00291 }
00292 
00293 ////////////////////////////////////////////////////////////////////
00294 //     Function: EggGroupNode::remove_child
00295 //       Access: Published
00296 //  Description: Removes the indicated child node from the group and
00297 //               returns it.  If the child was not already in the
00298 //               group, does nothing and returns NULL.
00299 ////////////////////////////////////////////////////////////////////
00300 PT(EggNode) EggGroupNode::
00301 remove_child(EggNode *node) {
00302   PT(EggNode) ptnode = node;
00303   iterator i = find(begin(), end(), ptnode);
00304   if (i == end()) {
00305     return PT(EggNode)();
00306   } else {
00307     // erase() calls prepare_remove_child().
00308     erase(i);
00309     return ptnode;
00310   }
00311 }
00312 
00313 
00314 ////////////////////////////////////////////////////////////////////
00315 //     Function: EggGroupNode::steal_children
00316 //       Access: Published
00317 //  Description: Moves all the children from the other node to this
00318 //               one.  This is especially useful because the group
00319 //               node copy assignment operator does not copy children.
00320 ////////////////////////////////////////////////////////////////////
00321 void EggGroupNode::
00322 steal_children(EggGroupNode &other) {
00323   Children::iterator ci;
00324   for (ci = other._children.begin();
00325        ci != other._children.end();
00326        ++ci) {
00327     other.prepare_remove_child(*ci);
00328     prepare_add_child(*ci);
00329   }
00330 
00331   _children.splice(_children.end(), other._children);
00332 }
00333 
00334 ////////////////////////////////////////////////////////////////////
00335 //     Function: EggGroupNode::find_child
00336 //       Access: Published
00337 //  Description: Returns the child of this node whose name is the
00338 //               indicated string, or NULL if there is no child of
00339 //               this node by that name.  Does not search recursively.
00340 ////////////////////////////////////////////////////////////////////
00341 EggNode *EggGroupNode::
00342 find_child(const string &name) const {
00343   Children::const_iterator ci;
00344   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00345     EggNode *child = (*ci);
00346     if (child->get_name() == name) {
00347       return child;
00348     }
00349   }
00350 
00351   return NULL;
00352 }
00353 
00354 ////////////////////////////////////////////////////////////////////
00355 //     Function: EggGroupNode::has_absolute_pathnames
00356 //       Access: Published
00357 //  Description: Returns true if any nodes at this level and below
00358 //               include a reference to a file via an absolute
00359 //               pathname, or false if all references are relative.
00360 ////////////////////////////////////////////////////////////////////
00361 bool EggGroupNode::
00362 has_absolute_pathnames() const {
00363   Children::const_iterator ci;
00364   for (ci = _children.begin();
00365        ci != _children.end();
00366        ++ci) {
00367     EggNode *child = *ci;
00368     if (child->is_of_type(EggTexture::get_class_type())) {
00369       EggTexture *tex = DCAST(EggTexture, child);
00370       if (!tex->get_filename().is_local()) {
00371         if (egg_cat.is_debug()) {
00372           egg_cat.debug()
00373             << "Absolute pathname: " << tex->get_filename()
00374             << "\n";
00375         }
00376         return true;
00377       }
00378 
00379       if (tex->has_alpha_filename()) {
00380         if (!tex->get_alpha_filename().is_local()) {
00381           if (egg_cat.is_debug()) {
00382             egg_cat.debug()
00383               << "Absolute pathname: " << tex->get_alpha_filename()
00384               << "\n";
00385           }
00386           return true;
00387         }
00388       }
00389 
00390     } else if (child->is_of_type(EggFilenameNode::get_class_type())) {
00391       EggFilenameNode *fnode = DCAST(EggFilenameNode, child);
00392       if (!fnode->get_filename().is_local()) {
00393         if (egg_cat.is_debug()) {
00394           egg_cat.debug()
00395             << "Absolute pathname: " << fnode->get_filename()
00396             << "\n";
00397         }
00398         return true;
00399       }
00400 
00401     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
00402       if (DCAST(EggGroupNode, child)->has_absolute_pathnames()) {
00403         return true;
00404       }
00405     }
00406   }
00407 
00408   return false;
00409 }
00410 
00411 ////////////////////////////////////////////////////////////////////
00412 //     Function: EggGroupNode::resolve_filenames
00413 //       Access: Published
00414 //  Description: Walks the tree and attempts to resolve any filenames
00415 //               encountered.  This looks up filenames along the
00416 //               specified search path; it does not automatically
00417 //               search the model_path for missing files.
00418 ////////////////////////////////////////////////////////////////////
00419 void EggGroupNode::
00420 resolve_filenames(const DSearchPath &searchpath) {
00421   VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00422   
00423   Children::iterator ci;
00424   for (ci = _children.begin();
00425        ci != _children.end();
00426        ++ci) {
00427     EggNode *child = *ci;
00428     if (child->is_of_type(EggTexture::get_class_type())) {
00429       EggTexture *tex = DCAST(EggTexture, child);
00430       Filename tex_filename = tex->get_filename();
00431       vfs->resolve_filename(tex_filename, searchpath);
00432       tex->set_filename(tex_filename);
00433       
00434       if (tex->has_alpha_filename()) {
00435         Filename alpha_filename = tex->get_alpha_filename();
00436         vfs->resolve_filename(alpha_filename, searchpath);
00437         tex->set_alpha_filename(alpha_filename);
00438       }
00439 
00440     } else if (child->is_of_type(EggFilenameNode::get_class_type())) {
00441       EggFilenameNode *fnode = DCAST(EggFilenameNode, child);
00442       Filename filename = fnode->get_filename();
00443       vfs->resolve_filename(filename, searchpath, fnode->get_default_extension());
00444       fnode->set_filename(filename);
00445 
00446     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
00447       DCAST(EggGroupNode, child)->resolve_filenames(searchpath);
00448     }
00449   }
00450 }
00451 
00452 ////////////////////////////////////////////////////////////////////
00453 //     Function: EggGroupNode::force_filenames
00454 //       Access: Published
00455 //  Description: Similar to resolve_filenames, but each non-absolute
00456 //               filename encountered is arbitrarily taken to be in
00457 //               the indicated directory, whether or not the so-named
00458 //               filename exists.
00459 ////////////////////////////////////////////////////////////////////
00460 void EggGroupNode::
00461 force_filenames(const Filename &directory) {
00462   Children::iterator ci;
00463   for (ci = _children.begin();
00464        ci != _children.end();
00465        ++ci) {
00466     EggNode *child = *ci;
00467     if (child->is_of_type(EggTexture::get_class_type())) {
00468       EggTexture *tex = DCAST(EggTexture, child);
00469       Filename tex_filename = tex->get_filename();
00470       if (tex_filename.is_local()) {
00471         tex->set_filename(Filename(directory, tex_filename));
00472       }
00473 
00474       if (tex->has_alpha_filename()) {
00475         Filename alpha_filename = tex->get_alpha_filename();
00476         if (alpha_filename.is_local()) {
00477           tex->set_alpha_filename(Filename(directory, alpha_filename));
00478         }
00479       }
00480 
00481     } else if (child->is_of_type(EggFilenameNode::get_class_type())) {
00482       EggFilenameNode *fnode = DCAST(EggFilenameNode, child);
00483       Filename filename = fnode->get_filename();
00484       if (filename.is_local()) {
00485         fnode->set_filename(Filename(directory, filename));
00486       }
00487 
00488     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
00489       DCAST(EggGroupNode, child)->force_filenames(directory);
00490     }
00491   }
00492 }
00493 
00494 ////////////////////////////////////////////////////////////////////
00495 //     Function: EggGroupNode::reverse_vertex_ordering
00496 //       Access: Published
00497 //  Description: Reverses the vertex ordering of all polygons defined
00498 //               at this node and below.  Does not change the surface
00499 //               normals, if any.
00500 ////////////////////////////////////////////////////////////////////
00501 void EggGroupNode::
00502 reverse_vertex_ordering() {
00503   Children::iterator ci;
00504   for (ci = _children.begin();
00505        ci != _children.end();
00506        ++ci) {
00507     EggNode *child = *ci;
00508     if (child->is_of_type(EggPrimitive::get_class_type())) {
00509       EggPrimitive *prim = DCAST(EggPrimitive, child);
00510       prim->reverse_vertex_ordering();
00511 
00512     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
00513       DCAST(EggGroupNode, child)->reverse_vertex_ordering();
00514     }
00515   }
00516 }
00517 
00518 ////////////////////////////////////////////////////////////////////
00519 //     Function: EggGroupNode::recompute_vertex_normals
00520 //       Access: Published
00521 //  Description: Recomputes all the vertex normals for polygon
00522 //               geometry at this group node and below so that they
00523 //               accurately reflect the vertex positions.  A shared
00524 //               edge between two polygons (even in different groups)
00525 //               is considered smooth if the angle between the two
00526 //               edges is less than threshold degrees.
00527 //
00528 //               This function also removes degenerate polygons that
00529 //               do not have enough vertices to define a normal.  It
00530 //               does not affect normals for other kinds of primitives
00531 //               like Nurbs or Points.
00532 //
00533 //               This function does not remove or adjust vertices in
00534 //               the vertex pool; it only adds new vertices with the
00535 //               correct normals.  Thus, it is a good idea to call
00536 //               remove_unused_vertices() after calling this.
00537 ////////////////////////////////////////////////////////////////////
00538 void EggGroupNode::
00539 recompute_vertex_normals(double threshold, CoordinateSystem cs) {
00540   // First, collect all the vertices together with their shared
00541   // polygons.
00542   NVertexCollection collection;
00543   r_collect_vertex_normals(collection, threshold, cs);
00544 
00545   // Now bust them into separate groups according to the edge
00546   // threshold.  Two polygons that share a vertex belong in the same
00547   // group only if the angle between their normals is within the
00548   // threshold.
00549 
00550   double cos_angle = cos(deg_2_rad(threshold));
00551 
00552   NVertexCollection::iterator ci;
00553   for (ci = collection.begin(); ci != collection.end(); ++ci) {
00554     NVertexGroup &group = (*ci).second;
00555 
00556     // Here's a group of polygons that share a vertex.  Build up a new
00557     // group that consists of just the first polygon and all the ones
00558     // that are within threshold degrees from it.
00559     NVertexGroup::iterator gi;
00560     gi = group.begin();
00561     while (gi != group.end()) {
00562       const NVertexReference &base_ref = (*gi);
00563       NVertexGroup new_group;
00564       NVertexGroup leftover_group;
00565       new_group.push_back(base_ref);
00566       ++gi;
00567 
00568       while (gi != group.end()) {
00569         const NVertexReference &ref = (*gi);
00570         double dot = base_ref._normal.dot(ref._normal);
00571         if (dot > cos_angle) {
00572           // These polygons are close enough to the same angle.
00573           new_group.push_back(ref);
00574         } else {
00575           // These polygons are not.
00576           leftover_group.push_back(ref);
00577         }
00578         ++gi;
00579       }
00580 
00581       // Now new_group is a collection of connected polygons and the
00582       // vertices that connect them.  Smooth these vertices.
00583       do_compute_vertex_normals(new_group);
00584 
00585       // And reset the group of remaining polygons.
00586       group.swap(leftover_group);
00587       gi = group.begin();
00588     }
00589   }
00590 }
00591 
00592 ////////////////////////////////////////////////////////////////////
00593 //     Function: EggGroupNode::recompute_polygon_normals
00594 //       Access: Published
00595 //  Description: Recomputes all the polygon normals for polygon
00596 //               geometry at this group node and below so that they
00597 //               accurately reflect the vertex positions.  Normals are
00598 //               removed from the vertices and defined only on
00599 //               polygons, giving the geometry a faceted appearance.
00600 //
00601 //               This function also removes degenerate polygons that
00602 //               do not have enough vertices to define a normal.  It
00603 //               does not affect normals for other kinds of primitives
00604 //               like Nurbs or Points.
00605 //
00606 //               This function does not remove or adjust vertices in
00607 //               the vertex pool; it only adds new vertices with the
00608 //               normals removed.  Thus, it is a good idea to call
00609 //               remove_unused_vertices() after calling this.
00610 ////////////////////////////////////////////////////////////////////
00611 void EggGroupNode::
00612 recompute_polygon_normals(CoordinateSystem cs) {
00613   Children::iterator ci, cnext;
00614   ci = _children.begin();
00615   while (ci != _children.end()) {
00616     cnext = ci;
00617     ++cnext;
00618     EggNode *child = *ci;
00619 
00620     if (child->is_of_type(EggPolygon::get_class_type())) {
00621       EggPolygon *polygon = DCAST(EggPolygon, child);
00622 
00623       if (!polygon->recompute_polygon_normal(cs)) {
00624         // The polygon is degenerate.  Remove it.
00625         prepare_remove_child(child);
00626         _children.erase(ci);
00627 
00628       } else {
00629         // Remove the normal from each polygon vertex.
00630         size_t num_vertices = polygon->size();
00631         for (size_t i = 0; i < num_vertices; i++) {
00632           EggVertex *vertex = polygon->get_vertex(i);
00633           EggVertexPool *pool = vertex->get_pool();
00634 
00635           if (vertex->has_normal()) {
00636             EggVertex new_vertex(*vertex);
00637             new_vertex.clear_normal();
00638             EggVertex *unique = pool->create_unique_vertex(new_vertex);
00639             unique->copy_grefs_from(*vertex);
00640 
00641             polygon->set_vertex(i, unique);
00642           }
00643         }
00644       }
00645 
00646     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
00647       DCAST(EggGroupNode, child)->recompute_polygon_normals(cs);
00648     }
00649 
00650     ci = cnext;
00651   }
00652 }
00653 
00654 ////////////////////////////////////////////////////////////////////
00655 //     Function: EggGroupNode::strip_normals
00656 //       Access: Published
00657 //  Description: Removes all normals from primitives, and the vertices
00658 //               they reference, at this node and below.
00659 //
00660 //               This function does not remove or adjust vertices in
00661 //               the vertex pool; it only adds new vertices with the
00662 //               normal removed.  Thus, it is a good idea to call
00663 //               remove_unused_vertices() after calling this.
00664 ////////////////////////////////////////////////////////////////////
00665 void EggGroupNode::
00666 strip_normals() {
00667   Children::iterator ci;
00668   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00669     EggNode *child = *ci;
00670 
00671     if (child->is_of_type(EggPrimitive::get_class_type())) {
00672       EggPrimitive *prim = DCAST(EggPrimitive, child);
00673       prim->clear_normal();
00674 
00675       // Remove the normal from each prim vertex.
00676       size_t num_vertices = prim->size();
00677       for (size_t i = 0; i < num_vertices; i++) {
00678         EggVertex *vertex = prim->get_vertex(i);
00679         EggVertexPool *pool = vertex->get_pool();
00680 
00681         if (vertex->has_normal()) {
00682           EggVertex new_vertex(*vertex);
00683           new_vertex.clear_normal();
00684           EggVertex *unique = pool->create_unique_vertex(new_vertex);
00685           unique->copy_grefs_from(*vertex);
00686 
00687           prim->set_vertex(i, unique);
00688         }
00689       }
00690 
00691     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
00692       DCAST(EggGroupNode, child)->strip_normals();
00693     }
00694   }
00695 }
00696 
00697 ////////////////////////////////////////////////////////////////////
00698 //     Function: EggGroupNode::recompute_tangent_binormal
00699 //       Access: Published
00700 //  Description: This function recomputes the tangent and binormal for
00701 //               the named texture coordinate set for all vertices at
00702 //               this level and below.  Use the empty string for the
00703 //               default texture coordinate set.
00704 //
00705 //               It is necessary for each vertex to already have a
00706 //               normal (or at least a polygon normal), as well as a
00707 //               texture coordinate in the named texture coordinate
00708 //               set, before calling this function.  You might precede
00709 //               this with recompute_vertex_normals() to ensure that
00710 //               the normals exist.
00711 //
00712 //               Like recompute_vertex_normals(), this function does
00713 //               not remove or adjust vertices in the vertex pool; it
00714 //               only adds new vertices with the new tangents and
00715 //               binormals computed.  Thus, it is a good idea to call
00716 //               remove_unused_vertices() after calling this.
00717 ////////////////////////////////////////////////////////////////////
00718 bool EggGroupNode::
00719 recompute_tangent_binormal(const GlobPattern &uv_name) {
00720   // First, collect all the vertices together with their shared
00721   // polygons.
00722   TBNVertexCollection collection;
00723   r_collect_tangent_binormal(uv_name, collection);
00724 
00725   // Now compute the tangent and binormal separately for each common
00726   // group of vertices.
00727   TBNVertexCollection::const_iterator ci;
00728   for (ci = collection.begin(); ci != collection.end(); ++ci) {
00729     const TBNVertexValue &value = (*ci).first;
00730     const TBNVertexGroup &group = (*ci).second;
00731 
00732     do_compute_tangent_binormal(value, group);
00733   }
00734   
00735   return true;
00736 }
00737 
00738 ////////////////////////////////////////////////////////////////////
00739 //     Function: EggGroupNode::recompute_tangent_binormal
00740 //       Access: Published
00741 //  Description: This function recomputes the tangent and binormal for
00742 //               the named texture coordinate sets.
00743 //               Returns true if anything was done.
00744 ////////////////////////////////////////////////////////////////////
00745 bool EggGroupNode::
00746 recompute_tangent_binormal(const vector_string &names) {
00747   bool changed = false;
00748 
00749   for (vector_string::const_iterator si = names.begin();
00750        si != names.end();
00751        ++si) {
00752     GlobPattern uv_name(*si);
00753     nout << "Computing tangent and binormal for \"" << uv_name << "\"\n";
00754     recompute_tangent_binormal(uv_name);
00755     changed = true;
00756   }
00757   
00758   return changed;
00759 }
00760 
00761 ////////////////////////////////////////////////////////////////////
00762 //     Function: EggGroupNode::recompute_tangent_binormal_auto
00763 //       Access: Published
00764 //  Description: This function recomputes the tangent and binormal for
00765 //               any texture coordinate set that affects a normal map.
00766 //               Returns true if anything was done.
00767 ////////////////////////////////////////////////////////////////////
00768 bool EggGroupNode::
00769 recompute_tangent_binormal_auto() {
00770   vector_string names;
00771   EggTextureCollection texs;
00772   EggTextureCollection::iterator eti;
00773   texs.find_used_textures(this);
00774   for (eti = texs.begin(); eti != texs.end(); eti++) {
00775     EggTexture *eggtex = (*eti);
00776     if ((eggtex->get_env_type() == EggTexture::ET_normal)||
00777         (eggtex->get_env_type() == EggTexture::ET_normal_height)) {
00778       string uv = eggtex->get_uv_name();
00779       vector_string::iterator it = find(names.begin(), names.end(), uv);
00780       if (it == names.end()) {
00781         names.push_back(uv);
00782       }
00783     }
00784   }
00785   return recompute_tangent_binormal(names);
00786 }
00787 
00788 ////////////////////////////////////////////////////////////////////
00789 //     Function: EggGroupNode::triangulate_polygons
00790 //       Access: Published
00791 //  Description: Replace all higher-order polygons at this point in
00792 //               the scene graph and below with triangles.  Returns
00793 //               the total number of new triangles produced, less
00794 //               degenerate polygons removed.
00795 //
00796 //               If flags contains T_polygon and T_convex, both
00797 //               concave and convex polygons will be subdivided into
00798 //               triangles; with only T_polygon, only concave polygons
00799 //               will be subdivided, and convex polygons will be
00800 //               largely unchanged.
00801 ////////////////////////////////////////////////////////////////////
00802 int EggGroupNode::
00803 triangulate_polygons(int flags) {
00804   int num_produced = 0;
00805 
00806   Children children_copy = _children;
00807 
00808   Children::iterator ci;
00809   for (ci = children_copy.begin();
00810        ci != children_copy.end();
00811        ++ci) {
00812     EggNode *child = (*ci);
00813 
00814     if (child->is_of_type(EggPolygon::get_class_type())) {
00815       if ((flags & T_polygon) != 0) {
00816         EggPolygon *poly = DCAST(EggPolygon, child);
00817         poly->triangulate_in_place((flags & T_convex) != 0);
00818       }
00819 
00820     } else if (child->is_of_type(EggCompositePrimitive::get_class_type())) {
00821       if ((flags & T_composite) != 0) {
00822         EggCompositePrimitive *comp = DCAST(EggCompositePrimitive, child);
00823         comp->triangulate_in_place();
00824       }
00825 
00826     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
00827       if ((flags & T_recurse) != 0) {
00828         num_produced += DCAST(EggGroupNode, child)->triangulate_polygons(flags);
00829       }
00830     }
00831   }
00832 
00833   num_produced += max(0, (int)(_children.size() - children_copy.size()));
00834   return num_produced;
00835 }
00836 
00837 ////////////////////////////////////////////////////////////////////
00838 //     Function: EggGroupNode::mesh_triangles
00839 //       Access: Published
00840 //  Description: Combine triangles together into triangle strips, at
00841 //               this group and below.
00842 ////////////////////////////////////////////////////////////////////
00843 void EggGroupNode::
00844 mesh_triangles(int flags) {
00845   EggMesher mesher;
00846   mesher.mesh(this, (flags & T_flat_shaded) != 0);
00847 
00848   if ((flags & T_recurse) != 0) {
00849     EggGroupNode::iterator ci;
00850     for (ci = begin(); ci != end(); ++ci) {
00851       if ((*ci)->is_of_type(EggGroupNode::get_class_type())) {
00852         EggGroupNode *group_child = DCAST(EggGroupNode, *ci);
00853         group_child->mesh_triangles(flags);
00854       }
00855     }
00856   }
00857 }
00858 
00859 ////////////////////////////////////////////////////////////////////
00860 //     Function: EggGroupNode::rename_nodes
00861 //       Access: Published
00862 //  Description: Rename by stripping out the prefix
00863 ////////////////////////////////////////////////////////////////////
00864 int EggGroupNode::
00865 rename_nodes(vector_string strip_prefix, bool recurse) {
00866   int num_renamed = 0;
00867   for (unsigned int ni = 0; ni < strip_prefix.size(); ++ni) {
00868     string axe_name = strip_prefix[ni];
00869     if (this->get_name().substr(0, axe_name.size()) == axe_name) {
00870       string new_name = this->get_name().substr(axe_name.size());
00871       //cout << "renaming " << this->get_name() << "->" << new_name << endl;
00872       this->set_name(new_name);
00873       num_renamed += 1;
00874     }
00875   }
00876   if (recurse) {
00877     EggGroupNode::iterator ci;
00878     for (ci = begin(); ci != end(); ++ci) {
00879       if ((*ci)->is_of_type(EggGroupNode::get_class_type())) {
00880         EggGroupNode *group_child = DCAST(EggGroupNode, *ci);
00881         num_renamed += group_child->rename_nodes(strip_prefix, recurse);
00882       }
00883       else if ((*ci)->is_of_type(EggNode::get_class_type())) {
00884         EggNode *node_child = DCAST(EggNode, *ci);
00885         num_renamed += node_child->rename_node(strip_prefix);
00886       }
00887     }
00888   }
00889   return num_renamed;
00890 }
00891 
00892 ////////////////////////////////////////////////////////////////////
00893 //     Function: EggGroupNode::remove_unused_vertices
00894 //       Access: Published
00895 //  Description: Removes all vertices from VertexPools within this
00896 //               group or below that are not referenced by at least
00897 //               one primitive.  Also collapses together equivalent
00898 //               vertices, and renumbers all vertices after the
00899 //               operation so their indices are consecutive, beginning
00900 //               at zero.  Returns the total number of vertices
00901 //               removed.
00902 //
00903 //               Note that this operates on the VertexPools within
00904 //               this group level, without respect to primitives that
00905 //               reference these vertices (unlike other functions like
00906 //               strip_normals()).  It is therefore most useful to
00907 //               call this on the EggData root, rather than on a
00908 //               subgroup within the hierarchy, since a VertexPool may
00909 //               appear anywhere in the hierarchy.
00910 ////////////////////////////////////////////////////////////////////
00911 int EggGroupNode::
00912 remove_unused_vertices(bool recurse) {
00913   int num_removed = 0;
00914 
00915   Children::iterator ci, cnext;
00916   ci = _children.begin();
00917   while (ci != _children.end()) {
00918     cnext = ci;
00919     ++cnext;
00920     EggNode *child = *ci;
00921 
00922     if (child->is_of_type(EggVertexPool::get_class_type())) {
00923       EggVertexPool *vpool = DCAST(EggVertexPool, child);
00924       num_removed += vpool->remove_unused_vertices();
00925 
00926       if (vpool->empty()) {
00927         // If, after removing all the vertices, there's nothing left
00928         // in the vertex pool, then remove the whole vertex pool.
00929         _children.erase(ci);
00930       }
00931 
00932     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
00933       if (recurse) {
00934         num_removed += DCAST(EggGroupNode, child)->remove_unused_vertices(recurse);
00935       }
00936     }
00937 
00938     ci = cnext;
00939   }
00940 
00941   return num_removed;
00942 }
00943 
00944 ////////////////////////////////////////////////////////////////////
00945 //     Function: EggGroupNode::remove_invalid_primitives
00946 //       Access: Published
00947 //  Description: Removes primitives at this level and below which
00948 //               appear to be degenerate; e.g. polygons with fewer
00949 //               than 3 vertices, etc.  Returns the number of
00950 //               primitives removed.
00951 ////////////////////////////////////////////////////////////////////
00952 int EggGroupNode::
00953 remove_invalid_primitives(bool recurse) {
00954   int num_removed = 0;
00955 
00956   Children::iterator ci, cnext;
00957   ci = _children.begin();
00958   while (ci != _children.end()) {
00959     cnext = ci;
00960     ++cnext;
00961     EggNode *child = *ci;
00962 
00963     if (child->is_of_type(EggPrimitive::get_class_type())) {
00964       EggPrimitive *prim = DCAST(EggPrimitive, child);
00965       if (!prim->cleanup()) {
00966         _children.erase(ci);
00967         num_removed++;
00968       }
00969 
00970     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
00971       if (recurse) {
00972         num_removed += DCAST(EggGroupNode, child)->remove_invalid_primitives(recurse);
00973       }
00974     }
00975 
00976     ci = cnext;
00977   }
00978 
00979   return num_removed;
00980 }
00981 
00982 ////////////////////////////////////////////////////////////////////
00983 //     Function: EggGroupNode::clear_connected_shading
00984 //       Access: Published
00985 //  Description: Resets the connected_shading information on all
00986 //               primitives at this node and below, so that it may be
00987 //               accurately rederived by the next call to
00988 //               get_connected_shading().
00989 //
00990 //               It may be a good idea to call
00991 //               remove_unused_vertices() as well, to establish the
00992 //               correct connectivity between common vertices.
00993 ////////////////////////////////////////////////////////////////////
00994 void EggGroupNode::
00995 clear_connected_shading() {
00996   Children::iterator ci;
00997   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00998     EggNode *child = *ci;
00999 
01000     if (child->is_of_type(EggPrimitive::get_class_type())) {
01001       EggPrimitive *prim = DCAST(EggPrimitive, child);
01002       prim->clear_connected_shading();
01003     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01004       DCAST(EggGroupNode, child)->clear_connected_shading();
01005     }
01006   }
01007 }
01008 
01009 ////////////////////////////////////////////////////////////////////
01010 //     Function: EggGroupNode::get_connected_shading
01011 //       Access: Published
01012 //  Description: Queries the connected_shading information on all
01013 //               primitives at this node and below, to ensure that it
01014 //               has been completely filled in before we start mucking
01015 //               around with vertices.
01016 ////////////////////////////////////////////////////////////////////
01017 void EggGroupNode::
01018 get_connected_shading() {
01019   Children::iterator ci;
01020   for (ci = _children.begin(); ci != _children.end(); ++ci) {
01021     EggNode *child = *ci;
01022 
01023     if (child->is_of_type(EggPrimitive::get_class_type())) {
01024       EggPrimitive *prim = DCAST(EggPrimitive, child);
01025       prim->get_connected_shading();
01026     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01027       DCAST(EggGroupNode, child)->get_connected_shading();
01028     }
01029   }
01030 }
01031 
01032 ////////////////////////////////////////////////////////////////////
01033 //     Function: EggGroupNode::unify_attributes
01034 //       Access: Published
01035 //  Description: Applies per-vertex normal and color to all vertices,
01036 //               if they are in fact per-vertex (and different for
01037 //               each vertex), or moves them to the primitive if they
01038 //               are all the same.
01039 //
01040 //               After this call, either the primitive will have
01041 //               normals or its vertices will, but not both.  Ditto
01042 //               for colors.
01043 //
01044 //               If use_connected_shading is true, each polygon is
01045 //               considered in conjunction with all connected
01046 //               polygons; otherwise, each polygon is considered
01047 //               individually.
01048 //
01049 //               If allow_per_primitive is false, S_per_face or
01050 //               S_overall will treated like S_per_vertex: normals and
01051 //               colors will always be assigned to the vertices.  In
01052 //               this case, there will never be per-primitive colors
01053 //               or normals after this call returns.  On the other
01054 //               hand, if allow_per_primitive is true, then S_per_face
01055 //               means that normals and colors should be assigned to
01056 //               the primitives, and removed from the vertices, as
01057 //               described above.
01058 //
01059 //               This may create redundant vertices in the vertex
01060 //               pool, so it may be a good idea to follow this up with
01061 //               remove_unused_vertices().
01062 ////////////////////////////////////////////////////////////////////
01063 void EggGroupNode::
01064 unify_attributes(bool use_connected_shading, bool allow_per_primitive,
01065                  bool recurse) {
01066   Children::iterator ci;
01067   for (ci = _children.begin(); ci != _children.end(); ++ci) {
01068     EggNode *child = *ci;
01069 
01070     if (child->is_of_type(EggPrimitive::get_class_type())) {
01071       EggPrimitive *prim = DCAST(EggPrimitive, child);
01072 
01073       EggPrimitive::Shading shading = EggPrimitive::S_per_vertex;
01074 
01075       if (allow_per_primitive) {
01076         shading = prim->get_shading();
01077         if (use_connected_shading) {
01078           shading = prim->get_connected_shading();
01079         }
01080       }
01081 
01082       prim->unify_attributes(shading);
01083 
01084     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01085       if (recurse) {
01086         DCAST(EggGroupNode, child)->unify_attributes
01087           (use_connected_shading, allow_per_primitive, recurse);
01088       }
01089     }
01090   }
01091 }
01092 
01093 ////////////////////////////////////////////////////////////////////
01094 //     Function: EggGroupNode::apply_last_attribute
01095 //       Access: Published
01096 //  Description: Sets the last vertex of the triangle (or each
01097 //               component) to the primitive normal and/or color, if
01098 //               the primitive is flat-shaded.  This reflects the
01099 //               OpenGL convention of storing flat-shaded properties on
01100 //               the last vertex, although it is not usually a
01101 //               convention in Egg.
01102 //
01103 //               This may create redundant vertices in the vertex
01104 //               pool, so it may be a good idea to follow this up with
01105 //               remove_unused_vertices().
01106 ////////////////////////////////////////////////////////////////////
01107 void EggGroupNode::
01108 apply_last_attribute(bool recurse) {
01109   Children::iterator ci;
01110   for (ci = _children.begin(); ci != _children.end(); ++ci) {
01111     EggNode *child = *ci;
01112 
01113     if (child->is_of_type(EggPrimitive::get_class_type())) {
01114       EggPrimitive *prim = DCAST(EggPrimitive, child);
01115       prim->apply_last_attribute();
01116     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01117       if (recurse) {
01118         DCAST(EggGroupNode, child)->apply_last_attribute(recurse);
01119       }
01120     }
01121   }
01122 }
01123 
01124 ////////////////////////////////////////////////////////////////////
01125 //     Function: EggGroupNode::apply_first_attribute
01126 //       Access: Published
01127 //  Description: Sets the first vertex of the triangle (or each
01128 //               component) to the primitive normal and/or color, if
01129 //               the primitive is flat-shaded.  This reflects the
01130 //               DirectX convention of storing flat-shaded properties on
01131 //               the first vertex, although it is not usually a
01132 //               convention in Egg.
01133 //
01134 //               This may create redundant vertices in the vertex
01135 //               pool, so it may be a good idea to follow this up with
01136 //               remove_unused_vertices().
01137 ////////////////////////////////////////////////////////////////////
01138 void EggGroupNode::
01139 apply_first_attribute(bool recurse) {
01140   Children::iterator ci;
01141   for (ci = _children.begin(); ci != _children.end(); ++ci) {
01142     EggNode *child = *ci;
01143 
01144     if (child->is_of_type(EggPrimitive::get_class_type())) {
01145       EggPrimitive *prim = DCAST(EggPrimitive, child);
01146       prim->apply_first_attribute();
01147     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01148       if (recurse) {
01149         DCAST(EggGroupNode, child)->apply_first_attribute(recurse);
01150       }
01151     }
01152   }
01153 }
01154 
01155 ////////////////////////////////////////////////////////////////////
01156 //     Function: EggGroupNode::post_apply_flat_attribute
01157 //       Access: Published
01158 //  Description: Intended as a followup to apply_last_attribute(),
01159 //               this also sets an attribute on the first vertices of
01160 //               the primitive, if they don't already have an
01161 //               attribute set, just so they end up with *something*.
01162 ////////////////////////////////////////////////////////////////////
01163 void EggGroupNode::
01164 post_apply_flat_attribute(bool recurse) {
01165   Children::iterator ci;
01166   for (ci = _children.begin(); ci != _children.end(); ++ci) {
01167     EggNode *child = *ci;
01168 
01169     if (child->is_of_type(EggPrimitive::get_class_type())) {
01170       EggPrimitive *prim = DCAST(EggPrimitive, child);
01171       prim->post_apply_flat_attribute();
01172     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01173       if (recurse) {
01174         DCAST(EggGroupNode, child)->post_apply_flat_attribute(recurse);
01175       }
01176     }
01177   }
01178 }
01179 
01180 ////////////////////////////////////////////////////////////////////
01181 //     Function: EggGroupNode::has_primitives
01182 //       Access: Published, Virtual
01183 //  Description: Returns true if there are any primitives
01184 //               (e.g. polygons) defined within this group or below,
01185 //               false otherwise.
01186 ////////////////////////////////////////////////////////////////////
01187 bool EggGroupNode::
01188 has_primitives() const {
01189   Children::const_iterator ci;
01190   for (ci = _children.begin();
01191        ci != _children.end();
01192        ++ci) {
01193     if ((*ci)->has_primitives()) {
01194       return true;
01195     }
01196   }
01197 
01198   return false;
01199 }
01200 
01201 ////////////////////////////////////////////////////////////////////
01202 //     Function: EggGroupNode::joint_has_primitives
01203 //       Access: Published, Virtual
01204 //  Description: Returns true if there are any primitives
01205 //               (e.g. polygons) defined within this group or below,
01206 //               but the search does not include nested joints.
01207 ////////////////////////////////////////////////////////////////////
01208 bool EggGroupNode::
01209 joint_has_primitives() const {
01210   Children::const_iterator ci;
01211   for (ci = _children.begin();
01212        ci != _children.end();
01213        ++ci) {
01214     EggNode *child = (*ci);
01215 
01216     if (!child->is_joint()) {
01217       if (child->joint_has_primitives()) {
01218         return true;
01219       }
01220     }
01221   }
01222 
01223   return false;
01224 }
01225 
01226 ////////////////////////////////////////////////////////////////////
01227 //     Function: EggGroupNode::has_normals
01228 //       Access: Published, Virtual
01229 //  Description: Returns true if any of the primitives (e.g. polygons)
01230 //               defined within this group or below have either face
01231 //               or vertex normals defined, false otherwise.
01232 ////////////////////////////////////////////////////////////////////
01233 bool EggGroupNode::
01234 has_normals() const {
01235   Children::const_iterator ci;
01236   for (ci = _children.begin();
01237        ci != _children.end();
01238        ++ci) {
01239     if ((*ci)->has_normals()) {
01240       return true;
01241     }
01242   }
01243 
01244   return false;
01245 }
01246 
01247 ////////////////////////////////////////////////////////////////////
01248 //     Function: EggGroupNode::rebuild_vertex_pools
01249 //       Access: Published
01250 //  Description: Copies vertices used by the primitives at this group
01251 //               node (and below, if recurse is true) into one or more
01252 //               new vertex pools, and updates the primitives to
01253 //               reference these pools.  It is up to the caller to
01254 //               parent the newly-created vertex pools somewhere
01255 //               appropriate in the egg hierarchy.
01256 //
01257 //               No more than max_vertices will be placed into any one
01258 //               vertex pool.  This is the sole criteria for splitting
01259 //               vertex pools.
01260 ////////////////////////////////////////////////////////////////////
01261 void EggGroupNode::
01262 rebuild_vertex_pools(EggVertexPools &vertex_pools, unsigned int max_vertices,
01263                      bool recurse) {
01264   Children::iterator ci;
01265   for (ci = _children.begin(); ci != _children.end(); ++ci) {
01266     EggNode *child = *ci;
01267 
01268     if (child->is_of_type(EggPrimitive::get_class_type())) {
01269       typedef pvector< PT(EggVertex) > Vertices;
01270       Vertices vertices;
01271       EggPrimitive *prim = DCAST(EggPrimitive, child);
01272 
01273       // Copy all of the vertices out.
01274       EggPrimitive::const_iterator pi;
01275       for (pi = prim->begin(); pi != prim->end(); ++pi) {
01276         vertices.push_back(*pi);
01277       }
01278 
01279       typedef pvector<EggAttributes> Attributes;
01280       Attributes attributes;
01281 
01282       if (prim->is_of_type(EggCompositePrimitive::get_class_type())) {
01283         // A compositive primitive has the additional complication of
01284         // dealing with its attributes.
01285         EggCompositePrimitive *cprim = DCAST(EggCompositePrimitive, prim);
01286         int i;
01287         int num_components = cprim->get_num_components();
01288         for (i = 0; i < num_components; i++) {
01289           attributes.push_back(*cprim->get_component(i));
01290         }
01291       }
01292 
01293       prim->clear();
01294 
01295       // Now look for a new home for the vertices.  First, see if any
01296       // of the vertex pools we've already created already have a copy
01297       // of each one of the vertices.
01298       bool found_pool = false;
01299       EggVertexPool *best_pool = NULL;
01300       int best_new_vertices = 0;
01301 
01302       Vertices new_vertices;
01303       EggVertexPools::iterator vpi;
01304       for (vpi = vertex_pools.begin(); 
01305            vpi != vertex_pools.end() && !found_pool;
01306            ++vpi) {
01307         EggVertexPool *vertex_pool = (*vpi);
01308         int num_new_vertices = 0;
01309 
01310         new_vertices.clear();
01311         new_vertices.reserve(vertices.size());
01312 
01313         Vertices::const_iterator vi;
01314         for (vi = vertices.begin(); 
01315              vi != vertices.end() && !found_pool; 
01316              ++vi) {
01317           EggVertex *vertex = (*vi);
01318           EggVertex *new_vertex = vertex_pool->find_matching_vertex(*vertex);
01319           new_vertices.push_back(new_vertex);
01320           if (new_vertex == (EggVertex *)NULL) {
01321             ++num_new_vertices;
01322           }
01323         }
01324 
01325         if (num_new_vertices == 0) {
01326           // Great, we found a vertex pool that already shares all
01327           // these vertices.  No need to look any further.
01328           found_pool = true;
01329 
01330         } else if (vertex_pool->size() + num_new_vertices <= max_vertices) {
01331           // We would have to add some vertices to this pool, so this
01332           // vertex pool qualifies only if the number of vertices we
01333           // have to add would still keep it within our limit.
01334           if (best_pool == (EggVertexPool *)NULL ||
01335               num_new_vertices < best_new_vertices) {
01336             // This is currently our most favorable vertex pool.
01337             best_pool = vertex_pool;
01338             best_new_vertices = num_new_vertices;
01339           }
01340         }
01341       }
01342 
01343       if (!found_pool) {
01344         if (best_pool == (EggVertexPool *)NULL) {
01345           // There was no vertex pool that qualified.  We will have to
01346           // create a new vertex pool.
01347           best_pool = new EggVertexPool("");
01348           vertex_pools.push_back(best_pool);
01349         }
01350 
01351         new_vertices.clear();
01352         new_vertices.reserve(vertices.size());
01353 
01354         Vertices::const_iterator vi;
01355         for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
01356           EggVertex *vertex = (*vi);
01357           EggVertex *new_vertex = best_pool->create_unique_vertex(*vertex);
01358           new_vertex->copy_grefs_from(*vertex);
01359           new_vertices.push_back(new_vertex);
01360         }
01361       }
01362 
01363       Vertices::const_iterator vi;
01364       nassertv(new_vertices.size() == vertices.size());
01365       for (vi = new_vertices.begin(); vi != new_vertices.end(); ++vi) {
01366         EggVertex *new_vertex = (*vi);
01367         nassertv(new_vertex != (EggVertex *)NULL);
01368         prim->add_vertex(new_vertex);
01369       }
01370 
01371       if (prim->is_of_type(EggCompositePrimitive::get_class_type())) {
01372         // Now restore the composite attributes.
01373         EggCompositePrimitive *cprim = DCAST(EggCompositePrimitive, prim);
01374         int i;
01375         int num_components = cprim->get_num_components();
01376         nassertv(num_components == (int)attributes.size());
01377         for (i = 0; i < num_components; i++) {
01378           cprim->set_component(i, &attributes[i]);
01379         }
01380       }
01381         
01382     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01383       if (recurse) {
01384         DCAST(EggGroupNode, child)->rebuild_vertex_pools(vertex_pools, max_vertices, recurse);
01385       }
01386     }
01387   }
01388 }
01389 
01390 ////////////////////////////////////////////////////////////////////
01391 //     Function: EggGroupNode::update_under
01392 //       Access: Protected, Virtual
01393 //  Description: This function is called from within EggGroupNode
01394 //               whenever the parentage of the node has changed.  It
01395 //               should update the depth and under_instance flags
01396 //               accordingly.
01397 //
01398 //               Offset is the difference between the old depth value
01399 //               and the new value.  It should be consistent with the
01400 //               supplied depth value.  If it is not, we have some
01401 //               error.
01402 ////////////////////////////////////////////////////////////////////
01403 void EggGroupNode::
01404 update_under(int depth_offset) {
01405   EggNode::update_under(depth_offset);
01406 
01407   Children::iterator ci;
01408   for (ci = _children.begin();
01409        ci != _children.end();
01410        ++ci) {
01411     nassertv((*ci)->get_parent() == this);
01412     (*ci)->update_under(depth_offset);
01413   }
01414 }
01415 
01416 ////////////////////////////////////////////////////////////////////
01417 //     Function: EggGroupNode::r_transform
01418 //       Access: Protected, Virtual
01419 //  Description: This is called from within the egg code by
01420 //               transform().  It applies a transformation matrix
01421 //               to the current node in some sensible way, then
01422 //               continues down the tree.
01423 //
01424 //               The first matrix is the transformation to apply; the
01425 //               second is its inverse.  The third parameter is the
01426 //               coordinate system we are changing to, or CS_default
01427 //               if we are not changing coordinate systems.
01428 ////////////////////////////////////////////////////////////////////
01429 void EggGroupNode::
01430 r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
01431             CoordinateSystem to_cs) {
01432   Children::iterator ci;
01433   for (ci = _children.begin();
01434        ci != _children.end();
01435        ++ci) {
01436     (*ci)->r_transform(mat, inv, to_cs);
01437   }
01438 }
01439 
01440 ////////////////////////////////////////////////////////////////////
01441 //     Function: EggGroupNode::r_transform_vertices
01442 //       Access: Protected, Virtual
01443 //  Description: This is called from within the egg code by
01444 //               transform_vertices_only()().  It applies a
01445 //               transformation matrix to the current node in some
01446 //               sensible way (if the current node is a vertex pool
01447 //               with vertices), then continues down the tree.
01448 ////////////////////////////////////////////////////////////////////
01449 void EggGroupNode::
01450 r_transform_vertices(const LMatrix4d &mat) {
01451   Children::iterator ci;
01452   for (ci = _children.begin();
01453        ci != _children.end();
01454        ++ci) {
01455     (*ci)->r_transform_vertices(mat);
01456   }
01457 }
01458 
01459 ////////////////////////////////////////////////////////////////////
01460 //     Function: EggGroupNode::r_mark_coordsys
01461 //       Access: Protected, Virtual
01462 //  Description: This is only called immediately after loading an egg
01463 //               file from disk, to propagate the value found in the
01464 //               CoordinateSystem entry (or the default Y-up
01465 //               coordinate system) to all nodes that care about what
01466 //               the coordinate system is.
01467 ////////////////////////////////////////////////////////////////////
01468 void EggGroupNode::
01469 r_mark_coordsys(CoordinateSystem cs) {
01470   Children::iterator ci;
01471   for (ci = _children.begin();
01472        ci != _children.end();
01473        ++ci) {
01474     (*ci)->r_mark_coordsys(cs);
01475   }
01476 }
01477 
01478 ////////////////////////////////////////////////////////////////////
01479 //     Function: EggGroupNode::r_flatten_transforms
01480 //       Access: Protected, Virtual
01481 //  Description: The recursive implementation of flatten_transforms().
01482 ////////////////////////////////////////////////////////////////////
01483 void EggGroupNode::
01484 r_flatten_transforms() {
01485   Children::iterator ci;
01486   for (ci = _children.begin();
01487        ci != _children.end();
01488        ++ci) {
01489     (*ci)->r_flatten_transforms();
01490   }
01491 }
01492 
01493 ////////////////////////////////////////////////////////////////////
01494 //     Function: EggGroupNode::r_apply_texmats
01495 //       Access: Protected, Virtual
01496 //  Description: The recursive implementation of apply_texmats().
01497 ////////////////////////////////////////////////////////////////////
01498 void EggGroupNode::
01499 r_apply_texmats(EggTextureCollection &textures) {
01500   Children::iterator ci;
01501   for (ci = _children.begin();
01502        ci != _children.end();
01503        ++ci) {
01504     (*ci)->r_apply_texmats(textures);
01505   }
01506 }
01507 
01508 ////////////////////////////////////////////////////////////////////
01509 //     Function: EggGroupNode::find_coordsys_entry()
01510 //       Access: Protected
01511 //  Description: Walks the tree, looking for an EggCoordinateSystem
01512 //               entry.  If one is found, extracts it and returns its
01513 //               value.  If multiple entries are found, extracts all
01514 //               of them and returns CS_invalid if they disagree.
01515 ////////////////////////////////////////////////////////////////////
01516 CoordinateSystem EggGroupNode::
01517 find_coordsys_entry() {
01518   CoordinateSystem coordsys = CS_default;
01519 
01520   // We can do this ci/cnext iteration through the list as we modify
01521   // it, only because we know this works with an STL list type
01522   // container.  If this were a vector or a set, this wouldn't
01523   // necessarily work.
01524 
01525   Children::iterator ci, cnext;
01526   ci = _children.begin();
01527   while (ci != _children.end()) {
01528     cnext = ci;
01529     ++cnext;
01530     EggNode *child = *ci;
01531 
01532     if (child->is_of_type(EggCoordinateSystem::get_class_type())) {
01533       CoordinateSystem new_cs =
01534         DCAST(EggCoordinateSystem, child)->get_value();
01535 
01536       // Now remove the CoordinateSystem entry from our child list.
01537       prepare_remove_child(child);
01538       _children.erase(ci);
01539 
01540       if (new_cs != CS_default) {
01541         if (coordsys != CS_default && coordsys != new_cs) {
01542           coordsys = CS_invalid;
01543         } else {
01544           coordsys = new_cs;
01545         }
01546       }
01547 
01548     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01549       CoordinateSystem new_cs =
01550         DCAST(EggGroupNode, child)->find_coordsys_entry();
01551       if (new_cs != CS_default) {
01552         if (coordsys != CS_default && coordsys != new_cs) {
01553           coordsys = CS_invalid;
01554         } else {
01555           coordsys = new_cs;
01556         }
01557       }
01558     }
01559 
01560     ci = cnext;
01561   }
01562 
01563   return coordsys;
01564 }
01565 
01566 ////////////////////////////////////////////////////////////////////
01567 //     Function: EggGroupNode::find_textures()
01568 //       Access: Protected
01569 //  Description: Walks the tree, looking for EggTextures.  Each
01570 //               EggTexture that is found is removed from the
01571 //               hierarchy and added to the EggTextureCollection.
01572 //               Returns the number of EggTextures found.
01573 ////////////////////////////////////////////////////////////////////
01574 int EggGroupNode::
01575 find_textures(EggTextureCollection *collection) {
01576   int num_found = 0;
01577 
01578   // We can do this ci/cnext iteration through the list as we modify
01579   // it, only because we know this works with an STL list type
01580   // container.  If this were a vector or a set, this wouldn't
01581   // necessarily work.
01582 
01583   Children::iterator ci, cnext;
01584   ci = _children.begin();
01585   while (ci != _children.end()) {
01586     cnext = ci;
01587     ++cnext;
01588     EggNode *child = *ci;
01589 
01590     if (child->is_of_type(EggTexture::get_class_type())) {
01591       PT_EggTexture tex = DCAST(EggTexture, child);
01592 
01593       // Now remove the EggTexture entry from our child list.
01594       prepare_remove_child(tex);
01595       _children.erase(ci);
01596 
01597       // And add it to the collection.
01598       collection->add_texture(tex);
01599       num_found++;
01600 
01601     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01602       num_found +=
01603         DCAST(EggGroupNode, child)->find_textures(collection);
01604     }
01605 
01606     ci = cnext;
01607   }
01608 
01609   return num_found;
01610 }
01611 
01612 ////////////////////////////////////////////////////////////////////
01613 //     Function: EggGroupNode::find_materials()
01614 //       Access: Protected
01615 //  Description: Walks the tree, looking for EggMaterials.  Each
01616 //               EggMaterial that is found is removed from the
01617 //               hierarchy and added to the EggMaterialCollection.
01618 //               Returns the number of EggMaterials found.
01619 ////////////////////////////////////////////////////////////////////
01620 int EggGroupNode::
01621 find_materials(EggMaterialCollection *collection) {
01622   int num_found = 0;
01623 
01624   // We can do this ci/cnext iteration through the list as we modify
01625   // it, only because we know this works with an STL list type
01626   // container.  If this were a vector or a set, this wouldn't
01627   // necessarily work.
01628 
01629   Children::iterator ci, cnext;
01630   ci = _children.begin();
01631   while (ci != _children.end()) {
01632     cnext = ci;
01633     ++cnext;
01634     EggNode *child = *ci;
01635 
01636     if (child->is_of_type(EggMaterial::get_class_type())) {
01637       PT_EggMaterial tex = DCAST(EggMaterial, child);
01638 
01639       // Now remove the EggMaterial entry from our child list.
01640       prepare_remove_child(tex);
01641       _children.erase(ci);
01642 
01643       // And add it to the collection.
01644       collection->add_material(tex);
01645       num_found++;
01646 
01647     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01648       num_found +=
01649         DCAST(EggGroupNode, child)->find_materials(collection);
01650     }
01651 
01652     ci = cnext;
01653   }
01654 
01655   return num_found;
01656 }
01657 
01658 ////////////////////////////////////////////////////////////////////
01659 //     Function: EggGroupNode::r_load_externals
01660 //       Access: Protected
01661 //  Description: Walks the tree and locates unloaded external
01662 //               reference nodes, which it attempts to locate and load
01663 //               in.  The reference node is replaced with the entire
01664 //               subtree loaded.  This is intended to be called from
01665 //               EggData::load_externals().
01666 ////////////////////////////////////////////////////////////////////
01667 bool EggGroupNode::
01668 r_load_externals(const DSearchPath &searchpath, CoordinateSystem coordsys,
01669                  BamCacheRecord *record) {
01670   bool success = true;
01671 
01672   Children::iterator ci;
01673   for (ci = _children.begin();
01674        ci != _children.end();
01675        ++ci) {
01676     EggNode *child = *ci;
01677     if (child->is_of_type(EggExternalReference::get_class_type())) {
01678       PT(EggExternalReference) ref = DCAST(EggExternalReference, child);
01679 
01680       // Replace the reference with an empty group node.  When we load
01681       // the external file successfully, we'll put its contents here.
01682       Filename filename = ref->get_filename();
01683       EggGroupNode *new_node =
01684         new EggGroupNode(filename.get_basename_wo_extension());
01685       replace(ci, new_node);
01686 
01687       if (!EggData::resolve_egg_filename(filename, searchpath)) {
01688         egg_cat.error()
01689           << "Could not locate " << filename << " in "
01690           << searchpath << "\n";
01691       } else {
01692         // Now define a new EggData structure to hold the external
01693         // reference, and load it.
01694         EggData ext_data;
01695         ext_data.set_coordinate_system(coordsys);
01696         ext_data.set_auto_resolve_externals(true);
01697         if (ext_data.read(filename)) {
01698           // The external file was read correctly.  Add its contents
01699           // into the tree at this point.
01700           if (record != (BamCacheRecord *)NULL) {
01701             record->add_dependent_file(filename);
01702           }
01703 
01704           success =
01705             ext_data.load_externals(searchpath, record)
01706             && success;
01707           new_node->steal_children(ext_data);
01708         }
01709       }
01710 
01711     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01712       EggGroupNode *group_child = DCAST(EggGroupNode, child);
01713       success =
01714         group_child->r_load_externals(searchpath, coordsys, record)
01715         && success;
01716     }
01717   }
01718   return success;
01719 }
01720 
01721 
01722 ////////////////////////////////////////////////////////////////////
01723 //     Function: EggGroupNode::prepare_add_child
01724 //       Access: Private
01725 //  Description: Marks the node as a child of the group.  This is an
01726 //               internal function called by the STL-like functions
01727 //               push_back() and insert(), in preparation for actually
01728 //               adding the child.
01729 //
01730 //               It is an error to add a node that is already a child
01731 //               of this group or some other group.
01732 ////////////////////////////////////////////////////////////////////
01733 void EggGroupNode::
01734 prepare_add_child(EggNode *node) {
01735   nassertv(node != (EggNode *)NULL);
01736   test_ref_count_integrity();
01737   node->test_ref_count_integrity();
01738   // Make sure the node is not already a child of some other group.
01739   nassertv(node->get_parent() == NULL);
01740   nassertv(node->get_depth() == 0);
01741   node->_parent = this;
01742 
01743   node->update_under(get_depth() + 1);
01744 }
01745 
01746 
01747 ////////////////////////////////////////////////////////////////////
01748 //     Function: EggGroupNode::prepare_remove_child
01749 //       Access: Private
01750 //  Description: Marks the node as removed from the group.  This is an
01751 //               internal function called by the STL-like functions
01752 //               pop_back() and erase(), in preparation for actually
01753 //               doing the removal.
01754 //
01755 //               It is an error to attempt to remove a node that is
01756 //               not already a child of this group.
01757 ////////////////////////////////////////////////////////////////////
01758 void EggGroupNode::
01759 prepare_remove_child(EggNode *node) {
01760   nassertv(node != (EggNode *)NULL);
01761   // Make sure the node is in fact a child of this group.
01762   nassertv(node->get_parent() == this);
01763   nassertv(node->get_depth() == get_depth() + 1);
01764   node->_parent = NULL;
01765 
01766   node->update_under(-(get_depth() + 1));
01767 }
01768 
01769 
01770 
01771 ////////////////////////////////////////////////////////////////////
01772 //     Function: EggGroupNode::r_collect_vertex_normals
01773 //       Access: Private
01774 //  Description: This is part of the implementation of
01775 //               recompute_vertex_normals().  It walks the scene graph
01776 //               at this group node and below, identifying all the
01777 //               polygons and the vertices they have in common.
01778 ////////////////////////////////////////////////////////////////////
01779 void EggGroupNode::
01780 r_collect_vertex_normals(EggGroupNode::NVertexCollection &collection,
01781                          double threshold, CoordinateSystem cs) {
01782   // We can do this ci/cnext iteration through the list as we modify
01783   // it, only because we know this works with an STL list type
01784   // container.  If this were a vector or a set, this wouldn't
01785   // necessarily work.
01786 
01787   Children::iterator ci, cnext;
01788   ci = _children.begin();
01789   while (ci != _children.end()) {
01790     cnext = ci;
01791     ++cnext;
01792     EggNode *child = *ci;
01793 
01794     if (child->is_of_type(EggPolygon::get_class_type())) {
01795       EggPolygon *polygon = DCAST(EggPolygon, child);
01796       polygon->clear_normal();
01797 
01798       NVertexReference ref;
01799       ref._polygon = polygon;
01800       if (!polygon->calculate_normal(ref._normal, cs)) {
01801         // The polygon is degenerate.  Remove it.
01802 
01803         prepare_remove_child(child);
01804         _children.erase(ci);
01805 
01806       } else {
01807         // Now add each vertex from the polygon separately to our
01808         // collection.
01809         size_t num_vertices = polygon->size();
01810         for (size_t i = 0; i < num_vertices; i++) {
01811           EggVertex *vertex = polygon->get_vertex(i);
01812           ref._vertex = i;
01813           collection[vertex->get_pos3()].push_back(ref);
01814         }
01815       }
01816 
01817     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01818       EggGroupNode *group = DCAST(EggGroupNode, child);
01819 
01820       // We can't share vertices across an Instance node.  Don't
01821       // even bother trying.  Instead, just restart.
01822       if (group->is_under_instance()) {
01823         group->recompute_vertex_normals(threshold, cs);
01824       } else {
01825         group->r_collect_vertex_normals(collection, threshold, cs);
01826       }
01827     }
01828 
01829     ci = cnext;
01830   }
01831 }
01832 
01833 ////////////////////////////////////////////////////////////////////
01834 //     Function: EggGroupNode::do_compute_vertex_normals
01835 //       Access: Private
01836 //  Description: This is part of the implementation of
01837 //               recompute_vertex_normals().  It accepts a group of
01838 //               polygons and their common normals, and computes the
01839 //               same normal for all their shared vertices.
01840 ////////////////////////////////////////////////////////////////////
01841 void EggGroupNode::
01842 do_compute_vertex_normals(const NVertexGroup &group) {
01843   nassertv(!group.empty());
01844 
01845   // Determine the common normal.  This is simply the average of all
01846   // the polygon normals that share this vertex.
01847   Normald normal(0.0, 0.0, 0.0);
01848   NVertexGroup::const_iterator gi;
01849   for (gi = group.begin(); gi != group.end(); ++gi) {
01850     const NVertexReference &ref = (*gi);
01851     normal += ref._normal;
01852   }
01853 
01854   normal /= (double)group.size();
01855   normal.normalize();
01856 
01857   // Now we have the common normal; apply it to all the vertices.
01858 
01859   for (gi = group.begin(); gi != group.end(); ++gi) {
01860     const NVertexReference &ref = (*gi);
01861     EggVertex *vertex = ref._polygon->get_vertex(ref._vertex);
01862     EggVertexPool *pool = vertex->get_pool();
01863 
01864     EggVertex new_vertex(*vertex);
01865     new_vertex.set_normal(normal);
01866     EggVertex *unique = pool->create_unique_vertex(new_vertex);
01867     unique->copy_grefs_from(*vertex);
01868 
01869     ref._polygon->set_vertex(ref._vertex, unique);
01870   }
01871 }
01872 
01873 ////////////////////////////////////////////////////////////////////
01874 //     Function: EggGroupNode::r_collect_tangent_binormal
01875 //       Access: Private
01876 //  Description: This is part of the implementation of
01877 //               recompute_tangent_binormal().  It walks the scene
01878 //               graph at this group node and below, identifying all
01879 //               the polygons and the vertices they have in common.
01880 ////////////////////////////////////////////////////////////////////
01881 void EggGroupNode::
01882 r_collect_tangent_binormal(const GlobPattern &uv_name,
01883                            EggGroupNode::TBNVertexCollection &collection) {
01884   Children::iterator ci;
01885   for (ci = _children.begin(); ci != _children.end(); ++ci) {
01886     EggNode *child = *ci;
01887 
01888     if (child->is_of_type(EggPolygon::get_class_type())) {
01889       EggPolygon *polygon = DCAST(EggPolygon, child);
01890 
01891       TBNVertexReference ref;
01892       ref._polygon = polygon;
01893 
01894       // Now add each vertex from the polygon separately to our
01895       // collection.
01896       size_t num_vertices = polygon->size();
01897       for (size_t i = 0; i < num_vertices; i++) {
01898         // We look at the triangle formed by each three consecutive
01899         // vertices to determine the s direction and t direction at
01900         // each vertex.  v1 is the key vertex, the one at position i;
01901         // v2 is vertex i + 1, and v3 is vertex i - 1.
01902         EggVertex *v1 = polygon->get_vertex(i);
01903         EggVertex *v2 = polygon->get_vertex((i + 1) % num_vertices);
01904         EggVertex *v3 = polygon->get_vertex((i + num_vertices - 1) % num_vertices);
01905         if (v1->has_normal() || polygon->has_normal()) {
01906           // Go through all of the UV names on the vertex, looking for
01907           // one that matches the glob pattern.
01908           EggVertex::const_uv_iterator uvi;
01909           for (uvi = v1->uv_begin(); uvi != v1->uv_end(); ++uvi) {
01910             EggVertexUV *uv_obj = (*uvi);
01911             string name = uv_obj->get_name();
01912             if (uv_name.matches(name) &&
01913                 v2->has_uv(name) && v3->has_uv(name)) {
01914               TBNVertexValue value;
01915               value._uv_name = name;
01916               value._pos = v1->get_pos3();
01917               if (v1->has_normal()) {
01918                 value._normal = v1->get_normal();
01919               } else {
01920                 value._normal = polygon->get_normal();
01921               }
01922               value._uv = v1->get_uv(name);
01923               
01924               // Compute the s direction and t direction for this vertex.
01925               LPoint3d p1 = v1->get_pos3();
01926               LPoint3d p2 = v2->get_pos3();
01927               LPoint3d p3 = v3->get_pos3();
01928               
01929               TexCoordd w1 = v1->get_uv(name);
01930               TexCoordd w2 = v2->get_uv(name);
01931               TexCoordd w3 = v3->get_uv(name);
01932 
01933               // Check the facing of the texture; we will have to
01934               // split vertices whose UV's are mirrored along a seam.
01935               // The facing is determined by the winding order of the
01936               // texcoords on the polygon.  A front-facing polygon
01937               // should not contribute to the tangent and binormal of
01938               // a back-facing polygon, and vice-versa.
01939               value._facing = is_right(w1 - w2, w3 - w1);
01940 
01941               double x1 = p2[0] - p1[0];
01942               double x2 = p3[0] - p1[0];
01943               double y1 = p2[1] - p1[1];
01944               double y2 = p3[1] - p1[1];
01945               double z1 = p2[2] - p1[2];
01946               double z2 = p3[2] - p1[2];
01947               
01948               double s1 = w2[0] - w1[0];
01949               double s2 = w3[0] - w1[0];
01950               double t1 = w2[1] - w1[1];
01951               double t2 = w3[1] - w1[1];
01952               
01953               double denom = (s1 * t2 - s2 * t1);
01954               if (denom == 0.0) {
01955                 ref._sdir.set(0.0, 0.0, 0.0);
01956                 ref._tdir.set(0.0, 0.0, 0.0);
01957               } else {
01958                 double r = 1.0 / denom;
01959                 ref._sdir.set((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
01960                               (t2 * z1 - t1 * z2) * r);
01961                 ref._tdir.set((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
01962                               (s1 * z2 - s2 * z1) * r);
01963               }
01964 
01965               // Store the vertex referenced to the polygon.
01966               ref._vertex = i;
01967               collection[value].push_back(ref);
01968             }
01969           }
01970         }
01971       }
01972 
01973     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01974       EggGroupNode *group = DCAST(EggGroupNode, child);
01975 
01976       // We can't share vertices across an Instance node.  Don't
01977       // even bother trying.  Instead, just restart.
01978       if (group->is_under_instance()) {
01979         group->recompute_tangent_binormal(uv_name);
01980       } else {
01981         group->r_collect_tangent_binormal(uv_name, collection);
01982       }
01983     }
01984   }
01985 }
01986 
01987 ////////////////////////////////////////////////////////////////////
01988 //     Function: EggGroupNode::do_compute_tangent_binormal
01989 //       Access: Private
01990 //  Description: This is part of the implementation of
01991 //               recompute_tangent_binormal().  It accepts a group of
01992 //               polygons and their common normals and UV's, and
01993 //               computes the tangent and binormal for all their
01994 //               shared vertices.
01995 ////////////////////////////////////////////////////////////////////
01996 void EggGroupNode::
01997 do_compute_tangent_binormal(const TBNVertexValue &value,
01998                             const TBNVertexGroup &group) {
01999   nassertv(!group.empty());
02000 
02001   // Accumulate together all of the s vectors and t vectors computed
02002   // for the different vertices that are together here.
02003   Normald sdir(0.0, 0.0, 0.0);
02004   Normald tdir(0.0, 0.0, 0.0);
02005 
02006   TBNVertexGroup::const_iterator gi;
02007   for (gi = group.begin(); gi != group.end(); ++gi) {
02008     const TBNVertexReference &ref = (*gi);
02009     sdir += ref._sdir;
02010     tdir += ref._tdir;
02011   }
02012 
02013   // If sdir and/or tdir are zero, choose an arbitrary vector instead.
02014   // (This is really the only reason we normalize sdir and tdir,
02015   // though it also helps stabilize the math below in case the vectors
02016   // are very small but not quite zero.)
02017   if (!sdir.normalize()) {
02018     sdir.set(1.0, 0.0, 0.0);
02019   }
02020   if (!tdir.normalize()) {
02021     tdir = sdir.cross(Normald(0.0, 0.0, -1.0));
02022   }
02023 
02024   Normald tangent = (sdir - value._normal * value._normal.dot(sdir));
02025   tangent.normalize();
02026 
02027   Normald binormal = cross(value._normal, tangent);
02028   if (dot(binormal, tdir) < 0.0f) {
02029     binormal = -binormal;
02030   }
02031   // Shouldn't need to normalize this, but we do just for good measure.
02032   binormal.normalize();
02033 
02034   // Now we have the common tangent and binormal; apply them to all
02035   // the vertices.
02036 
02037   for (gi = group.begin(); gi != group.end(); ++gi) {
02038     const TBNVertexReference &ref = (*gi);
02039     EggVertex *vertex = ref._polygon->get_vertex(ref._vertex);
02040     EggVertexPool *pool = vertex->get_pool();
02041 
02042     EggVertex new_vertex(*vertex);
02043     EggVertexUV *uv_obj = new_vertex.modify_uv_obj(value._uv_name);
02044     nassertv(uv_obj != (EggVertexUV *)NULL);
02045     uv_obj->set_tangent(tangent);
02046     uv_obj->set_binormal(binormal);
02047 
02048     EggVertex *unique = pool->create_unique_vertex(new_vertex);
02049     unique->copy_grefs_from(*vertex);
02050 
02051     ref._polygon->set_vertex(ref._vertex, unique);
02052   }
02053 }
 All Classes Functions Variables Enumerations