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         (eggtex->get_env_type() == EggTexture::ET_normal_gloss)) {
00779       string uv = eggtex->get_uv_name();
00780       vector_string::iterator it = find(names.begin(), names.end(), uv);
00781       if (it == names.end()) {
00782         names.push_back(uv);
00783       }
00784     }
00785   }
00786   return recompute_tangent_binormal(names);
00787 }
00788 
00789 ////////////////////////////////////////////////////////////////////
00790 //     Function: EggGroupNode::triangulate_polygons
00791 //       Access: Published
00792 //  Description: Replace all higher-order polygons at this point in
00793 //               the scene graph and below with triangles.  Returns
00794 //               the total number of new triangles produced, less
00795 //               degenerate polygons removed.
00796 //
00797 //               If flags contains T_polygon and T_convex, both
00798 //               concave and convex polygons will be subdivided into
00799 //               triangles; with only T_polygon, only concave polygons
00800 //               will be subdivided, and convex polygons will be
00801 //               largely unchanged.
00802 ////////////////////////////////////////////////////////////////////
00803 int EggGroupNode::
00804 triangulate_polygons(int flags) {
00805   int num_produced = 0;
00806 
00807   Children children_copy = _children;
00808 
00809   Children::iterator ci;
00810   for (ci = children_copy.begin();
00811        ci != children_copy.end();
00812        ++ci) {
00813     EggNode *child = (*ci);
00814 
00815     if (child->is_of_type(EggPolygon::get_class_type())) {
00816       if ((flags & T_polygon) != 0) {
00817         EggPolygon *poly = DCAST(EggPolygon, child);
00818         poly->triangulate_in_place((flags & T_convex) != 0);
00819       }
00820 
00821     } else if (child->is_of_type(EggCompositePrimitive::get_class_type())) {
00822       if ((flags & T_composite) != 0) {
00823         EggCompositePrimitive *comp = DCAST(EggCompositePrimitive, child);
00824         comp->triangulate_in_place();
00825       }
00826 
00827     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
00828       if ((flags & T_recurse) != 0) {
00829         num_produced += DCAST(EggGroupNode, child)->triangulate_polygons(flags);
00830       }
00831     }
00832   }
00833 
00834   num_produced += max(0, (int)(_children.size() - children_copy.size()));
00835   return num_produced;
00836 }
00837 
00838 ////////////////////////////////////////////////////////////////////
00839 //     Function: EggGroupNode::mesh_triangles
00840 //       Access: Published
00841 //  Description: Combine triangles together into triangle strips, at
00842 //               this group and below.
00843 ////////////////////////////////////////////////////////////////////
00844 void EggGroupNode::
00845 mesh_triangles(int flags) {
00846   EggMesher mesher;
00847   mesher.mesh(this, (flags & T_flat_shaded) != 0);
00848 
00849   if ((flags & T_recurse) != 0) {
00850     EggGroupNode::iterator ci;
00851     for (ci = begin(); ci != end(); ++ci) {
00852       if ((*ci)->is_of_type(EggGroupNode::get_class_type())) {
00853         EggGroupNode *group_child = DCAST(EggGroupNode, *ci);
00854         group_child->mesh_triangles(flags);
00855       }
00856     }
00857   }
00858 }
00859 
00860 ////////////////////////////////////////////////////////////////////
00861 //     Function: EggGroupNode::make_point_primitives
00862 //       Access: Published
00863 //  Description: Creates PointLight primitives to reference any
00864 //               otherwise unreferences vertices discovered in this
00865 //               group or below.
00866 ////////////////////////////////////////////////////////////////////
00867 void EggGroupNode::
00868 make_point_primitives() {
00869   // Create a temporary node to hold the EggPoint objects we might
00870   // create while we iterate.  (We don't add them during the iteration
00871   // to avoid invalidating the iterator.)
00872   PT(EggGroupNode) temp = new EggGroup("temp");
00873 
00874   EggGroupNode::iterator ci;
00875   for (ci = begin(); ci != end(); ++ci) {
00876     if ((*ci)->is_of_type(EggGroupNode::get_class_type())) {
00877       EggGroupNode *group_child = DCAST(EggGroupNode, *ci);
00878       group_child->make_point_primitives();
00879 
00880     } else if ((*ci)->is_of_type(EggVertexPool::get_class_type())) {
00881       EggVertexPool *vpool = DCAST(EggVertexPool, *ci);
00882       PT(EggPrimitive) prim = new EggPoint;
00883       vpool->add_unused_vertices_to_prim(prim);
00884       if (!prim->empty()) {
00885         temp->add_child(prim);
00886       }
00887     }
00888   }
00889 
00890   steal_children(*temp);
00891 }
00892 
00893 ////////////////////////////////////////////////////////////////////
00894 //     Function: EggGroupNode::rename_nodes
00895 //       Access: Published
00896 //  Description: Rename by stripping out the prefix
00897 ////////////////////////////////////////////////////////////////////
00898 int EggGroupNode::
00899 rename_nodes(vector_string strip_prefix, bool recurse) {
00900   int num_renamed = 0;
00901   for (unsigned int ni = 0; ni < strip_prefix.size(); ++ni) {
00902     string axe_name = strip_prefix[ni];
00903     if (this->get_name().substr(0, axe_name.size()) == axe_name) {
00904       string new_name = this->get_name().substr(axe_name.size());
00905       //cout << "renaming " << this->get_name() << "->" << new_name << endl;
00906       this->set_name(new_name);
00907       num_renamed += 1;
00908     }
00909   }
00910   if (recurse) {
00911     EggGroupNode::iterator ci;
00912     for (ci = begin(); ci != end(); ++ci) {
00913       if ((*ci)->is_of_type(EggGroupNode::get_class_type())) {
00914         EggGroupNode *group_child = DCAST(EggGroupNode, *ci);
00915         num_renamed += group_child->rename_nodes(strip_prefix, recurse);
00916       }
00917       else if ((*ci)->is_of_type(EggNode::get_class_type())) {
00918         EggNode *node_child = DCAST(EggNode, *ci);
00919         num_renamed += node_child->rename_node(strip_prefix);
00920       }
00921     }
00922   }
00923   return num_renamed;
00924 }
00925 
00926 ////////////////////////////////////////////////////////////////////
00927 //     Function: EggGroupNode::remove_unused_vertices
00928 //       Access: Published
00929 //  Description: Removes all vertices from VertexPools within this
00930 //               group or below that are not referenced by at least
00931 //               one primitive.  Also collapses together equivalent
00932 //               vertices, and renumbers all vertices after the
00933 //               operation so their indices are consecutive, beginning
00934 //               at zero.  Returns the total number of vertices
00935 //               removed.
00936 //
00937 //               Note that this operates on the VertexPools within
00938 //               this group level, without respect to primitives that
00939 //               reference these vertices (unlike other functions like
00940 //               strip_normals()).  It is therefore most useful to
00941 //               call this on the EggData root, rather than on a
00942 //               subgroup within the hierarchy, since a VertexPool may
00943 //               appear anywhere in the hierarchy.
00944 ////////////////////////////////////////////////////////////////////
00945 int EggGroupNode::
00946 remove_unused_vertices(bool recurse) {
00947   int num_removed = 0;
00948 
00949   Children::iterator ci, cnext;
00950   ci = _children.begin();
00951   while (ci != _children.end()) {
00952     cnext = ci;
00953     ++cnext;
00954     EggNode *child = *ci;
00955 
00956     if (child->is_of_type(EggVertexPool::get_class_type())) {
00957       EggVertexPool *vpool = DCAST(EggVertexPool, child);
00958       num_removed += vpool->remove_unused_vertices();
00959 
00960       if (vpool->empty()) {
00961         // If, after removing all the vertices, there's nothing left
00962         // in the vertex pool, then remove the whole vertex pool.
00963         _children.erase(ci);
00964       }
00965 
00966     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
00967       if (recurse) {
00968         num_removed += DCAST(EggGroupNode, child)->remove_unused_vertices(recurse);
00969       }
00970     }
00971 
00972     ci = cnext;
00973   }
00974 
00975   return num_removed;
00976 }
00977 
00978 ////////////////////////////////////////////////////////////////////
00979 //     Function: EggGroupNode::remove_invalid_primitives
00980 //       Access: Published
00981 //  Description: Removes primitives at this level and below which
00982 //               appear to be degenerate; e.g. polygons with fewer
00983 //               than 3 vertices, etc.  Returns the number of
00984 //               primitives removed.
00985 ////////////////////////////////////////////////////////////////////
00986 int EggGroupNode::
00987 remove_invalid_primitives(bool recurse) {
00988   int num_removed = 0;
00989 
00990   Children::iterator ci, cnext;
00991   ci = _children.begin();
00992   while (ci != _children.end()) {
00993     cnext = ci;
00994     ++cnext;
00995     EggNode *child = *ci;
00996 
00997     if (child->is_of_type(EggPrimitive::get_class_type())) {
00998       EggPrimitive *prim = DCAST(EggPrimitive, child);
00999       if (!prim->cleanup()) {
01000         _children.erase(ci);
01001         num_removed++;
01002       }
01003 
01004     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01005       if (recurse) {
01006         num_removed += DCAST(EggGroupNode, child)->remove_invalid_primitives(recurse);
01007       }
01008     }
01009 
01010     ci = cnext;
01011   }
01012 
01013   return num_removed;
01014 }
01015 
01016 ////////////////////////////////////////////////////////////////////
01017 //     Function: EggGroupNode::clear_connected_shading
01018 //       Access: Published
01019 //  Description: Resets the connected_shading information on all
01020 //               primitives at this node and below, so that it may be
01021 //               accurately rederived by the next call to
01022 //               get_connected_shading().
01023 //
01024 //               It may be a good idea to call
01025 //               remove_unused_vertices() as well, to establish the
01026 //               correct connectivity between common vertices.
01027 ////////////////////////////////////////////////////////////////////
01028 void EggGroupNode::
01029 clear_connected_shading() {
01030   Children::iterator ci;
01031   for (ci = _children.begin(); ci != _children.end(); ++ci) {
01032     EggNode *child = *ci;
01033 
01034     if (child->is_of_type(EggPrimitive::get_class_type())) {
01035       EggPrimitive *prim = DCAST(EggPrimitive, child);
01036       prim->clear_connected_shading();
01037     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01038       DCAST(EggGroupNode, child)->clear_connected_shading();
01039     }
01040   }
01041 }
01042 
01043 ////////////////////////////////////////////////////////////////////
01044 //     Function: EggGroupNode::get_connected_shading
01045 //       Access: Published
01046 //  Description: Queries the connected_shading information on all
01047 //               primitives at this node and below, to ensure that it
01048 //               has been completely filled in before we start mucking
01049 //               around with vertices.
01050 ////////////////////////////////////////////////////////////////////
01051 void EggGroupNode::
01052 get_connected_shading() {
01053   Children::iterator ci;
01054   for (ci = _children.begin(); ci != _children.end(); ++ci) {
01055     EggNode *child = *ci;
01056 
01057     if (child->is_of_type(EggPrimitive::get_class_type())) {
01058       EggPrimitive *prim = DCAST(EggPrimitive, child);
01059       prim->get_connected_shading();
01060     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01061       DCAST(EggGroupNode, child)->get_connected_shading();
01062     }
01063   }
01064 }
01065 
01066 ////////////////////////////////////////////////////////////////////
01067 //     Function: EggGroupNode::unify_attributes
01068 //       Access: Published
01069 //  Description: Applies per-vertex normal and color to all vertices,
01070 //               if they are in fact per-vertex (and different for
01071 //               each vertex), or moves them to the primitive if they
01072 //               are all the same.
01073 //
01074 //               After this call, either the primitive will have
01075 //               normals or its vertices will, but not both.  Ditto
01076 //               for colors.
01077 //
01078 //               If use_connected_shading is true, each polygon is
01079 //               considered in conjunction with all connected
01080 //               polygons; otherwise, each polygon is considered
01081 //               individually.
01082 //
01083 //               If allow_per_primitive is false, S_per_face or
01084 //               S_overall will treated like S_per_vertex: normals and
01085 //               colors will always be assigned to the vertices.  In
01086 //               this case, there will never be per-primitive colors
01087 //               or normals after this call returns.  On the other
01088 //               hand, if allow_per_primitive is true, then S_per_face
01089 //               means that normals and colors should be assigned to
01090 //               the primitives, and removed from the vertices, as
01091 //               described above.
01092 //
01093 //               This may create redundant vertices in the vertex
01094 //               pool, so it may be a good idea to follow this up with
01095 //               remove_unused_vertices().
01096 ////////////////////////////////////////////////////////////////////
01097 void EggGroupNode::
01098 unify_attributes(bool use_connected_shading, bool allow_per_primitive,
01099                  bool recurse) {
01100   Children::iterator ci;
01101   for (ci = _children.begin(); ci != _children.end(); ++ci) {
01102     EggNode *child = *ci;
01103 
01104     if (child->is_of_type(EggPrimitive::get_class_type())) {
01105       EggPrimitive *prim = DCAST(EggPrimitive, child);
01106 
01107       EggPrimitive::Shading shading = EggPrimitive::S_per_vertex;
01108 
01109       if (allow_per_primitive) {
01110         shading = prim->get_shading();
01111         if (use_connected_shading) {
01112           shading = prim->get_connected_shading();
01113         }
01114       }
01115 
01116       prim->unify_attributes(shading);
01117 
01118     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01119       if (recurse) {
01120         DCAST(EggGroupNode, child)->unify_attributes
01121           (use_connected_shading, allow_per_primitive, recurse);
01122       }
01123     }
01124   }
01125 }
01126 
01127 ////////////////////////////////////////////////////////////////////
01128 //     Function: EggGroupNode::apply_last_attribute
01129 //       Access: Published
01130 //  Description: Sets the last vertex of the triangle (or each
01131 //               component) to the primitive normal and/or color, if
01132 //               the primitive is flat-shaded.  This reflects the
01133 //               OpenGL convention of storing flat-shaded properties on
01134 //               the last vertex, although it is not usually a
01135 //               convention in Egg.
01136 //
01137 //               This may create redundant vertices in the vertex
01138 //               pool, so it may be a good idea to follow this up with
01139 //               remove_unused_vertices().
01140 ////////////////////////////////////////////////////////////////////
01141 void EggGroupNode::
01142 apply_last_attribute(bool recurse) {
01143   Children::iterator ci;
01144   for (ci = _children.begin(); ci != _children.end(); ++ci) {
01145     EggNode *child = *ci;
01146 
01147     if (child->is_of_type(EggPrimitive::get_class_type())) {
01148       EggPrimitive *prim = DCAST(EggPrimitive, child);
01149       prim->apply_last_attribute();
01150     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01151       if (recurse) {
01152         DCAST(EggGroupNode, child)->apply_last_attribute(recurse);
01153       }
01154     }
01155   }
01156 }
01157 
01158 ////////////////////////////////////////////////////////////////////
01159 //     Function: EggGroupNode::apply_first_attribute
01160 //       Access: Published
01161 //  Description: Sets the first vertex of the triangle (or each
01162 //               component) to the primitive normal and/or color, if
01163 //               the primitive is flat-shaded.  This reflects the
01164 //               DirectX convention of storing flat-shaded properties on
01165 //               the first vertex, although it is not usually a
01166 //               convention in Egg.
01167 //
01168 //               This may create redundant vertices in the vertex
01169 //               pool, so it may be a good idea to follow this up with
01170 //               remove_unused_vertices().
01171 ////////////////////////////////////////////////////////////////////
01172 void EggGroupNode::
01173 apply_first_attribute(bool recurse) {
01174   Children::iterator ci;
01175   for (ci = _children.begin(); ci != _children.end(); ++ci) {
01176     EggNode *child = *ci;
01177 
01178     if (child->is_of_type(EggPrimitive::get_class_type())) {
01179       EggPrimitive *prim = DCAST(EggPrimitive, child);
01180       prim->apply_first_attribute();
01181     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01182       if (recurse) {
01183         DCAST(EggGroupNode, child)->apply_first_attribute(recurse);
01184       }
01185     }
01186   }
01187 }
01188 
01189 ////////////////////////////////////////////////////////////////////
01190 //     Function: EggGroupNode::post_apply_flat_attribute
01191 //       Access: Published
01192 //  Description: Intended as a followup to apply_last_attribute(),
01193 //               this also sets an attribute on the first vertices of
01194 //               the primitive, if they don't already have an
01195 //               attribute set, just so they end up with *something*.
01196 ////////////////////////////////////////////////////////////////////
01197 void EggGroupNode::
01198 post_apply_flat_attribute(bool recurse) {
01199   Children::iterator ci;
01200   for (ci = _children.begin(); ci != _children.end(); ++ci) {
01201     EggNode *child = *ci;
01202 
01203     if (child->is_of_type(EggPrimitive::get_class_type())) {
01204       EggPrimitive *prim = DCAST(EggPrimitive, child);
01205       prim->post_apply_flat_attribute();
01206     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01207       if (recurse) {
01208         DCAST(EggGroupNode, child)->post_apply_flat_attribute(recurse);
01209       }
01210     }
01211   }
01212 }
01213 
01214 ////////////////////////////////////////////////////////////////////
01215 //     Function: EggGroupNode::has_primitives
01216 //       Access: Published, Virtual
01217 //  Description: Returns true if there are any primitives
01218 //               (e.g. polygons) defined within this group or below,
01219 //               false otherwise.
01220 ////////////////////////////////////////////////////////////////////
01221 bool EggGroupNode::
01222 has_primitives() const {
01223   Children::const_iterator ci;
01224   for (ci = _children.begin();
01225        ci != _children.end();
01226        ++ci) {
01227     if ((*ci)->has_primitives()) {
01228       return true;
01229     }
01230   }
01231 
01232   return false;
01233 }
01234 
01235 ////////////////////////////////////////////////////////////////////
01236 //     Function: EggGroupNode::joint_has_primitives
01237 //       Access: Published, Virtual
01238 //  Description: Returns true if there are any primitives
01239 //               (e.g. polygons) defined within this group or below,
01240 //               but the search does not include nested joints.
01241 ////////////////////////////////////////////////////////////////////
01242 bool EggGroupNode::
01243 joint_has_primitives() const {
01244   Children::const_iterator ci;
01245   for (ci = _children.begin();
01246        ci != _children.end();
01247        ++ci) {
01248     EggNode *child = (*ci);
01249 
01250     if (!child->is_joint()) {
01251       if (child->joint_has_primitives()) {
01252         return true;
01253       }
01254     }
01255   }
01256 
01257   return false;
01258 }
01259 
01260 ////////////////////////////////////////////////////////////////////
01261 //     Function: EggGroupNode::has_normals
01262 //       Access: Published, Virtual
01263 //  Description: Returns true if any of the primitives (e.g. polygons)
01264 //               defined within this group or below have either face
01265 //               or vertex normals defined, false otherwise.
01266 ////////////////////////////////////////////////////////////////////
01267 bool EggGroupNode::
01268 has_normals() const {
01269   Children::const_iterator ci;
01270   for (ci = _children.begin();
01271        ci != _children.end();
01272        ++ci) {
01273     if ((*ci)->has_normals()) {
01274       return true;
01275     }
01276   }
01277 
01278   return false;
01279 }
01280 
01281 ////////////////////////////////////////////////////////////////////
01282 //     Function: EggGroupNode::rebuild_vertex_pools
01283 //       Access: Published
01284 //  Description: Copies vertices used by the primitives at this group
01285 //               node (and below, if recurse is true) into one or more
01286 //               new vertex pools, and updates the primitives to
01287 //               reference these pools.  It is up to the caller to
01288 //               parent the newly-created vertex pools somewhere
01289 //               appropriate in the egg hierarchy.
01290 //
01291 //               No more than max_vertices will be placed into any one
01292 //               vertex pool.  This is the sole criteria for splitting
01293 //               vertex pools.
01294 ////////////////////////////////////////////////////////////////////
01295 void EggGroupNode::
01296 rebuild_vertex_pools(EggVertexPools &vertex_pools, unsigned int max_vertices,
01297                      bool recurse) {
01298   Children::iterator ci;
01299   for (ci = _children.begin(); ci != _children.end(); ++ci) {
01300     EggNode *child = *ci;
01301 
01302     if (child->is_of_type(EggPrimitive::get_class_type())) {
01303       typedef pvector< PT(EggVertex) > Vertices;
01304       Vertices vertices;
01305       EggPrimitive *prim = DCAST(EggPrimitive, child);
01306 
01307       // Copy all of the vertices out.
01308       EggPrimitive::const_iterator pi;
01309       for (pi = prim->begin(); pi != prim->end(); ++pi) {
01310         vertices.push_back(*pi);
01311       }
01312 
01313       typedef epvector<EggAttributes> Attributes;
01314       Attributes attributes;
01315 
01316       if (prim->is_of_type(EggCompositePrimitive::get_class_type())) {
01317         // A compositive primitive has the additional complication of
01318         // dealing with its attributes.
01319         EggCompositePrimitive *cprim = DCAST(EggCompositePrimitive, prim);
01320         int i;
01321         int num_components = cprim->get_num_components();
01322         for (i = 0; i < num_components; i++) {
01323           attributes.push_back(*cprim->get_component(i));
01324         }
01325       }
01326 
01327       prim->clear();
01328 
01329       // Now look for a new home for the vertices.  First, see if any
01330       // of the vertex pools we've already created already have a copy
01331       // of each one of the vertices.
01332       bool found_pool = false;
01333       EggVertexPool *best_pool = NULL;
01334       int best_new_vertices = 0;
01335 
01336       Vertices new_vertices;
01337       EggVertexPools::iterator vpi;
01338       for (vpi = vertex_pools.begin(); 
01339            vpi != vertex_pools.end() && !found_pool;
01340            ++vpi) {
01341         EggVertexPool *vertex_pool = (*vpi);
01342         int num_new_vertices = 0;
01343 
01344         new_vertices.clear();
01345         new_vertices.reserve(vertices.size());
01346 
01347         Vertices::const_iterator vi;
01348         for (vi = vertices.begin(); 
01349              vi != vertices.end() && !found_pool; 
01350              ++vi) {
01351           EggVertex *vertex = (*vi);
01352           EggVertex *new_vertex = vertex_pool->find_matching_vertex(*vertex);
01353           new_vertices.push_back(new_vertex);
01354           if (new_vertex == (EggVertex *)NULL) {
01355             ++num_new_vertices;
01356           }
01357         }
01358 
01359         if (num_new_vertices == 0) {
01360           // Great, we found a vertex pool that already shares all
01361           // these vertices.  No need to look any further.
01362           found_pool = true;
01363 
01364         } else if (vertex_pool->size() + num_new_vertices <= max_vertices) {
01365           // We would have to add some vertices to this pool, so this
01366           // vertex pool qualifies only if the number of vertices we
01367           // have to add would still keep it within our limit.
01368           if (best_pool == (EggVertexPool *)NULL ||
01369               num_new_vertices < best_new_vertices) {
01370             // This is currently our most favorable vertex pool.
01371             best_pool = vertex_pool;
01372             best_new_vertices = num_new_vertices;
01373           }
01374         }
01375       }
01376 
01377       if (!found_pool) {
01378         if (best_pool == (EggVertexPool *)NULL) {
01379           // There was no vertex pool that qualified.  We will have to
01380           // create a new vertex pool.
01381           best_pool = new EggVertexPool("");
01382           vertex_pools.push_back(best_pool);
01383         }
01384 
01385         new_vertices.clear();
01386         new_vertices.reserve(vertices.size());
01387 
01388         Vertices::const_iterator vi;
01389         for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
01390           EggVertex *vertex = (*vi);
01391           EggVertex *new_vertex = best_pool->create_unique_vertex(*vertex);
01392           new_vertex->copy_grefs_from(*vertex);
01393           new_vertices.push_back(new_vertex);
01394         }
01395       }
01396 
01397       Vertices::const_iterator vi;
01398       nassertv(new_vertices.size() == vertices.size());
01399       for (vi = new_vertices.begin(); vi != new_vertices.end(); ++vi) {
01400         EggVertex *new_vertex = (*vi);
01401         nassertv(new_vertex != (EggVertex *)NULL);
01402         prim->add_vertex(new_vertex);
01403       }
01404 
01405       if (prim->is_of_type(EggCompositePrimitive::get_class_type())) {
01406         // Now restore the composite attributes.
01407         EggCompositePrimitive *cprim = DCAST(EggCompositePrimitive, prim);
01408         int i;
01409         int num_components = cprim->get_num_components();
01410         nassertv(num_components == (int)attributes.size());
01411         for (i = 0; i < num_components; i++) {
01412           cprim->set_component(i, &attributes[i]);
01413         }
01414       }
01415         
01416     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01417       if (recurse) {
01418         DCAST(EggGroupNode, child)->rebuild_vertex_pools(vertex_pools, max_vertices, recurse);
01419       }
01420     }
01421   }
01422 }
01423 
01424 ////////////////////////////////////////////////////////////////////
01425 //     Function: EggGroupNode::update_under
01426 //       Access: Protected, Virtual
01427 //  Description: This function is called from within EggGroupNode
01428 //               whenever the parentage of the node has changed.  It
01429 //               should update the depth and under_instance flags
01430 //               accordingly.
01431 //
01432 //               Offset is the difference between the old depth value
01433 //               and the new value.  It should be consistent with the
01434 //               supplied depth value.  If it is not, we have some
01435 //               error.
01436 ////////////////////////////////////////////////////////////////////
01437 void EggGroupNode::
01438 update_under(int depth_offset) {
01439   EggNode::update_under(depth_offset);
01440 
01441   Children::iterator ci;
01442   for (ci = _children.begin();
01443        ci != _children.end();
01444        ++ci) {
01445     nassertv((*ci)->get_parent() == this);
01446     (*ci)->update_under(depth_offset);
01447   }
01448 }
01449 
01450 ////////////////////////////////////////////////////////////////////
01451 //     Function: EggGroupNode::r_transform
01452 //       Access: Protected, Virtual
01453 //  Description: This is called from within the egg code by
01454 //               transform().  It applies a transformation matrix
01455 //               to the current node in some sensible way, then
01456 //               continues down the tree.
01457 //
01458 //               The first matrix is the transformation to apply; the
01459 //               second is its inverse.  The third parameter is the
01460 //               coordinate system we are changing to, or CS_default
01461 //               if we are not changing coordinate systems.
01462 ////////////////////////////////////////////////////////////////////
01463 void EggGroupNode::
01464 r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
01465             CoordinateSystem to_cs) {
01466   Children::iterator ci;
01467   for (ci = _children.begin();
01468        ci != _children.end();
01469        ++ci) {
01470     (*ci)->r_transform(mat, inv, to_cs);
01471   }
01472 }
01473 
01474 ////////////////////////////////////////////////////////////////////
01475 //     Function: EggGroupNode::r_transform_vertices
01476 //       Access: Protected, Virtual
01477 //  Description: This is called from within the egg code by
01478 //               transform_vertices_only()().  It applies a
01479 //               transformation matrix to the current node in some
01480 //               sensible way (if the current node is a vertex pool
01481 //               with vertices), then continues down the tree.
01482 ////////////////////////////////////////////////////////////////////
01483 void EggGroupNode::
01484 r_transform_vertices(const LMatrix4d &mat) {
01485   Children::iterator ci;
01486   for (ci = _children.begin();
01487        ci != _children.end();
01488        ++ci) {
01489     (*ci)->r_transform_vertices(mat);
01490   }
01491 }
01492 
01493 ////////////////////////////////////////////////////////////////////
01494 //     Function: EggGroupNode::r_mark_coordsys
01495 //       Access: Protected, Virtual
01496 //  Description: This is only called immediately after loading an egg
01497 //               file from disk, to propagate the value found in the
01498 //               CoordinateSystem entry (or the default Y-up
01499 //               coordinate system) to all nodes that care about what
01500 //               the coordinate system is.
01501 ////////////////////////////////////////////////////////////////////
01502 void EggGroupNode::
01503 r_mark_coordsys(CoordinateSystem cs) {
01504   Children::iterator ci;
01505   for (ci = _children.begin();
01506        ci != _children.end();
01507        ++ci) {
01508     (*ci)->r_mark_coordsys(cs);
01509   }
01510 }
01511 
01512 ////////////////////////////////////////////////////////////////////
01513 //     Function: EggGroupNode::r_flatten_transforms
01514 //       Access: Protected, Virtual
01515 //  Description: The recursive implementation of flatten_transforms().
01516 ////////////////////////////////////////////////////////////////////
01517 void EggGroupNode::
01518 r_flatten_transforms() {
01519   Children::iterator ci;
01520   for (ci = _children.begin();
01521        ci != _children.end();
01522        ++ci) {
01523     (*ci)->r_flatten_transforms();
01524   }
01525 }
01526 
01527 ////////////////////////////////////////////////////////////////////
01528 //     Function: EggGroupNode::r_apply_texmats
01529 //       Access: Protected, Virtual
01530 //  Description: The recursive implementation of apply_texmats().
01531 ////////////////////////////////////////////////////////////////////
01532 void EggGroupNode::
01533 r_apply_texmats(EggTextureCollection &textures) {
01534   Children::iterator ci;
01535   for (ci = _children.begin();
01536        ci != _children.end();
01537        ++ci) {
01538     (*ci)->r_apply_texmats(textures);
01539   }
01540 }
01541 
01542 ////////////////////////////////////////////////////////////////////
01543 //     Function: EggGroupNode::find_coordsys_entry()
01544 //       Access: Protected
01545 //  Description: Walks the tree, looking for an EggCoordinateSystem
01546 //               entry.  If one is found, extracts it and returns its
01547 //               value.  If multiple entries are found, extracts all
01548 //               of them and returns CS_invalid if they disagree.
01549 ////////////////////////////////////////////////////////////////////
01550 CoordinateSystem EggGroupNode::
01551 find_coordsys_entry() {
01552   CoordinateSystem coordsys = CS_default;
01553 
01554   // We can do this ci/cnext iteration through the list as we modify
01555   // it, only because we know this works with an STL list type
01556   // container.  If this were a vector or a set, this wouldn't
01557   // necessarily work.
01558 
01559   Children::iterator ci, cnext;
01560   ci = _children.begin();
01561   while (ci != _children.end()) {
01562     cnext = ci;
01563     ++cnext;
01564     EggNode *child = *ci;
01565 
01566     if (child->is_of_type(EggCoordinateSystem::get_class_type())) {
01567       CoordinateSystem new_cs =
01568         DCAST(EggCoordinateSystem, child)->get_value();
01569 
01570       // Now remove the CoordinateSystem entry from our child list.
01571       prepare_remove_child(child);
01572       _children.erase(ci);
01573 
01574       if (new_cs != CS_default) {
01575         if (coordsys != CS_default && coordsys != new_cs) {
01576           coordsys = CS_invalid;
01577         } else {
01578           coordsys = new_cs;
01579         }
01580       }
01581 
01582     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01583       CoordinateSystem new_cs =
01584         DCAST(EggGroupNode, child)->find_coordsys_entry();
01585       if (new_cs != CS_default) {
01586         if (coordsys != CS_default && coordsys != new_cs) {
01587           coordsys = CS_invalid;
01588         } else {
01589           coordsys = new_cs;
01590         }
01591       }
01592     }
01593 
01594     ci = cnext;
01595   }
01596 
01597   return coordsys;
01598 }
01599 
01600 ////////////////////////////////////////////////////////////////////
01601 //     Function: EggGroupNode::find_textures()
01602 //       Access: Protected
01603 //  Description: Walks the tree, looking for EggTextures.  Each
01604 //               EggTexture that is found is removed from the
01605 //               hierarchy and added to the EggTextureCollection.
01606 //               Returns the number of EggTextures found.
01607 ////////////////////////////////////////////////////////////////////
01608 int EggGroupNode::
01609 find_textures(EggTextureCollection *collection) {
01610   int num_found = 0;
01611 
01612   // We can do this ci/cnext iteration through the list as we modify
01613   // it, only because we know this works with an STL list type
01614   // container.  If this were a vector or a set, this wouldn't
01615   // necessarily work.
01616 
01617   Children::iterator ci, cnext;
01618   ci = _children.begin();
01619   while (ci != _children.end()) {
01620     cnext = ci;
01621     ++cnext;
01622     EggNode *child = *ci;
01623 
01624     if (child->is_of_type(EggTexture::get_class_type())) {
01625       PT_EggTexture tex = DCAST(EggTexture, child);
01626 
01627       // Now remove the EggTexture entry from our child list.
01628       prepare_remove_child(tex);
01629       _children.erase(ci);
01630 
01631       // And add it to the collection.
01632       collection->add_texture(tex);
01633       num_found++;
01634 
01635     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01636       num_found +=
01637         DCAST(EggGroupNode, child)->find_textures(collection);
01638     }
01639 
01640     ci = cnext;
01641   }
01642 
01643   return num_found;
01644 }
01645 
01646 ////////////////////////////////////////////////////////////////////
01647 //     Function: EggGroupNode::find_materials()
01648 //       Access: Protected
01649 //  Description: Walks the tree, looking for EggMaterials.  Each
01650 //               EggMaterial that is found is removed from the
01651 //               hierarchy and added to the EggMaterialCollection.
01652 //               Returns the number of EggMaterials found.
01653 ////////////////////////////////////////////////////////////////////
01654 int EggGroupNode::
01655 find_materials(EggMaterialCollection *collection) {
01656   int num_found = 0;
01657 
01658   // We can do this ci/cnext iteration through the list as we modify
01659   // it, only because we know this works with an STL list type
01660   // container.  If this were a vector or a set, this wouldn't
01661   // necessarily work.
01662 
01663   Children::iterator ci, cnext;
01664   ci = _children.begin();
01665   while (ci != _children.end()) {
01666     cnext = ci;
01667     ++cnext;
01668     EggNode *child = *ci;
01669 
01670     if (child->is_of_type(EggMaterial::get_class_type())) {
01671       PT_EggMaterial tex = DCAST(EggMaterial, child);
01672 
01673       // Now remove the EggMaterial entry from our child list.
01674       prepare_remove_child(tex);
01675       _children.erase(ci);
01676 
01677       // And add it to the collection.
01678       collection->add_material(tex);
01679       num_found++;
01680 
01681     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01682       num_found +=
01683         DCAST(EggGroupNode, child)->find_materials(collection);
01684     }
01685 
01686     ci = cnext;
01687   }
01688 
01689   return num_found;
01690 }
01691 
01692 ////////////////////////////////////////////////////////////////////
01693 //     Function: EggGroupNode::r_load_externals
01694 //       Access: Protected
01695 //  Description: Walks the tree and locates unloaded external
01696 //               reference nodes, which it attempts to locate and load
01697 //               in.  The reference node is replaced with the entire
01698 //               subtree loaded.  This is intended to be called from
01699 //               EggData::load_externals().
01700 ////////////////////////////////////////////////////////////////////
01701 bool EggGroupNode::
01702 r_load_externals(const DSearchPath &searchpath, CoordinateSystem coordsys,
01703                  BamCacheRecord *record) {
01704   bool success = true;
01705 
01706   Children::iterator ci;
01707   for (ci = _children.begin();
01708        ci != _children.end();
01709        ++ci) {
01710     EggNode *child = *ci;
01711     if (child->is_of_type(EggExternalReference::get_class_type())) {
01712       PT(EggExternalReference) ref = DCAST(EggExternalReference, child);
01713 
01714       // Replace the reference with an empty group node.  When we load
01715       // the external file successfully, we'll put its contents here.
01716       Filename filename = ref->get_filename();
01717       EggGroupNode *new_node =
01718         new EggGroupNode(filename.get_basename_wo_extension());
01719       replace(ci, new_node);
01720 
01721       if (!EggData::resolve_egg_filename(filename, searchpath)) {
01722         egg_cat.error()
01723           << "Could not locate " << filename << " in "
01724           << searchpath << "\n";
01725       } else {
01726         // Now define a new EggData structure to hold the external
01727         // reference, and load it.
01728         EggData ext_data;
01729         ext_data.set_coordinate_system(coordsys);
01730         ext_data.set_auto_resolve_externals(true);
01731         if (ext_data.read(filename)) {
01732           // The external file was read correctly.  Add its contents
01733           // into the tree at this point.
01734           if (record != (BamCacheRecord *)NULL) {
01735             record->add_dependent_file(filename);
01736           }
01737 
01738           success =
01739             ext_data.load_externals(searchpath, record)
01740             && success;
01741           new_node->steal_children(ext_data);
01742         }
01743       }
01744 
01745     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01746       EggGroupNode *group_child = DCAST(EggGroupNode, child);
01747       success =
01748         group_child->r_load_externals(searchpath, coordsys, record)
01749         && success;
01750     }
01751   }
01752   return success;
01753 }
01754 
01755 
01756 ////////////////////////////////////////////////////////////////////
01757 //     Function: EggGroupNode::prepare_add_child
01758 //       Access: Private
01759 //  Description: Marks the node as a child of the group.  This is an
01760 //               internal function called by the STL-like functions
01761 //               push_back() and insert(), in preparation for actually
01762 //               adding the child.
01763 //
01764 //               It is an error to add a node that is already a child
01765 //               of this group or some other group.
01766 ////////////////////////////////////////////////////////////////////
01767 void EggGroupNode::
01768 prepare_add_child(EggNode *node) {
01769   nassertv(node != (EggNode *)NULL);
01770   test_ref_count_integrity();
01771   node->test_ref_count_integrity();
01772   // Make sure the node is not already a child of some other group.
01773   nassertv(node->get_parent() == NULL);
01774   nassertv(node->get_depth() == 0);
01775   node->_parent = this;
01776 
01777   node->update_under(get_depth() + 1);
01778 }
01779 
01780 
01781 ////////////////////////////////////////////////////////////////////
01782 //     Function: EggGroupNode::prepare_remove_child
01783 //       Access: Private
01784 //  Description: Marks the node as removed from the group.  This is an
01785 //               internal function called by the STL-like functions
01786 //               pop_back() and erase(), in preparation for actually
01787 //               doing the removal.
01788 //
01789 //               It is an error to attempt to remove a node that is
01790 //               not already a child of this group.
01791 ////////////////////////////////////////////////////////////////////
01792 void EggGroupNode::
01793 prepare_remove_child(EggNode *node) {
01794   nassertv(node != (EggNode *)NULL);
01795   // Make sure the node is in fact a child of this group.
01796   nassertv(node->get_parent() == this);
01797   nassertv(node->get_depth() == get_depth() + 1);
01798   node->_parent = NULL;
01799 
01800   node->update_under(-(get_depth() + 1));
01801 }
01802 
01803 
01804 
01805 ////////////////////////////////////////////////////////////////////
01806 //     Function: EggGroupNode::r_collect_vertex_normals
01807 //       Access: Private
01808 //  Description: This is part of the implementation of
01809 //               recompute_vertex_normals().  It walks the scene graph
01810 //               at this group node and below, identifying all the
01811 //               polygons and the vertices they have in common.
01812 ////////////////////////////////////////////////////////////////////
01813 void EggGroupNode::
01814 r_collect_vertex_normals(EggGroupNode::NVertexCollection &collection,
01815                          double threshold, CoordinateSystem cs) {
01816   // We can do this ci/cnext iteration through the list as we modify
01817   // it, only because we know this works with an STL list type
01818   // container.  If this were a vector or a set, this wouldn't
01819   // necessarily work.
01820 
01821   Children::iterator ci, cnext;
01822   ci = _children.begin();
01823   while (ci != _children.end()) {
01824     cnext = ci;
01825     ++cnext;
01826     EggNode *child = *ci;
01827 
01828     if (child->is_of_type(EggPolygon::get_class_type())) {
01829       EggPolygon *polygon = DCAST(EggPolygon, child);
01830       polygon->clear_normal();
01831 
01832       NVertexReference ref;
01833       ref._polygon = polygon;
01834       if (!polygon->calculate_normal(ref._normal, cs)) {
01835         // The polygon is degenerate.  Remove it.
01836 
01837         prepare_remove_child(child);
01838         _children.erase(ci);
01839 
01840       } else {
01841         // Now add each vertex from the polygon separately to our
01842         // collection.
01843         size_t num_vertices = polygon->size();
01844         for (size_t i = 0; i < num_vertices; i++) {
01845           EggVertex *vertex = polygon->get_vertex(i);
01846           ref._vertex = i;
01847           collection[vertex->get_pos3()].push_back(ref);
01848         }
01849       }
01850 
01851     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
01852       EggGroupNode *group = DCAST(EggGroupNode, child);
01853 
01854       // We can't share vertices across an Instance node.  Don't
01855       // even bother trying.  Instead, just restart.
01856       if (group->is_under_instance()) {
01857         group->recompute_vertex_normals(threshold, cs);
01858       } else {
01859         group->r_collect_vertex_normals(collection, threshold, cs);
01860       }
01861     }
01862 
01863     ci = cnext;
01864   }
01865 }
01866 
01867 ////////////////////////////////////////////////////////////////////
01868 //     Function: EggGroupNode::do_compute_vertex_normals
01869 //       Access: Private
01870 //  Description: This is part of the implementation of
01871 //               recompute_vertex_normals().  It accepts a group of
01872 //               polygons and their common normals, and computes the
01873 //               same normal for all their shared vertices.
01874 ////////////////////////////////////////////////////////////////////
01875 void EggGroupNode::
01876 do_compute_vertex_normals(const NVertexGroup &group) {
01877   nassertv(!group.empty());
01878 
01879   // Determine the common normal.  This is simply the average of all
01880   // the polygon normals that share this vertex.
01881   LNormald normal(0.0, 0.0, 0.0);
01882   NVertexGroup::const_iterator gi;
01883   for (gi = group.begin(); gi != group.end(); ++gi) {
01884     const NVertexReference &ref = (*gi);
01885     normal += ref._normal;
01886   }
01887 
01888   normal /= (double)group.size();
01889   normal.normalize();
01890 
01891   // Now we have the common normal; apply it to all the vertices.
01892 
01893   for (gi = group.begin(); gi != group.end(); ++gi) {
01894     const NVertexReference &ref = (*gi);
01895     EggVertex *vertex = ref._polygon->get_vertex(ref._vertex);
01896     EggVertexPool *pool = vertex->get_pool();
01897 
01898     EggVertex new_vertex(*vertex);
01899     new_vertex.set_normal(normal);
01900     EggVertex *unique = pool->create_unique_vertex(new_vertex);
01901     unique->copy_grefs_from(*vertex);
01902 
01903     ref._polygon->set_vertex(ref._vertex, unique);
01904   }
01905 }
01906 
01907 ////////////////////////////////////////////////////////////////////
01908 //     Function: EggGroupNode::r_collect_tangent_binormal
01909 //       Access: Private
01910 //  Description: This is part of the implementation of
01911 //               recompute_tangent_binormal().  It walks the scene
01912 //               graph at this group node and below, identifying all
01913 //               the polygons and the vertices they have in common.
01914 ////////////////////////////////////////////////////////////////////
01915 void EggGroupNode::
01916 r_collect_tangent_binormal(const GlobPattern &uv_name,
01917                            EggGroupNode::TBNVertexCollection &collection) {
01918   Children::iterator ci;
01919   for (ci = _children.begin(); ci != _children.end(); ++ci) {
01920     EggNode *child = *ci;
01921 
01922     if (child->is_of_type(EggPolygon::get_class_type())) {
01923       EggPolygon *polygon = DCAST(EggPolygon, child);
01924 
01925       TBNVertexReference ref;
01926       ref._polygon = polygon;
01927 
01928       // Now add each vertex from the polygon separately to our
01929       // collection.
01930       size_t num_vertices = polygon->size();
01931       for (size_t i = 0; i < num_vertices; i++) {
01932         // We look at the triangle formed by each three consecutive
01933         // vertices to determine the s direction and t direction at
01934         // each vertex.  v1 is the key vertex, the one at position i;
01935         // v2 is vertex i + 1, and v3 is vertex i - 1.
01936         EggVertex *v1 = polygon->get_vertex(i);
01937         EggVertex *v2 = polygon->get_vertex((i + 1) % num_vertices);
01938         EggVertex *v3 = polygon->get_vertex((i + num_vertices - 1) % num_vertices);
01939         if (v1->has_normal() || polygon->has_normal()) {
01940           // Go through all of the UV names on the vertex, looking for
01941           // one that matches the glob pattern.
01942           EggVertex::const_uv_iterator uvi;
01943           for (uvi = v1->uv_begin(); uvi != v1->uv_end(); ++uvi) {
01944             EggVertexUV *uv_obj = (*uvi);
01945             string name = uv_obj->get_name();
01946             if (uv_name.matches(name) &&
01947                 v2->has_uv(name) && v3->has_uv(name)) {
01948               TBNVertexValue value;
01949               value._uv_name = name;
01950               value._pos = v1->get_pos3();
01951               if (v1->has_normal()) {
01952                 value._normal = v1->get_normal();
01953               } else {
01954                 value._normal = polygon->get_normal();
01955               }
01956               value._uv = v1->get_uv(name);
01957               
01958               // Compute the s direction and t direction for this vertex.
01959               LPoint3d p1 = v1->get_pos3();
01960               LPoint3d p2 = v2->get_pos3();
01961               LPoint3d p3 = v3->get_pos3();
01962               
01963               LTexCoordd w1 = v1->get_uv(name);
01964               LTexCoordd w2 = v2->get_uv(name);
01965               LTexCoordd w3 = v3->get_uv(name);
01966 
01967               // Check the facing of the texture; we will have to
01968               // split vertices whose UV's are mirrored along a seam.
01969               // The facing is determined by the winding order of the
01970               // texcoords on the polygon.  A front-facing polygon
01971               // should not contribute to the tangent and binormal of
01972               // a back-facing polygon, and vice-versa.
01973               value._facing = is_right(w1 - w2, w3 - w1);
01974 
01975               double x1 = p2[0] - p1[0];
01976               double x2 = p3[0] - p1[0];
01977               double y1 = p2[1] - p1[1];
01978               double y2 = p3[1] - p1[1];
01979               double z1 = p2[2] - p1[2];
01980               double z2 = p3[2] - p1[2];
01981               
01982               double s1 = w2[0] - w1[0];
01983               double s2 = w3[0] - w1[0];
01984               double t1 = w2[1] - w1[1];
01985               double t2 = w3[1] - w1[1];
01986               
01987               double denom = (s1 * t2 - s2 * t1);
01988               if (denom == 0.0) {
01989                 ref._sdir.set(0.0, 0.0, 0.0);
01990                 ref._tdir.set(0.0, 0.0, 0.0);
01991               } else {
01992                 double r = 1.0 / denom;
01993                 ref._sdir.set((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
01994                               (t2 * z1 - t1 * z2) * r);
01995                 ref._tdir.set((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
01996                               (s1 * z2 - s2 * z1) * r);
01997               }
01998 
01999               // Store the vertex referenced to the polygon.
02000               ref._vertex = i;
02001               collection[value].push_back(ref);
02002             }
02003           }
02004         }
02005       }
02006 
02007     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
02008       EggGroupNode *group = DCAST(EggGroupNode, child);
02009 
02010       // We can't share vertices across an Instance node.  Don't
02011       // even bother trying.  Instead, just restart.
02012       if (group->is_under_instance()) {
02013         group->recompute_tangent_binormal(uv_name);
02014       } else {
02015         group->r_collect_tangent_binormal(uv_name, collection);
02016       }
02017     }
02018   }
02019 }
02020 
02021 ////////////////////////////////////////////////////////////////////
02022 //     Function: EggGroupNode::do_compute_tangent_binormal
02023 //       Access: Private
02024 //  Description: This is part of the implementation of
02025 //               recompute_tangent_binormal().  It accepts a group of
02026 //               polygons and their common normals and UV's, and
02027 //               computes the tangent and binormal for all their
02028 //               shared vertices.
02029 ////////////////////////////////////////////////////////////////////
02030 void EggGroupNode::
02031 do_compute_tangent_binormal(const TBNVertexValue &value,
02032                             const TBNVertexGroup &group) {
02033   nassertv(!group.empty());
02034 
02035   // Accumulate together all of the s vectors and t vectors computed
02036   // for the different vertices that are together here.
02037   LNormald sdir(0.0, 0.0, 0.0);
02038   LNormald tdir(0.0, 0.0, 0.0);
02039 
02040   TBNVertexGroup::const_iterator gi;
02041   for (gi = group.begin(); gi != group.end(); ++gi) {
02042     const TBNVertexReference &ref = (*gi);
02043     sdir += ref._sdir;
02044     tdir += ref._tdir;
02045   }
02046 
02047   // If sdir and/or tdir are zero, choose an arbitrary vector instead.
02048   // (This is really the only reason we normalize sdir and tdir,
02049   // though it also helps stabilize the math below in case the vectors
02050   // are very small but not quite zero.)
02051   if (!sdir.normalize()) {
02052     sdir.set(1.0, 0.0, 0.0);
02053   }
02054   if (!tdir.normalize()) {
02055     tdir = sdir.cross(LNormald(0.0, 0.0, -1.0));
02056   }
02057 
02058   LNormald tangent = (sdir - value._normal * value._normal.dot(sdir));
02059   tangent.normalize();
02060 
02061   LNormald binormal = cross(value._normal, tangent);
02062   if (dot(binormal, tdir) < 0.0f) {
02063     binormal = -binormal;
02064   }
02065   // Shouldn't need to normalize this, but we do just for good measure.
02066   binormal.normalize();
02067 
02068   // Now we have the common tangent and binormal; apply them to all
02069   // the vertices.
02070 
02071   for (gi = group.begin(); gi != group.end(); ++gi) {
02072     const TBNVertexReference &ref = (*gi);
02073     EggVertex *vertex = ref._polygon->get_vertex(ref._vertex);
02074     EggVertexPool *pool = vertex->get_pool();
02075 
02076     EggVertex new_vertex(*vertex);
02077     EggVertexUV *uv_obj = new_vertex.modify_uv_obj(value._uv_name);
02078     nassertv(uv_obj != (EggVertexUV *)NULL);
02079     uv_obj->set_tangent(tangent);
02080     uv_obj->set_binormal(binormal);
02081 
02082     EggVertex *unique = pool->create_unique_vertex(new_vertex);
02083     unique->copy_grefs_from(*vertex);
02084 
02085     ref._polygon->set_vertex(ref._vertex, unique);
02086   }
02087 }
 All Classes Functions Variables Enumerations