Panda3D
eggGroupNode.cxx
1 // Filename: eggGroupNode.cxx
2 // Created by: drose (16Jan99)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "eggGroupNode.h"
16 #include "eggGroup.h"
17 #include "eggCoordinateSystem.h"
18 #include "eggData.h"
19 #include "eggFilenameNode.h"
20 #include "eggExternalReference.h"
21 #include "eggPrimitive.h"
22 #include "eggPoint.h"
23 #include "eggPolygon.h"
24 #include "eggCompositePrimitive.h"
25 #include "eggMesher.h"
26 #include "eggVertexPool.h"
27 #include "eggVertex.h"
28 #include "eggTextureCollection.h"
29 #include "eggMaterialCollection.h"
30 #include "epvector.h"
31 #include "pt_EggTexture.h"
32 #include "pt_EggMaterial.h"
33 #include "config_egg.h"
34 
35 #include "dSearchPath.h"
36 #include "virtualFileSystem.h"
37 #include "deg_2_rad.h"
38 #include "dcast.h"
39 #include "bamCacheRecord.h"
40 
41 #include <algorithm>
42 
43 TypeHandle EggGroupNode::_type_handle;
44 
45 
46 ////////////////////////////////////////////////////////////////////
47 // Function: EggGroupNode::Copy constructor
48 // Access: Published
49 // Description:
50 ////////////////////////////////////////////////////////////////////
51 EggGroupNode::
52 EggGroupNode(const EggGroupNode &copy) : EggNode(copy) {
53  if (!copy.empty()) {
54  egg_cat.warning()
55  << "The EggGroupNode copy constructor does not copy children!\n";
56  }
57 }
58 
59 ////////////////////////////////////////////////////////////////////
60 // Function: EggGroupNode::Copy assignment operator
61 // Access: Published
62 // Description:
63 ////////////////////////////////////////////////////////////////////
64 EggGroupNode &EggGroupNode::
65 operator =(const EggGroupNode &copy) {
66  if (!copy.empty()) {
67  egg_cat.warning()
68  << "The EggGroupNode copy assignment does not copy children!\n";
69  }
70  EggNode::operator =(copy);
71  return *this;
72 }
73 
74 ////////////////////////////////////////////////////////////////////
75 // Function: EggGroupNode::Destructor
76 // Access: Published, Virtual
77 // Description:
78 ////////////////////////////////////////////////////////////////////
79 EggGroupNode::
80 ~EggGroupNode() {
81 }
82 
83 
84 ////////////////////////////////////////////////////////////////////
85 // Function: EggGroupNode::write
86 // Access: Published, Virtual
87 // Description: Writes the group and all of its children to the
88 // indicated output stream in Egg format.
89 ////////////////////////////////////////////////////////////////////
90 void EggGroupNode::
91 write(ostream &out, int indent_level) const {
92  iterator i;
93 
94  // Since joints tend to reference vertex pools, which sometimes
95  // appear later in the file, and since generally non-joints don't
96  // reference joints, we try to maximize our chance of writing out a
97  // one-pass readable egg file by writing joints at the end of the
98  // list of children of a particular node.
99 
100  for (i = begin(); i != end(); ++i) {
101  PT(EggNode) child = (*i);
102  if (!child->is_joint()) {
103  child->write(out, indent_level);
104  }
105  }
106 
107  for (i = begin(); i != end(); ++i) {
108  PT(EggNode) child = (*i);
109  if (child->is_joint()) {
110  child->write(out, indent_level);
111  }
112  }
113 }
114 
115 ////////////////////////////////////////////////////////////////////
116 // Function: EggGroupNode::begin
117 // Access: Published
118 // Description:
119 ////////////////////////////////////////////////////////////////////
120 EggGroupNode::iterator EggGroupNode::
121 begin() const {
122  return _children.begin();
123 }
124 
125 ////////////////////////////////////////////////////////////////////
126 // Function: EggGroupNode::end
127 // Access: Published
128 // Description:
129 ////////////////////////////////////////////////////////////////////
130 EggGroupNode::iterator EggGroupNode::
131 end() const {
132  return _children.end();
133 }
134 
135 ////////////////////////////////////////////////////////////////////
136 // Function: EggGroupNode::rbegin
137 // Access: Published
138 // Description:
139 ////////////////////////////////////////////////////////////////////
140 EggGroupNode::reverse_iterator EggGroupNode::
141 rbegin() const {
142  return _children.rbegin();
143 }
144 
145 ////////////////////////////////////////////////////////////////////
146 // Function: EggGroupNode::rend
147 // Access: Published
148 // Description:
149 ////////////////////////////////////////////////////////////////////
150 EggGroupNode::reverse_iterator EggGroupNode::
151 rend() const {
152  return _children.rend();
153 }
154 
155 ////////////////////////////////////////////////////////////////////
156 // Function: EggGroupNode::insert
157 // Access: Published
158 // Description:
159 ////////////////////////////////////////////////////////////////////
160 EggGroupNode::iterator EggGroupNode::
161 insert(iterator position, PT(EggNode) x) {
162  prepare_add_child(x);
163  return _children.insert((Children::iterator &)position, x);
164 }
165 
166 ////////////////////////////////////////////////////////////////////
167 // Function: EggGroupNode::erase
168 // Access: Published
169 // Description:
170 ////////////////////////////////////////////////////////////////////
171 EggGroupNode::iterator EggGroupNode::
172 erase(iterator position) {
173  prepare_remove_child(*position);
174  return _children.erase((Children::iterator &)position);
175 }
176 
177 ////////////////////////////////////////////////////////////////////
178 // Function: EggGroupNode::erase
179 // Access: Published
180 // Description:
181 ////////////////////////////////////////////////////////////////////
182 EggGroupNode::iterator EggGroupNode::
183 erase(iterator first, iterator last) {
184  iterator i;
185  for (i = first; i != last; ++i) {
186  prepare_remove_child(*i);
187  }
188  return _children.erase((Children::iterator &)first,
189  (Children::iterator &)last);
190 }
191 
192 ////////////////////////////////////////////////////////////////////
193 // Function: EggGroupNode::replace
194 // Access: Published
195 // Description: Replaces the node at the indicated position with
196 // the indicated node. It is an error to call this
197 // with an invalid position iterator (e.g. end()).
198 ////////////////////////////////////////////////////////////////////
199 void EggGroupNode::
200 replace(iterator position, PT(EggNode) x) {
201  nassertv(position != end());
202 
203  prepare_remove_child(*position);
204  prepare_add_child(x);
205  *(Children::iterator &)position = x;
206 }
207 
208 ////////////////////////////////////////////////////////////////////
209 // Function: EggGroupNode::empty
210 // Access: Published
211 // Description:
212 ////////////////////////////////////////////////////////////////////
213 bool EggGroupNode::
214 empty() const {
215  return _children.empty();
216 }
217 
218 ////////////////////////////////////////////////////////////////////
219 // Function: EggGroupNode::size
220 // Access: Published
221 // Description:
222 ////////////////////////////////////////////////////////////////////
223 EggGroupNode::size_type EggGroupNode::
224 size() const {
225  return _children.size();
226 }
227 
228 ////////////////////////////////////////////////////////////////////
229 // Function: EggGroupNode::clear
230 // Access: Published
231 // Description:
232 ////////////////////////////////////////////////////////////////////
233 void EggGroupNode::
234 clear() {
235  erase(begin(), end());
236 }
237 
238 ////////////////////////////////////////////////////////////////////
239 // Function: EggGroupNode::get_first_child
240 // Access: Published
241 // Description: Returns the first child in the group's list of
242 // children, or NULL if the list of children is empty.
243 // Can be used with get_next_child() to return the
244 // complete list of children without using the iterator
245 // class; however, this is non-thread-safe, and so is
246 // not recommended except for languages other than C++
247 // which cannot use the iterators.
248 ////////////////////////////////////////////////////////////////////
251  _gnc_iterator = begin();
252  return get_next_child();
253 }
254 
255 ////////////////////////////////////////////////////////////////////
256 // Function: EggGroupNode::get_next_child
257 // Access: Published
258 // Description: Returns the next child in the group's list of
259 // children since the last call to get_first_child() or
260 // get_next_child(), or NULL if the last child has been
261 // returned. Can be used with get_first_child() to
262 // return the complete list of children without using
263 // the iterator class; however, this is non-thread-safe,
264 // and so is not recommended except for languages other
265 // than C++ which cannot use the iterators.
266 //
267 // It is an error to call this without previously
268 // calling get_first_child().
269 ////////////////////////////////////////////////////////////////////
272  if (_gnc_iterator != end()) {
273  return *_gnc_iterator++;
274  }
275  return NULL;
276 }
277 
278 ////////////////////////////////////////////////////////////////////
279 // Function: EggGroupNode::add_child
280 // Access: Published
281 // Description: Adds the indicated child to the group and returns it.
282 // If the child node is already a child of some other
283 // node, removes it first.
284 ////////////////////////////////////////////////////////////////////
288  PT(EggNode) ptnode = node;
289  if (node->_parent != NULL) {
290  node->_parent->remove_child(node);
291  }
292  prepare_add_child(node);
293  _children.push_back(node);
294  return node;
295 }
296 
297 ////////////////////////////////////////////////////////////////////
298 // Function: EggGroupNode::remove_child
299 // Access: Published
300 // Description: Removes the indicated child node from the group and
301 // returns it. If the child was not already in the
302 // group, does nothing and returns NULL.
303 ////////////////////////////////////////////////////////////////////
304 PT(EggNode) EggGroupNode::
305 remove_child(EggNode *node) {
306  PT(EggNode) ptnode = node;
307  iterator i = find(begin(), end(), ptnode);
308  if (i == end()) {
309  return PT(EggNode)();
310  } else {
311  // erase() calls prepare_remove_child().
312  erase(i);
313  return ptnode;
314  }
315 }
316 
317 
318 ////////////////////////////////////////////////////////////////////
319 // Function: EggGroupNode::steal_children
320 // Access: Published
321 // Description: Moves all the children from the other node to this
322 // one. This is especially useful because the group
323 // node copy assignment operator does not copy children.
324 ////////////////////////////////////////////////////////////////////
325 void EggGroupNode::
327  Children::iterator ci;
328  for (ci = other._children.begin();
329  ci != other._children.end();
330  ++ci) {
331  other.prepare_remove_child(*ci);
332  prepare_add_child(*ci);
333  }
334 
335  _children.splice(_children.end(), other._children);
336 }
337 
338 ////////////////////////////////////////////////////////////////////
339 // Function: EggGroupNode::find_child
340 // Access: Published
341 // Description: Returns the child of this node whose name is the
342 // indicated string, or NULL if there is no child of
343 // this node by that name. Does not search recursively.
344 ////////////////////////////////////////////////////////////////////
346 find_child(const string &name) const {
347  Children::const_iterator ci;
348  for (ci = _children.begin(); ci != _children.end(); ++ci) {
349  EggNode *child = (*ci);
350  if (child->get_name() == name) {
351  return child;
352  }
353  }
354 
355  return NULL;
356 }
357 
358 ////////////////////////////////////////////////////////////////////
359 // Function: EggGroupNode::has_absolute_pathnames
360 // Access: Published
361 // Description: Returns true if any nodes at this level and below
362 // include a reference to a file via an absolute
363 // pathname, or false if all references are relative.
364 ////////////////////////////////////////////////////////////////////
365 bool EggGroupNode::
367  Children::const_iterator ci;
368  for (ci = _children.begin();
369  ci != _children.end();
370  ++ci) {
371  EggNode *child = *ci;
372  if (child->is_of_type(EggTexture::get_class_type())) {
373  EggTexture *tex = DCAST(EggTexture, child);
374  if (!tex->get_filename().is_local()) {
375  if (egg_cat.is_debug()) {
376  egg_cat.debug()
377  << "Absolute pathname: " << tex->get_filename()
378  << "\n";
379  }
380  return true;
381  }
382 
383  if (tex->has_alpha_filename()) {
384  if (!tex->get_alpha_filename().is_local()) {
385  if (egg_cat.is_debug()) {
386  egg_cat.debug()
387  << "Absolute pathname: " << tex->get_alpha_filename()
388  << "\n";
389  }
390  return true;
391  }
392  }
393 
394  } else if (child->is_of_type(EggFilenameNode::get_class_type())) {
395  EggFilenameNode *fnode = DCAST(EggFilenameNode, child);
396  if (!fnode->get_filename().is_local()) {
397  if (egg_cat.is_debug()) {
398  egg_cat.debug()
399  << "Absolute pathname: " << fnode->get_filename()
400  << "\n";
401  }
402  return true;
403  }
404 
405  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
406  if (DCAST(EggGroupNode, child)->has_absolute_pathnames()) {
407  return true;
408  }
409  }
410  }
411 
412  return false;
413 }
414 
415 ////////////////////////////////////////////////////////////////////
416 // Function: EggGroupNode::resolve_filenames
417 // Access: Published
418 // Description: Walks the tree and attempts to resolve any filenames
419 // encountered. This looks up filenames along the
420 // specified search path; it does not automatically
421 // search the model_path for missing files.
422 ////////////////////////////////////////////////////////////////////
423 void EggGroupNode::
424 resolve_filenames(const DSearchPath &searchpath) {
426 
427  Children::iterator ci;
428  for (ci = _children.begin();
429  ci != _children.end();
430  ++ci) {
431  EggNode *child = *ci;
432  if (child->is_of_type(EggTexture::get_class_type())) {
433  EggTexture *tex = DCAST(EggTexture, child);
434  Filename tex_filename = tex->get_filename();
435  vfs->resolve_filename(tex_filename, searchpath);
436  tex->set_filename(tex_filename);
437 
438  if (tex->has_alpha_filename()) {
439  Filename alpha_filename = tex->get_alpha_filename();
440  vfs->resolve_filename(alpha_filename, searchpath);
441  tex->set_alpha_filename(alpha_filename);
442  }
443 
444  } else if (child->is_of_type(EggFilenameNode::get_class_type())) {
445  EggFilenameNode *fnode = DCAST(EggFilenameNode, child);
446  Filename filename = fnode->get_filename();
447  vfs->resolve_filename(filename, searchpath, fnode->get_default_extension());
448  fnode->set_filename(filename);
449 
450  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
451  DCAST(EggGroupNode, child)->resolve_filenames(searchpath);
452  }
453  }
454 }
455 
456 ////////////////////////////////////////////////////////////////////
457 // Function: EggGroupNode::force_filenames
458 // Access: Published
459 // Description: Similar to resolve_filenames, but each non-absolute
460 // filename encountered is arbitrarily taken to be in
461 // the indicated directory, whether or not the so-named
462 // filename exists.
463 ////////////////////////////////////////////////////////////////////
464 void EggGroupNode::
465 force_filenames(const Filename &directory) {
466  Children::iterator ci;
467  for (ci = _children.begin();
468  ci != _children.end();
469  ++ci) {
470  EggNode *child = *ci;
471  if (child->is_of_type(EggTexture::get_class_type())) {
472  EggTexture *tex = DCAST(EggTexture, child);
473  Filename tex_filename = tex->get_filename();
474  if (tex_filename.is_local()) {
475  tex->set_filename(Filename(directory, tex_filename));
476  }
477 
478  if (tex->has_alpha_filename()) {
479  Filename alpha_filename = tex->get_alpha_filename();
480  if (alpha_filename.is_local()) {
481  tex->set_alpha_filename(Filename(directory, alpha_filename));
482  }
483  }
484 
485  } else if (child->is_of_type(EggFilenameNode::get_class_type())) {
486  EggFilenameNode *fnode = DCAST(EggFilenameNode, child);
487  Filename filename = fnode->get_filename();
488  if (filename.is_local()) {
489  fnode->set_filename(Filename(directory, filename));
490  }
491 
492  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
493  DCAST(EggGroupNode, child)->force_filenames(directory);
494  }
495  }
496 }
497 
498 ////////////////////////////////////////////////////////////////////
499 // Function: EggGroupNode::reverse_vertex_ordering
500 // Access: Published
501 // Description: Reverses the vertex ordering of all polygons defined
502 // at this node and below. Does not change the surface
503 // normals, if any.
504 ////////////////////////////////////////////////////////////////////
505 void EggGroupNode::
507  Children::iterator ci;
508  for (ci = _children.begin();
509  ci != _children.end();
510  ++ci) {
511  EggNode *child = *ci;
512  if (child->is_of_type(EggPrimitive::get_class_type())) {
513  EggPrimitive *prim = DCAST(EggPrimitive, child);
514  prim->reverse_vertex_ordering();
515 
516  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
517  DCAST(EggGroupNode, child)->reverse_vertex_ordering();
518  }
519  }
520 }
521 
522 ////////////////////////////////////////////////////////////////////
523 // Function: EggGroupNode::recompute_vertex_normals
524 // Access: Published
525 // Description: Recomputes all the vertex normals for polygon
526 // geometry at this group node and below so that they
527 // accurately reflect the vertex positions. A shared
528 // edge between two polygons (even in different groups)
529 // is considered smooth if the angle between the two
530 // edges is less than threshold degrees.
531 //
532 // This function also removes degenerate polygons that
533 // do not have enough vertices to define a normal. It
534 // does not affect normals for other kinds of primitives
535 // like Nurbs or Points.
536 //
537 // This function does not remove or adjust vertices in
538 // the vertex pool; it only adds new vertices with the
539 // correct normals. Thus, it is a good idea to call
540 // remove_unused_vertices() after calling this.
541 ////////////////////////////////////////////////////////////////////
542 void EggGroupNode::
543 recompute_vertex_normals(double threshold, CoordinateSystem cs) {
544  // First, collect all the vertices together with their shared
545  // polygons.
546  NVertexCollection collection;
547  r_collect_vertex_normals(collection, threshold, cs);
548 
549  // Now bust them into separate groups according to the edge
550  // threshold. Two polygons that share a vertex belong in the same
551  // group only if the angle between their normals is within the
552  // threshold.
553 
554  double cos_angle = cos(deg_2_rad(threshold));
555 
556  NVertexCollection::iterator ci;
557  for (ci = collection.begin(); ci != collection.end(); ++ci) {
558  NVertexGroup &group = (*ci).second;
559 
560  // Here's a group of polygons that share a vertex. Build up a new
561  // group that consists of just the first polygon and all the ones
562  // that are within threshold degrees from it.
563  NVertexGroup::iterator gi;
564  gi = group.begin();
565  while (gi != group.end()) {
566  const NVertexReference &base_ref = (*gi);
567  NVertexGroup new_group;
568  NVertexGroup leftover_group;
569  new_group.push_back(base_ref);
570  ++gi;
571 
572  while (gi != group.end()) {
573  const NVertexReference &ref = (*gi);
574  double dot = base_ref._normal.dot(ref._normal);
575  if (dot > cos_angle) {
576  // These polygons are close enough to the same angle.
577  new_group.push_back(ref);
578  } else {
579  // These polygons are not.
580  leftover_group.push_back(ref);
581  }
582  ++gi;
583  }
584 
585  // Now new_group is a collection of connected polygons and the
586  // vertices that connect them. Smooth these vertices.
587  do_compute_vertex_normals(new_group);
588 
589  // And reset the group of remaining polygons.
590  group.swap(leftover_group);
591  gi = group.begin();
592  }
593  }
594 }
595 
596 ////////////////////////////////////////////////////////////////////
597 // Function: EggGroupNode::recompute_polygon_normals
598 // Access: Published
599 // Description: Recomputes all the polygon normals for polygon
600 // geometry at this group node and below so that they
601 // accurately reflect the vertex positions. Normals are
602 // removed from the vertices and defined only on
603 // polygons, giving the geometry a faceted appearance.
604 //
605 // This function also removes degenerate polygons that
606 // do not have enough vertices to define a normal. It
607 // does not affect normals for other kinds of primitives
608 // like Nurbs or Points.
609 //
610 // This function does not remove or adjust vertices in
611 // the vertex pool; it only adds new vertices with the
612 // normals removed. Thus, it is a good idea to call
613 // remove_unused_vertices() after calling this.
614 ////////////////////////////////////////////////////////////////////
615 void EggGroupNode::
616 recompute_polygon_normals(CoordinateSystem cs) {
617  Children::iterator ci, cnext;
618  ci = _children.begin();
619  while (ci != _children.end()) {
620  cnext = ci;
621  ++cnext;
622  EggNode *child = *ci;
623 
624  if (child->is_of_type(EggPolygon::get_class_type())) {
625  EggPolygon *polygon = DCAST(EggPolygon, child);
626 
627  if (!polygon->recompute_polygon_normal(cs)) {
628  // The polygon is degenerate. Remove it.
629  prepare_remove_child(child);
630  _children.erase(ci);
631 
632  } else {
633  // Remove the normal from each polygon vertex.
634  size_t num_vertices = polygon->size();
635  for (size_t i = 0; i < num_vertices; i++) {
636  EggVertex *vertex = polygon->get_vertex(i);
637  EggVertexPool *pool = vertex->get_pool();
638 
639  if (vertex->has_normal()) {
640  EggVertex new_vertex(*vertex);
641  new_vertex.clear_normal();
642  EggVertex *unique = pool->create_unique_vertex(new_vertex);
643  unique->copy_grefs_from(*vertex);
644 
645  polygon->set_vertex(i, unique);
646  }
647  }
648  }
649 
650  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
651  DCAST(EggGroupNode, child)->recompute_polygon_normals(cs);
652  }
653 
654  ci = cnext;
655  }
656 }
657 
658 ////////////////////////////////////////////////////////////////////
659 // Function: EggGroupNode::strip_normals
660 // Access: Published
661 // Description: Removes all normals from primitives, and the vertices
662 // they reference, at this node and below.
663 //
664 // This function does not remove or adjust vertices in
665 // the vertex pool; it only adds new vertices with the
666 // normal removed. Thus, it is a good idea to call
667 // remove_unused_vertices() after calling this.
668 ////////////////////////////////////////////////////////////////////
669 void EggGroupNode::
671  Children::iterator ci;
672  for (ci = _children.begin(); ci != _children.end(); ++ci) {
673  EggNode *child = *ci;
674 
675  if (child->is_of_type(EggPrimitive::get_class_type())) {
676  EggPrimitive *prim = DCAST(EggPrimitive, child);
677  prim->clear_normal();
678 
679  // Remove the normal from each prim vertex.
680  size_t num_vertices = prim->size();
681  for (size_t i = 0; i < num_vertices; i++) {
682  EggVertex *vertex = prim->get_vertex(i);
683  EggVertexPool *pool = vertex->get_pool();
684 
685  if (vertex->has_normal()) {
686  EggVertex new_vertex(*vertex);
687  new_vertex.clear_normal();
688  EggVertex *unique = pool->create_unique_vertex(new_vertex);
689  unique->copy_grefs_from(*vertex);
690 
691  prim->set_vertex(i, unique);
692  }
693  }
694 
695  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
696  DCAST(EggGroupNode, child)->strip_normals();
697  }
698  }
699 }
700 
701 ////////////////////////////////////////////////////////////////////
702 // Function: EggGroupNode::recompute_tangent_binormal
703 // Access: Published
704 // Description: This function recomputes the tangent and binormal for
705 // the named texture coordinate set for all vertices at
706 // this level and below. Use the empty string for the
707 // default texture coordinate set.
708 //
709 // It is necessary for each vertex to already have a
710 // normal (or at least a polygon normal), as well as a
711 // texture coordinate in the named texture coordinate
712 // set, before calling this function. You might precede
713 // this with recompute_vertex_normals() to ensure that
714 // the normals exist.
715 //
716 // Like recompute_vertex_normals(), this function does
717 // not remove or adjust vertices in the vertex pool; it
718 // only adds new vertices with the new tangents and
719 // binormals computed. Thus, it is a good idea to call
720 // remove_unused_vertices() after calling this.
721 ////////////////////////////////////////////////////////////////////
722 bool EggGroupNode::
724  // First, collect all the vertices together with their shared
725  // polygons.
726  TBNVertexCollection collection;
727  r_collect_tangent_binormal(uv_name, collection);
728 
729  // Now compute the tangent and binormal separately for each common
730  // group of vertices.
731  TBNVertexCollection::const_iterator ci;
732  for (ci = collection.begin(); ci != collection.end(); ++ci) {
733  const TBNVertexValue &value = (*ci).first;
734  const TBNVertexGroup &group = (*ci).second;
735 
736  do_compute_tangent_binormal(value, group);
737  }
738 
739  return true;
740 }
741 
742 ////////////////////////////////////////////////////////////////////
743 // Function: EggGroupNode::recompute_tangent_binormal
744 // Access: Published
745 // Description: This function recomputes the tangent and binormal for
746 // the named texture coordinate sets.
747 // Returns true if anything was done.
748 ////////////////////////////////////////////////////////////////////
749 bool EggGroupNode::
750 recompute_tangent_binormal(const vector_string &names) {
751  bool changed = false;
752 
753  for (vector_string::const_iterator si = names.begin();
754  si != names.end();
755  ++si) {
756  GlobPattern uv_name(*si);
757  nout << "Computing tangent and binormal for \"" << uv_name << "\"\n";
759  changed = true;
760  }
761 
762  return changed;
763 }
764 
765 ////////////////////////////////////////////////////////////////////
766 // Function: EggGroupNode::recompute_tangent_binormal_auto
767 // Access: Published
768 // Description: This function recomputes the tangent and binormal for
769 // any texture coordinate set that affects a normal map.
770 // Returns true if anything was done.
771 ////////////////////////////////////////////////////////////////////
772 bool EggGroupNode::
774  vector_string names;
776  EggTextureCollection::iterator eti;
777  texs.find_used_textures(this);
778  for (eti = texs.begin(); eti != texs.end(); eti++) {
779  EggTexture *eggtex = (*eti);
780  if ((eggtex->get_env_type() == EggTexture::ET_normal)||
781  (eggtex->get_env_type() == EggTexture::ET_normal_height)||
782  (eggtex->get_env_type() == EggTexture::ET_normal_gloss)) {
783  string uv = eggtex->get_uv_name();
784  vector_string::iterator it = find(names.begin(), names.end(), uv);
785  if (it == names.end()) {
786  names.push_back(uv);
787  }
788  }
789  }
790  return recompute_tangent_binormal(names);
791 }
792 
793 ////////////////////////////////////////////////////////////////////
794 // Function: EggGroupNode::triangulate_polygons
795 // Access: Published
796 // Description: Replace all higher-order polygons at this point in
797 // the scene graph and below with triangles. Returns
798 // the total number of new triangles produced, less
799 // degenerate polygons removed.
800 //
801 // If flags contains T_polygon and T_convex, both
802 // concave and convex polygons will be subdivided into
803 // triangles; with only T_polygon, only concave polygons
804 // will be subdivided, and convex polygons will be
805 // largely unchanged.
806 ////////////////////////////////////////////////////////////////////
807 int EggGroupNode::
809  int num_produced = 0;
810 
811  Children children_copy = _children;
812 
813  Children::iterator ci;
814  for (ci = children_copy.begin();
815  ci != children_copy.end();
816  ++ci) {
817  EggNode *child = (*ci);
818 
819  if (child->is_of_type(EggPolygon::get_class_type())) {
820  if ((flags & T_polygon) != 0) {
821  EggPolygon *poly = DCAST(EggPolygon, child);
822  poly->triangulate_in_place((flags & T_convex) != 0);
823  }
824 
825  } else if (child->is_of_type(EggCompositePrimitive::get_class_type())) {
826  if ((flags & T_composite) != 0) {
827  EggCompositePrimitive *comp = DCAST(EggCompositePrimitive, child);
828  comp->triangulate_in_place();
829  }
830 
831  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
832  if ((flags & T_recurse) != 0) {
833  num_produced += DCAST(EggGroupNode, child)->triangulate_polygons(flags);
834  }
835  }
836  }
837 
838  num_produced += max(0, (int)(_children.size() - children_copy.size()));
839  return num_produced;
840 }
841 
842 ////////////////////////////////////////////////////////////////////
843 // Function: EggGroupNode::mesh_triangles
844 // Access: Published
845 // Description: Combine triangles together into triangle strips, at
846 // this group and below.
847 ////////////////////////////////////////////////////////////////////
848 void EggGroupNode::
849 mesh_triangles(int flags) {
850  EggMesher mesher;
851  mesher.mesh(this, (flags & T_flat_shaded) != 0);
852 
853  if ((flags & T_recurse) != 0) {
854  EggGroupNode::iterator ci;
855  for (ci = begin(); ci != end(); ++ci) {
856  if ((*ci)->is_of_type(EggGroupNode::get_class_type())) {
857  EggGroupNode *group_child = DCAST(EggGroupNode, *ci);
858  group_child->mesh_triangles(flags);
859  }
860  }
861  }
862 }
863 
864 ////////////////////////////////////////////////////////////////////
865 // Function: EggGroupNode::make_point_primitives
866 // Access: Published
867 // Description: Creates PointLight primitives to reference any
868 // otherwise unreferences vertices discovered in this
869 // group or below.
870 ////////////////////////////////////////////////////////////////////
871 void EggGroupNode::
873  // Create a temporary node to hold the EggPoint objects we might
874  // create while we iterate. (We don't add them during the iteration
875  // to avoid invalidating the iterator.)
876  PT(EggGroupNode) temp = new EggGroup("temp");
877 
878  EggGroupNode::iterator ci;
879  for (ci = begin(); ci != end(); ++ci) {
880  if ((*ci)->is_of_type(EggGroupNode::get_class_type())) {
881  EggGroupNode *group_child = DCAST(EggGroupNode, *ci);
882  group_child->make_point_primitives();
883 
884  } else if ((*ci)->is_of_type(EggVertexPool::get_class_type())) {
885  EggVertexPool *vpool = DCAST(EggVertexPool, *ci);
886  PT(EggPrimitive) prim = new EggPoint;
887  vpool->add_unused_vertices_to_prim(prim);
888  if (!prim->empty()) {
889  temp->add_child(prim);
890  }
891  }
892  }
893 
894  steal_children(*temp);
895 }
896 
897 ////////////////////////////////////////////////////////////////////
898 // Function: EggGroupNode::rename_nodes
899 // Access: Published
900 // Description: Rename by stripping out the prefix
901 ////////////////////////////////////////////////////////////////////
902 int EggGroupNode::
903 rename_nodes(vector_string strip_prefix, bool recurse) {
904  int num_renamed = 0;
905  for (unsigned int ni = 0; ni < strip_prefix.size(); ++ni) {
906  string axe_name = strip_prefix[ni];
907  if (this->get_name().substr(0, axe_name.size()) == axe_name) {
908  string new_name = this->get_name().substr(axe_name.size());
909  //cout << "renaming " << this->get_name() << "->" << new_name << endl;
910  this->set_name(new_name);
911  num_renamed += 1;
912  }
913  }
914  if (recurse) {
915  EggGroupNode::iterator ci;
916  for (ci = begin(); ci != end(); ++ci) {
917  if ((*ci)->is_of_type(EggGroupNode::get_class_type())) {
918  EggGroupNode *group_child = DCAST(EggGroupNode, *ci);
919  num_renamed += group_child->rename_nodes(strip_prefix, recurse);
920  }
921  else if ((*ci)->is_of_type(EggNode::get_class_type())) {
922  EggNode *node_child = DCAST(EggNode, *ci);
923  num_renamed += node_child->rename_node(strip_prefix);
924  }
925  }
926  }
927  return num_renamed;
928 }
929 
930 ////////////////////////////////////////////////////////////////////
931 // Function: EggGroupNode::remove_unused_vertices
932 // Access: Published
933 // Description: Removes all vertices from VertexPools within this
934 // group or below that are not referenced by at least
935 // one primitive. Also collapses together equivalent
936 // vertices, and renumbers all vertices after the
937 // operation so their indices are consecutive, beginning
938 // at zero. Returns the total number of vertices
939 // removed.
940 //
941 // Note that this operates on the VertexPools within
942 // this group level, without respect to primitives that
943 // reference these vertices (unlike other functions like
944 // strip_normals()). It is therefore most useful to
945 // call this on the EggData root, rather than on a
946 // subgroup within the hierarchy, since a VertexPool may
947 // appear anywhere in the hierarchy.
948 ////////////////////////////////////////////////////////////////////
949 int EggGroupNode::
950 remove_unused_vertices(bool recurse) {
951  int num_removed = 0;
952 
953  Children::iterator ci, cnext;
954  ci = _children.begin();
955  while (ci != _children.end()) {
956  cnext = ci;
957  ++cnext;
958  EggNode *child = *ci;
959 
960  if (child->is_of_type(EggVertexPool::get_class_type())) {
961  EggVertexPool *vpool = DCAST(EggVertexPool, child);
962  num_removed += vpool->remove_unused_vertices();
963 
964  if (vpool->empty()) {
965  // If, after removing all the vertices, there's nothing left
966  // in the vertex pool, then remove the whole vertex pool.
967  _children.erase(ci);
968  }
969 
970  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
971  if (recurse) {
972  num_removed += DCAST(EggGroupNode, child)->remove_unused_vertices(recurse);
973  }
974  }
975 
976  ci = cnext;
977  }
978 
979  return num_removed;
980 }
981 
982 ////////////////////////////////////////////////////////////////////
983 // Function: EggGroupNode::remove_invalid_primitives
984 // Access: Published
985 // Description: Removes primitives at this level and below which
986 // appear to be degenerate; e.g. polygons with fewer
987 // than 3 vertices, etc. Returns the number of
988 // primitives removed.
989 ////////////////////////////////////////////////////////////////////
990 int EggGroupNode::
992  int num_removed = 0;
993 
994  Children::iterator ci, cnext;
995  ci = _children.begin();
996  while (ci != _children.end()) {
997  cnext = ci;
998  ++cnext;
999  EggNode *child = *ci;
1000 
1001  if (child->is_of_type(EggPrimitive::get_class_type())) {
1002  EggPrimitive *prim = DCAST(EggPrimitive, child);
1003  if (!prim->cleanup()) {
1004  _children.erase(ci);
1005  num_removed++;
1006  }
1007 
1008  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
1009  if (recurse) {
1010  num_removed += DCAST(EggGroupNode, child)->remove_invalid_primitives(recurse);
1011  }
1012  }
1013 
1014  ci = cnext;
1015  }
1016 
1017  return num_removed;
1018 }
1019 
1020 ////////////////////////////////////////////////////////////////////
1021 // Function: EggGroupNode::clear_connected_shading
1022 // Access: Published
1023 // Description: Resets the connected_shading information on all
1024 // primitives at this node and below, so that it may be
1025 // accurately rederived by the next call to
1026 // get_connected_shading().
1027 //
1028 // It may be a good idea to call
1029 // remove_unused_vertices() as well, to establish the
1030 // correct connectivity between common vertices.
1031 ////////////////////////////////////////////////////////////////////
1032 void EggGroupNode::
1034  Children::iterator ci;
1035  for (ci = _children.begin(); ci != _children.end(); ++ci) {
1036  EggNode *child = *ci;
1037 
1038  if (child->is_of_type(EggPrimitive::get_class_type())) {
1039  EggPrimitive *prim = DCAST(EggPrimitive, child);
1040  prim->clear_connected_shading();
1041  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
1042  DCAST(EggGroupNode, child)->clear_connected_shading();
1043  }
1044  }
1045 }
1046 
1047 ////////////////////////////////////////////////////////////////////
1048 // Function: EggGroupNode::get_connected_shading
1049 // Access: Published
1050 // Description: Queries the connected_shading information on all
1051 // primitives at this node and below, to ensure that it
1052 // has been completely filled in before we start mucking
1053 // around with vertices.
1054 ////////////////////////////////////////////////////////////////////
1055 void EggGroupNode::
1057  Children::iterator ci;
1058  for (ci = _children.begin(); ci != _children.end(); ++ci) {
1059  EggNode *child = *ci;
1060 
1061  if (child->is_of_type(EggPrimitive::get_class_type())) {
1062  EggPrimitive *prim = DCAST(EggPrimitive, child);
1063  prim->get_connected_shading();
1064  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
1065  DCAST(EggGroupNode, child)->get_connected_shading();
1066  }
1067  }
1068 }
1069 
1070 ////////////////////////////////////////////////////////////////////
1071 // Function: EggGroupNode::unify_attributes
1072 // Access: Published
1073 // Description: Applies per-vertex normal and color to all vertices,
1074 // if they are in fact per-vertex (and different for
1075 // each vertex), or moves them to the primitive if they
1076 // are all the same.
1077 //
1078 // After this call, either the primitive will have
1079 // normals or its vertices will, but not both. Ditto
1080 // for colors.
1081 //
1082 // If use_connected_shading is true, each polygon is
1083 // considered in conjunction with all connected
1084 // polygons; otherwise, each polygon is considered
1085 // individually.
1086 //
1087 // If allow_per_primitive is false, S_per_face or
1088 // S_overall will treated like S_per_vertex: normals and
1089 // colors will always be assigned to the vertices. In
1090 // this case, there will never be per-primitive colors
1091 // or normals after this call returns. On the other
1092 // hand, if allow_per_primitive is true, then S_per_face
1093 // means that normals and colors should be assigned to
1094 // the primitives, and removed from the vertices, as
1095 // described above.
1096 //
1097 // This may create redundant vertices in the vertex
1098 // pool, so it may be a good idea to follow this up with
1099 // remove_unused_vertices().
1100 ////////////////////////////////////////////////////////////////////
1101 void EggGroupNode::
1102 unify_attributes(bool use_connected_shading, bool allow_per_primitive,
1103  bool recurse) {
1104  Children::iterator ci;
1105  for (ci = _children.begin(); ci != _children.end(); ++ci) {
1106  EggNode *child = *ci;
1107 
1108  if (child->is_of_type(EggPrimitive::get_class_type())) {
1109  EggPrimitive *prim = DCAST(EggPrimitive, child);
1110 
1111  EggPrimitive::Shading shading = EggPrimitive::S_per_vertex;
1112 
1113  if (allow_per_primitive) {
1114  shading = prim->get_shading();
1115  if (use_connected_shading) {
1116  shading = prim->get_connected_shading();
1117  }
1118  }
1119 
1120  prim->unify_attributes(shading);
1121 
1122  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
1123  if (recurse) {
1124  DCAST(EggGroupNode, child)->unify_attributes
1125  (use_connected_shading, allow_per_primitive, recurse);
1126  }
1127  }
1128  }
1129 }
1130 
1131 ////////////////////////////////////////////////////////////////////
1132 // Function: EggGroupNode::apply_last_attribute
1133 // Access: Published
1134 // Description: Sets the last vertex of the triangle (or each
1135 // component) to the primitive normal and/or color, if
1136 // the primitive is flat-shaded. This reflects the
1137 // OpenGL convention of storing flat-shaded properties on
1138 // the last vertex, although it is not usually a
1139 // convention in Egg.
1140 //
1141 // This may create redundant vertices in the vertex
1142 // pool, so it may be a good idea to follow this up with
1143 // remove_unused_vertices().
1144 ////////////////////////////////////////////////////////////////////
1145 void EggGroupNode::
1146 apply_last_attribute(bool recurse) {
1147  Children::iterator ci;
1148  for (ci = _children.begin(); ci != _children.end(); ++ci) {
1149  EggNode *child = *ci;
1150 
1151  if (child->is_of_type(EggPrimitive::get_class_type())) {
1152  EggPrimitive *prim = DCAST(EggPrimitive, child);
1153  prim->apply_last_attribute();
1154  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
1155  if (recurse) {
1156  DCAST(EggGroupNode, child)->apply_last_attribute(recurse);
1157  }
1158  }
1159  }
1160 }
1161 
1162 ////////////////////////////////////////////////////////////////////
1163 // Function: EggGroupNode::apply_first_attribute
1164 // Access: Published
1165 // Description: Sets the first vertex of the triangle (or each
1166 // component) to the primitive normal and/or color, if
1167 // the primitive is flat-shaded. This reflects the
1168 // DirectX convention of storing flat-shaded properties on
1169 // the first vertex, although it is not usually a
1170 // convention in Egg.
1171 //
1172 // This may create redundant vertices in the vertex
1173 // pool, so it may be a good idea to follow this up with
1174 // remove_unused_vertices().
1175 ////////////////////////////////////////////////////////////////////
1176 void EggGroupNode::
1177 apply_first_attribute(bool recurse) {
1178  Children::iterator ci;
1179  for (ci = _children.begin(); ci != _children.end(); ++ci) {
1180  EggNode *child = *ci;
1181 
1182  if (child->is_of_type(EggPrimitive::get_class_type())) {
1183  EggPrimitive *prim = DCAST(EggPrimitive, child);
1184  prim->apply_first_attribute();
1185  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
1186  if (recurse) {
1187  DCAST(EggGroupNode, child)->apply_first_attribute(recurse);
1188  }
1189  }
1190  }
1191 }
1192 
1193 ////////////////////////////////////////////////////////////////////
1194 // Function: EggGroupNode::post_apply_flat_attribute
1195 // Access: Published
1196 // Description: Intended as a followup to apply_last_attribute(),
1197 // this also sets an attribute on the first vertices of
1198 // the primitive, if they don't already have an
1199 // attribute set, just so they end up with *something*.
1200 ////////////////////////////////////////////////////////////////////
1201 void EggGroupNode::
1203  Children::iterator ci;
1204  for (ci = _children.begin(); ci != _children.end(); ++ci) {
1205  EggNode *child = *ci;
1206 
1207  if (child->is_of_type(EggPrimitive::get_class_type())) {
1208  EggPrimitive *prim = DCAST(EggPrimitive, child);
1209  prim->post_apply_flat_attribute();
1210  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
1211  if (recurse) {
1212  DCAST(EggGroupNode, child)->post_apply_flat_attribute(recurse);
1213  }
1214  }
1215  }
1216 }
1217 
1218 ////////////////////////////////////////////////////////////////////
1219 // Function: EggGroupNode::has_primitives
1220 // Access: Published, Virtual
1221 // Description: Returns true if there are any primitives
1222 // (e.g. polygons) defined within this group or below,
1223 // false otherwise.
1224 ////////////////////////////////////////////////////////////////////
1225 bool EggGroupNode::
1227  Children::const_iterator ci;
1228  for (ci = _children.begin();
1229  ci != _children.end();
1230  ++ci) {
1231  if ((*ci)->has_primitives()) {
1232  return true;
1233  }
1234  }
1235 
1236  return false;
1237 }
1238 
1239 ////////////////////////////////////////////////////////////////////
1240 // Function: EggGroupNode::joint_has_primitives
1241 // Access: Published, Virtual
1242 // Description: Returns true if there are any primitives
1243 // (e.g. polygons) defined within this group or below,
1244 // but the search does not include nested joints.
1245 ////////////////////////////////////////////////////////////////////
1246 bool EggGroupNode::
1248  Children::const_iterator ci;
1249  for (ci = _children.begin();
1250  ci != _children.end();
1251  ++ci) {
1252  EggNode *child = (*ci);
1253 
1254  if (!child->is_joint()) {
1255  if (child->joint_has_primitives()) {
1256  return true;
1257  }
1258  }
1259  }
1260 
1261  return false;
1262 }
1263 
1264 ////////////////////////////////////////////////////////////////////
1265 // Function: EggGroupNode::has_normals
1266 // Access: Published, Virtual
1267 // Description: Returns true if any of the primitives (e.g. polygons)
1268 // defined within this group or below have either face
1269 // or vertex normals defined, false otherwise.
1270 ////////////////////////////////////////////////////////////////////
1271 bool EggGroupNode::
1272 has_normals() const {
1273  Children::const_iterator ci;
1274  for (ci = _children.begin();
1275  ci != _children.end();
1276  ++ci) {
1277  if ((*ci)->has_normals()) {
1278  return true;
1279  }
1280  }
1281 
1282  return false;
1283 }
1284 
1285 ////////////////////////////////////////////////////////////////////
1286 // Function: EggGroupNode::rebuild_vertex_pools
1287 // Access: Published
1288 // Description: Copies vertices used by the primitives at this group
1289 // node (and below, if recurse is true) into one or more
1290 // new vertex pools, and updates the primitives to
1291 // reference these pools. It is up to the caller to
1292 // parent the newly-created vertex pools somewhere
1293 // appropriate in the egg hierarchy.
1294 //
1295 // No more than max_vertices will be placed into any one
1296 // vertex pool. This is the sole criteria for splitting
1297 // vertex pools.
1298 ////////////////////////////////////////////////////////////////////
1299 void EggGroupNode::
1300 rebuild_vertex_pools(EggVertexPools &vertex_pools, unsigned int max_vertices,
1301  bool recurse) {
1302  Children::iterator ci;
1303  for (ci = _children.begin(); ci != _children.end(); ++ci) {
1304  EggNode *child = *ci;
1305 
1306  if (child->is_of_type(EggPrimitive::get_class_type())) {
1307  typedef pvector< PT(EggVertex) > Vertices;
1308  Vertices vertices;
1309  EggPrimitive *prim = DCAST(EggPrimitive, child);
1310 
1311  // Copy all of the vertices out.
1312  EggPrimitive::const_iterator pi;
1313  for (pi = prim->begin(); pi != prim->end(); ++pi) {
1314  vertices.push_back(*pi);
1315  }
1316 
1317  typedef epvector<EggAttributes> Attributes;
1318  Attributes attributes;
1319 
1320  if (prim->is_of_type(EggCompositePrimitive::get_class_type())) {
1321  // A compositive primitive has the additional complication of
1322  // dealing with its attributes.
1323  EggCompositePrimitive *cprim = DCAST(EggCompositePrimitive, prim);
1324  int i;
1325  int num_components = cprim->get_num_components();
1326  for (i = 0; i < num_components; i++) {
1327  attributes.push_back(*cprim->get_component(i));
1328  }
1329  }
1330 
1331  prim->clear();
1332 
1333  // Now look for a new home for the vertices. First, see if any
1334  // of the vertex pools we've already created already have a copy
1335  // of each one of the vertices.
1336  bool found_pool = false;
1337  EggVertexPool *best_pool = NULL;
1338  int best_new_vertices = 0;
1339 
1340  Vertices new_vertices;
1341  EggVertexPools::iterator vpi;
1342  for (vpi = vertex_pools.begin();
1343  vpi != vertex_pools.end() && !found_pool;
1344  ++vpi) {
1345  EggVertexPool *vertex_pool = (*vpi);
1346  int num_new_vertices = 0;
1347 
1348  new_vertices.clear();
1349  new_vertices.reserve(vertices.size());
1350 
1351  Vertices::const_iterator vi;
1352  for (vi = vertices.begin();
1353  vi != vertices.end() && !found_pool;
1354  ++vi) {
1355  EggVertex *vertex = (*vi);
1356  EggVertex *new_vertex = vertex_pool->find_matching_vertex(*vertex);
1357  new_vertices.push_back(new_vertex);
1358  if (new_vertex == (EggVertex *)NULL) {
1359  ++num_new_vertices;
1360  }
1361  }
1362 
1363  if (num_new_vertices == 0) {
1364  // Great, we found a vertex pool that already shares all
1365  // these vertices. No need to look any further.
1366  found_pool = true;
1367 
1368  } else if (vertex_pool->size() + num_new_vertices <= max_vertices) {
1369  // We would have to add some vertices to this pool, so this
1370  // vertex pool qualifies only if the number of vertices we
1371  // have to add would still keep it within our limit.
1372  if (best_pool == (EggVertexPool *)NULL ||
1373  num_new_vertices < best_new_vertices) {
1374  // This is currently our most favorable vertex pool.
1375  best_pool = vertex_pool;
1376  best_new_vertices = num_new_vertices;
1377  }
1378  }
1379  }
1380 
1381  if (!found_pool) {
1382  if (best_pool == (EggVertexPool *)NULL) {
1383  // There was no vertex pool that qualified. We will have to
1384  // create a new vertex pool.
1385  best_pool = new EggVertexPool("");
1386  vertex_pools.push_back(best_pool);
1387  }
1388 
1389  new_vertices.clear();
1390  new_vertices.reserve(vertices.size());
1391 
1392  Vertices::const_iterator vi;
1393  for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
1394  EggVertex *vertex = (*vi);
1395  EggVertex *new_vertex = best_pool->create_unique_vertex(*vertex);
1396  new_vertex->copy_grefs_from(*vertex);
1397  new_vertices.push_back(new_vertex);
1398  }
1399  }
1400 
1401  Vertices::const_iterator vi;
1402  nassertv(new_vertices.size() == vertices.size());
1403  for (vi = new_vertices.begin(); vi != new_vertices.end(); ++vi) {
1404  EggVertex *new_vertex = (*vi);
1405  nassertv(new_vertex != (EggVertex *)NULL);
1406  prim->add_vertex(new_vertex);
1407  }
1408 
1409  if (prim->is_of_type(EggCompositePrimitive::get_class_type())) {
1410  // Now restore the composite attributes.
1411  EggCompositePrimitive *cprim = DCAST(EggCompositePrimitive, prim);
1412  int i;
1413  int num_components = cprim->get_num_components();
1414  nassertv(num_components == (int)attributes.size());
1415  for (i = 0; i < num_components; i++) {
1416  cprim->set_component(i, &attributes[i]);
1417  }
1418  }
1419 
1420  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
1421  if (recurse) {
1422  DCAST(EggGroupNode, child)->rebuild_vertex_pools(vertex_pools, max_vertices, recurse);
1423  }
1424  }
1425  }
1426 }
1427 
1428 ////////////////////////////////////////////////////////////////////
1429 // Function: EggGroupNode::update_under
1430 // Access: Protected, Virtual
1431 // Description: This function is called from within EggGroupNode
1432 // whenever the parentage of the node has changed. It
1433 // should update the depth and under_instance flags
1434 // accordingly.
1435 //
1436 // Offset is the difference between the old depth value
1437 // and the new value. It should be consistent with the
1438 // supplied depth value. If it is not, we have some
1439 // error.
1440 ////////////////////////////////////////////////////////////////////
1441 void EggGroupNode::
1442 update_under(int depth_offset) {
1443  EggNode::update_under(depth_offset);
1444 
1445  Children::iterator ci;
1446  for (ci = _children.begin();
1447  ci != _children.end();
1448  ++ci) {
1449  nassertv((*ci)->get_parent() == this);
1450  (*ci)->update_under(depth_offset);
1451  }
1452 }
1453 
1454 ////////////////////////////////////////////////////////////////////
1455 // Function: EggGroupNode::r_transform
1456 // Access: Protected, Virtual
1457 // Description: This is called from within the egg code by
1458 // transform(). It applies a transformation matrix
1459 // to the current node in some sensible way, then
1460 // continues down the tree.
1461 //
1462 // The first matrix is the transformation to apply; the
1463 // second is its inverse. The third parameter is the
1464 // coordinate system we are changing to, or CS_default
1465 // if we are not changing coordinate systems.
1466 ////////////////////////////////////////////////////////////////////
1467 void EggGroupNode::
1468 r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
1469  CoordinateSystem to_cs) {
1470  Children::iterator ci;
1471  for (ci = _children.begin();
1472  ci != _children.end();
1473  ++ci) {
1474  (*ci)->r_transform(mat, inv, to_cs);
1475  }
1476 }
1477 
1478 ////////////////////////////////////////////////////////////////////
1479 // Function: EggGroupNode::r_transform_vertices
1480 // Access: Protected, Virtual
1481 // Description: This is called from within the egg code by
1482 // transform_vertices_only()(). It applies a
1483 // transformation matrix to the current node in some
1484 // sensible way (if the current node is a vertex pool
1485 // with vertices), then continues down the tree.
1486 ////////////////////////////////////////////////////////////////////
1487 void EggGroupNode::
1488 r_transform_vertices(const LMatrix4d &mat) {
1489  Children::iterator ci;
1490  for (ci = _children.begin();
1491  ci != _children.end();
1492  ++ci) {
1493  (*ci)->r_transform_vertices(mat);
1494  }
1495 }
1496 
1497 ////////////////////////////////////////////////////////////////////
1498 // Function: EggGroupNode::r_mark_coordsys
1499 // Access: Protected, Virtual
1500 // Description: This is only called immediately after loading an egg
1501 // file from disk, to propagate the value found in the
1502 // CoordinateSystem entry (or the default Y-up
1503 // coordinate system) to all nodes that care about what
1504 // the coordinate system is.
1505 ////////////////////////////////////////////////////////////////////
1506 void EggGroupNode::
1507 r_mark_coordsys(CoordinateSystem cs) {
1508  Children::iterator ci;
1509  for (ci = _children.begin();
1510  ci != _children.end();
1511  ++ci) {
1512  (*ci)->r_mark_coordsys(cs);
1513  }
1514 }
1515 
1516 ////////////////////////////////////////////////////////////////////
1517 // Function: EggGroupNode::r_flatten_transforms
1518 // Access: Protected, Virtual
1519 // Description: The recursive implementation of flatten_transforms().
1520 ////////////////////////////////////////////////////////////////////
1521 void EggGroupNode::
1522 r_flatten_transforms() {
1523  Children::iterator ci;
1524  for (ci = _children.begin();
1525  ci != _children.end();
1526  ++ci) {
1527  (*ci)->r_flatten_transforms();
1528  }
1529 }
1530 
1531 ////////////////////////////////////////////////////////////////////
1532 // Function: EggGroupNode::r_apply_texmats
1533 // Access: Protected, Virtual
1534 // Description: The recursive implementation of apply_texmats().
1535 ////////////////////////////////////////////////////////////////////
1536 void EggGroupNode::
1537 r_apply_texmats(EggTextureCollection &textures) {
1538  Children::iterator ci;
1539  for (ci = _children.begin();
1540  ci != _children.end();
1541  ++ci) {
1542  (*ci)->r_apply_texmats(textures);
1543  }
1544 }
1545 
1546 ////////////////////////////////////////////////////////////////////
1547 // Function: EggGroupNode::find_coordsys_entry()
1548 // Access: Protected
1549 // Description: Walks the tree, looking for an EggCoordinateSystem
1550 // entry. If one is found, extracts it and returns its
1551 // value. If multiple entries are found, extracts all
1552 // of them and returns CS_invalid if they disagree.
1553 ////////////////////////////////////////////////////////////////////
1554 CoordinateSystem EggGroupNode::
1555 find_coordsys_entry() {
1556  CoordinateSystem coordsys = CS_default;
1557 
1558  // We can do this ci/cnext iteration through the list as we modify
1559  // it, only because we know this works with an STL list type
1560  // container. If this were a vector or a set, this wouldn't
1561  // necessarily work.
1562 
1563  Children::iterator ci, cnext;
1564  ci = _children.begin();
1565  while (ci != _children.end()) {
1566  cnext = ci;
1567  ++cnext;
1568  EggNode *child = *ci;
1569 
1570  if (child->is_of_type(EggCoordinateSystem::get_class_type())) {
1571  CoordinateSystem new_cs =
1572  DCAST(EggCoordinateSystem, child)->get_value();
1573 
1574  // Now remove the CoordinateSystem entry from our child list.
1575  prepare_remove_child(child);
1576  _children.erase(ci);
1577 
1578  if (new_cs != CS_default) {
1579  if (coordsys != CS_default && coordsys != new_cs) {
1580  coordsys = CS_invalid;
1581  } else {
1582  coordsys = new_cs;
1583  }
1584  }
1585 
1586  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
1587  CoordinateSystem new_cs =
1588  DCAST(EggGroupNode, child)->find_coordsys_entry();
1589  if (new_cs != CS_default) {
1590  if (coordsys != CS_default && coordsys != new_cs) {
1591  coordsys = CS_invalid;
1592  } else {
1593  coordsys = new_cs;
1594  }
1595  }
1596  }
1597 
1598  ci = cnext;
1599  }
1600 
1601  return coordsys;
1602 }
1603 
1604 ////////////////////////////////////////////////////////////////////
1605 // Function: EggGroupNode::find_textures()
1606 // Access: Protected
1607 // Description: Walks the tree, looking for EggTextures. Each
1608 // EggTexture that is found is removed from the
1609 // hierarchy and added to the EggTextureCollection.
1610 // Returns the number of EggTextures found.
1611 ////////////////////////////////////////////////////////////////////
1612 int EggGroupNode::
1613 find_textures(EggTextureCollection *collection) {
1614  int num_found = 0;
1615 
1616  // We can do this ci/cnext iteration through the list as we modify
1617  // it, only because we know this works with an STL list type
1618  // container. If this were a vector or a set, this wouldn't
1619  // necessarily work.
1620 
1621  Children::iterator ci, cnext;
1622  ci = _children.begin();
1623  while (ci != _children.end()) {
1624  cnext = ci;
1625  ++cnext;
1626  EggNode *child = *ci;
1627 
1628  if (child->is_of_type(EggTexture::get_class_type())) {
1629  PT_EggTexture tex = DCAST(EggTexture, child);
1630 
1631  // Now remove the EggTexture entry from our child list.
1632  prepare_remove_child(tex);
1633  _children.erase(ci);
1634 
1635  // And add it to the collection.
1636  collection->add_texture(tex);
1637  num_found++;
1638 
1639  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
1640  num_found +=
1641  DCAST(EggGroupNode, child)->find_textures(collection);
1642  }
1643 
1644  ci = cnext;
1645  }
1646 
1647  return num_found;
1648 }
1649 
1650 ////////////////////////////////////////////////////////////////////
1651 // Function: EggGroupNode::find_materials()
1652 // Access: Protected
1653 // Description: Walks the tree, looking for EggMaterials. Each
1654 // EggMaterial that is found is removed from the
1655 // hierarchy and added to the EggMaterialCollection.
1656 // Returns the number of EggMaterials found.
1657 ////////////////////////////////////////////////////////////////////
1658 int EggGroupNode::
1659 find_materials(EggMaterialCollection *collection) {
1660  int num_found = 0;
1661 
1662  // We can do this ci/cnext iteration through the list as we modify
1663  // it, only because we know this works with an STL list type
1664  // container. If this were a vector or a set, this wouldn't
1665  // necessarily work.
1666 
1667  Children::iterator ci, cnext;
1668  ci = _children.begin();
1669  while (ci != _children.end()) {
1670  cnext = ci;
1671  ++cnext;
1672  EggNode *child = *ci;
1673 
1674  if (child->is_of_type(EggMaterial::get_class_type())) {
1675  PT_EggMaterial tex = DCAST(EggMaterial, child);
1676 
1677  // Now remove the EggMaterial entry from our child list.
1678  prepare_remove_child(tex);
1679  _children.erase(ci);
1680 
1681  // And add it to the collection.
1682  collection->add_material(tex);
1683  num_found++;
1684 
1685  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
1686  num_found +=
1687  DCAST(EggGroupNode, child)->find_materials(collection);
1688  }
1689 
1690  ci = cnext;
1691  }
1692 
1693  return num_found;
1694 }
1695 
1696 ////////////////////////////////////////////////////////////////////
1697 // Function: EggGroupNode::r_load_externals
1698 // Access: Protected
1699 // Description: Walks the tree and locates unloaded external
1700 // reference nodes, which it attempts to locate and load
1701 // in. The reference node is replaced with the entire
1702 // subtree loaded. This is intended to be called from
1703 // EggData::load_externals().
1704 ////////////////////////////////////////////////////////////////////
1705 bool EggGroupNode::
1706 r_load_externals(const DSearchPath &searchpath, CoordinateSystem coordsys,
1707  BamCacheRecord *record) {
1708  bool success = true;
1709 
1710  Children::iterator ci;
1711  for (ci = _children.begin();
1712  ci != _children.end();
1713  ++ci) {
1714  EggNode *child = *ci;
1715  if (child->is_of_type(EggExternalReference::get_class_type())) {
1716  PT(EggExternalReference) ref = DCAST(EggExternalReference, child);
1717 
1718  // Replace the reference with an empty group node. When we load
1719  // the external file successfully, we'll put its contents here.
1720  Filename filename = ref->get_filename();
1721  EggGroupNode *new_node =
1722  new EggGroupNode(filename.get_basename_wo_extension());
1723  replace(ci, new_node);
1724 
1725  if (!EggData::resolve_egg_filename(filename, searchpath)) {
1726  egg_cat.error()
1727  << "Could not locate " << filename << " in "
1728  << searchpath << "\n";
1729  } else {
1730  // Now define a new EggData structure to hold the external
1731  // reference, and load it.
1732  EggData ext_data;
1733  ext_data.set_coordinate_system(coordsys);
1734  ext_data.set_auto_resolve_externals(true);
1735  if (ext_data.read(filename)) {
1736  // The external file was read correctly. Add its contents
1737  // into the tree at this point.
1738  if (record != (BamCacheRecord *)NULL) {
1739  record->add_dependent_file(filename);
1740  }
1741 
1742  success =
1743  ext_data.load_externals(searchpath, record)
1744  && success;
1745  new_node->steal_children(ext_data);
1746  }
1747  }
1748 
1749  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
1750  EggGroupNode *group_child = DCAST(EggGroupNode, child);
1751  success =
1752  group_child->r_load_externals(searchpath, coordsys, record)
1753  && success;
1754  }
1755  }
1756  return success;
1757 }
1758 
1759 
1760 ////////////////////////////////////////////////////////////////////
1761 // Function: EggGroupNode::prepare_add_child
1762 // Access: Private
1763 // Description: Marks the node as a child of the group. This is an
1764 // internal function called by the STL-like functions
1765 // push_back() and insert(), in preparation for actually
1766 // adding the child.
1767 //
1768 // It is an error to add a node that is already a child
1769 // of this group or some other group.
1770 ////////////////////////////////////////////////////////////////////
1771 void EggGroupNode::
1772 prepare_add_child(EggNode *node) {
1773  nassertv(node != (EggNode *)NULL);
1775  node->test_ref_count_integrity();
1776  // Make sure the node is not already a child of some other group.
1777  nassertv(node->get_parent() == NULL);
1778  nassertv(node->get_depth() == 0);
1779  node->_parent = this;
1780 
1781  node->update_under(get_depth() + 1);
1782 }
1783 
1784 
1785 ////////////////////////////////////////////////////////////////////
1786 // Function: EggGroupNode::prepare_remove_child
1787 // Access: Private
1788 // Description: Marks the node as removed from the group. This is an
1789 // internal function called by the STL-like functions
1790 // pop_back() and erase(), in preparation for actually
1791 // doing the removal.
1792 //
1793 // It is an error to attempt to remove a node that is
1794 // not already a child of this group.
1795 ////////////////////////////////////////////////////////////////////
1796 void EggGroupNode::
1797 prepare_remove_child(EggNode *node) {
1798  nassertv(node != (EggNode *)NULL);
1799  // Make sure the node is in fact a child of this group.
1800  nassertv(node->get_parent() == this);
1801  nassertv(node->get_depth() == get_depth() + 1);
1802  node->_parent = NULL;
1803 
1804  node->update_under(-(get_depth() + 1));
1805 }
1806 
1807 
1808 
1809 ////////////////////////////////////////////////////////////////////
1810 // Function: EggGroupNode::r_collect_vertex_normals
1811 // Access: Private
1812 // Description: This is part of the implementation of
1813 // recompute_vertex_normals(). It walks the scene graph
1814 // at this group node and below, identifying all the
1815 // polygons and the vertices they have in common.
1816 ////////////////////////////////////////////////////////////////////
1817 void EggGroupNode::
1818 r_collect_vertex_normals(EggGroupNode::NVertexCollection &collection,
1819  double threshold, CoordinateSystem cs) {
1820  // We can do this ci/cnext iteration through the list as we modify
1821  // it, only because we know this works with an STL list type
1822  // container. If this were a vector or a set, this wouldn't
1823  // necessarily work.
1824 
1825  Children::iterator ci, cnext;
1826  ci = _children.begin();
1827  while (ci != _children.end()) {
1828  cnext = ci;
1829  ++cnext;
1830  EggNode *child = *ci;
1831 
1832  if (child->is_of_type(EggPolygon::get_class_type())) {
1833  EggPolygon *polygon = DCAST(EggPolygon, child);
1834  polygon->clear_normal();
1835 
1836  NVertexReference ref;
1837  ref._polygon = polygon;
1838  if (!polygon->calculate_normal(ref._normal, cs)) {
1839  // The polygon is degenerate. Remove it.
1840 
1841  prepare_remove_child(child);
1842  _children.erase(ci);
1843 
1844  } else {
1845  // Now add each vertex from the polygon separately to our
1846  // collection.
1847  size_t num_vertices = polygon->size();
1848  for (size_t i = 0; i < num_vertices; i++) {
1849  EggVertex *vertex = polygon->get_vertex(i);
1850  ref._vertex = i;
1851  collection[vertex->get_pos3()].push_back(ref);
1852  }
1853  }
1854 
1855  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
1856  EggGroupNode *group = DCAST(EggGroupNode, child);
1857 
1858  // We can't share vertices across an Instance node. Don't
1859  // even bother trying. Instead, just restart.
1860  if (group->is_under_instance()) {
1861  group->recompute_vertex_normals(threshold, cs);
1862  } else {
1863  group->r_collect_vertex_normals(collection, threshold, cs);
1864  }
1865  }
1866 
1867  ci = cnext;
1868  }
1869 }
1870 
1871 ////////////////////////////////////////////////////////////////////
1872 // Function: EggGroupNode::do_compute_vertex_normals
1873 // Access: Private
1874 // Description: This is part of the implementation of
1875 // recompute_vertex_normals(). It accepts a group of
1876 // polygons and their common normals, and computes the
1877 // same normal for all their shared vertices.
1878 ////////////////////////////////////////////////////////////////////
1879 void EggGroupNode::
1880 do_compute_vertex_normals(const NVertexGroup &group) {
1881  nassertv(!group.empty());
1882 
1883  // Determine the common normal. This is simply the average of all
1884  // the polygon normals that share this vertex.
1885  LNormald normal(0.0, 0.0, 0.0);
1886  NVertexGroup::const_iterator gi;
1887  for (gi = group.begin(); gi != group.end(); ++gi) {
1888  const NVertexReference &ref = (*gi);
1889  normal += ref._normal;
1890  }
1891 
1892  normal /= (double)group.size();
1893  normal.normalize();
1894 
1895  // Now we have the common normal; apply it to all the vertices.
1896 
1897  for (gi = group.begin(); gi != group.end(); ++gi) {
1898  const NVertexReference &ref = (*gi);
1899  EggVertex *vertex = ref._polygon->get_vertex(ref._vertex);
1900  EggVertexPool *pool = vertex->get_pool();
1901 
1902  EggVertex new_vertex(*vertex);
1903  new_vertex.set_normal(normal);
1904  EggVertex *unique = pool->create_unique_vertex(new_vertex);
1905  unique->copy_grefs_from(*vertex);
1906 
1907  ref._polygon->set_vertex(ref._vertex, unique);
1908  }
1909 }
1910 
1911 ////////////////////////////////////////////////////////////////////
1912 // Function: EggGroupNode::r_collect_tangent_binormal
1913 // Access: Private
1914 // Description: This is part of the implementation of
1915 // recompute_tangent_binormal(). It walks the scene
1916 // graph at this group node and below, identifying all
1917 // the polygons and the vertices they have in common.
1918 ////////////////////////////////////////////////////////////////////
1919 void EggGroupNode::
1920 r_collect_tangent_binormal(const GlobPattern &uv_name,
1921  EggGroupNode::TBNVertexCollection &collection) {
1922  Children::iterator ci;
1923  for (ci = _children.begin(); ci != _children.end(); ++ci) {
1924  EggNode *child = *ci;
1925 
1926  if (child->is_of_type(EggPolygon::get_class_type())) {
1927  EggPolygon *polygon = DCAST(EggPolygon, child);
1928 
1929  TBNVertexReference ref;
1930  ref._polygon = polygon;
1931 
1932  // Now add each vertex from the polygon separately to our
1933  // collection.
1934  size_t num_vertices = polygon->size();
1935  for (size_t i = 0; i < num_vertices; i++) {
1936  // We look at the triangle formed by each three consecutive
1937  // vertices to determine the s direction and t direction at
1938  // each vertex. v1 is the key vertex, the one at position i;
1939  // v2 is vertex i + 1, and v3 is vertex i - 1.
1940  EggVertex *v1 = polygon->get_vertex(i);
1941  EggVertex *v2 = polygon->get_vertex((i + 1) % num_vertices);
1942  EggVertex *v3 = polygon->get_vertex((i + num_vertices - 1) % num_vertices);
1943  if (v1->has_normal() || polygon->has_normal()) {
1944  // Go through all of the UV names on the vertex, looking for
1945  // one that matches the glob pattern.
1947  for (uvi = v1->uv_begin(); uvi != v1->uv_end(); ++uvi) {
1948  EggVertexUV *uv_obj = (*uvi);
1949  string name = uv_obj->get_name();
1950  if (uv_name.matches(name) &&
1951  v2->has_uv(name) && v3->has_uv(name)) {
1952  TBNVertexValue value;
1953  value._uv_name = name;
1954  value._pos = v1->get_pos3();
1955  if (v1->has_normal()) {
1956  value._normal = v1->get_normal();
1957  } else {
1958  value._normal = polygon->get_normal();
1959  }
1960  value._uv = v1->get_uv(name);
1961 
1962  // Compute the s direction and t direction for this vertex.
1963  LPoint3d p1 = v1->get_pos3();
1964  LPoint3d p2 = v2->get_pos3();
1965  LPoint3d p3 = v3->get_pos3();
1966 
1967  LTexCoordd w1 = v1->get_uv(name);
1968  LTexCoordd w2 = v2->get_uv(name);
1969  LTexCoordd w3 = v3->get_uv(name);
1970 
1971  // Check the facing of the texture; we will have to
1972  // split vertices whose UV's are mirrored along a seam.
1973  // The facing is determined by the winding order of the
1974  // texcoords on the polygon. A front-facing polygon
1975  // should not contribute to the tangent and binormal of
1976  // a back-facing polygon, and vice-versa.
1977  value._facing = is_right(w1 - w2, w3 - w1);
1978 
1979  double x1 = p2[0] - p1[0];
1980  double x2 = p3[0] - p1[0];
1981  double y1 = p2[1] - p1[1];
1982  double y2 = p3[1] - p1[1];
1983  double z1 = p2[2] - p1[2];
1984  double z2 = p3[2] - p1[2];
1985 
1986  double s1 = w2[0] - w1[0];
1987  double s2 = w3[0] - w1[0];
1988  double t1 = w2[1] - w1[1];
1989  double t2 = w3[1] - w1[1];
1990 
1991  double denom = (s1 * t2 - s2 * t1);
1992  if (denom == 0.0) {
1993  ref._sdir.set(0.0, 0.0, 0.0);
1994  ref._tdir.set(0.0, 0.0, 0.0);
1995  } else {
1996  double r = 1.0 / denom;
1997  ref._sdir.set((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
1998  (t2 * z1 - t1 * z2) * r);
1999  ref._tdir.set((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
2000  (s1 * z2 - s2 * z1) * r);
2001  }
2002 
2003  // Store the vertex referenced to the polygon.
2004  ref._vertex = i;
2005  collection[value].push_back(ref);
2006  }
2007  }
2008  }
2009  }
2010 
2011  } else if (child->is_of_type(EggGroupNode::get_class_type())) {
2012  EggGroupNode *group = DCAST(EggGroupNode, child);
2013 
2014  // We can't share vertices across an Instance node. Don't
2015  // even bother trying. Instead, just restart.
2016  if (group->is_under_instance()) {
2017  group->recompute_tangent_binormal(uv_name);
2018  } else {
2019  group->r_collect_tangent_binormal(uv_name, collection);
2020  }
2021  }
2022  }
2023 }
2024 
2025 ////////////////////////////////////////////////////////////////////
2026 // Function: EggGroupNode::do_compute_tangent_binormal
2027 // Access: Private
2028 // Description: This is part of the implementation of
2029 // recompute_tangent_binormal(). It accepts a group of
2030 // polygons and their common normals and UV's, and
2031 // computes the tangent and binormal for all their
2032 // shared vertices.
2033 ////////////////////////////////////////////////////////////////////
2034 void EggGroupNode::
2035 do_compute_tangent_binormal(const TBNVertexValue &value,
2036  const TBNVertexGroup &group) {
2037  nassertv(!group.empty());
2038 
2039  // Accumulate together all of the s vectors and t vectors computed
2040  // for the different vertices that are together here.
2041  LNormald sdir(0.0, 0.0, 0.0);
2042  LNormald tdir(0.0, 0.0, 0.0);
2043 
2044  TBNVertexGroup::const_iterator gi;
2045  for (gi = group.begin(); gi != group.end(); ++gi) {
2046  const TBNVertexReference &ref = (*gi);
2047  sdir += ref._sdir;
2048  tdir += ref._tdir;
2049  }
2050 
2051  // If sdir and/or tdir are zero, choose an arbitrary vector instead.
2052  // (This is really the only reason we normalize sdir and tdir,
2053  // though it also helps stabilize the math below in case the vectors
2054  // are very small but not quite zero.)
2055  if (!sdir.normalize()) {
2056  sdir.set(1.0, 0.0, 0.0);
2057  }
2058  if (!tdir.normalize()) {
2059  tdir = sdir.cross(LNormald(0.0, 0.0, -1.0));
2060  }
2061 
2062  LNormald tangent = (sdir - value._normal * value._normal.dot(sdir));
2063  tangent.normalize();
2064 
2065  LNormald binormal = cross(value._normal, tangent);
2066  if (dot(binormal, tdir) < 0.0f) {
2067  binormal = -binormal;
2068  }
2069  // Shouldn't need to normalize this, but we do just for good measure.
2070  binormal.normalize();
2071 
2072  // Now we have the common tangent and binormal; apply them to all
2073  // the vertices.
2074 
2075  for (gi = group.begin(); gi != group.end(); ++gi) {
2076  const TBNVertexReference &ref = (*gi);
2077  EggVertex *vertex = ref._polygon->get_vertex(ref._vertex);
2078  EggVertexPool *pool = vertex->get_pool();
2079 
2080  EggVertex new_vertex(*vertex);
2081  EggVertexUV *uv_obj = new_vertex.modify_uv_obj(value._uv_name);
2082  nassertv(uv_obj != (EggVertexUV *)NULL);
2083  uv_obj->set_tangent(tangent);
2084  uv_obj->set_binormal(binormal);
2085 
2086  EggVertex *unique = pool->create_unique_vertex(new_vertex);
2087  unique->copy_grefs_from(*vertex);
2088 
2089  ref._polygon->set_vertex(ref._vertex, unique);
2090  }
2091 }
bool empty() const
Returns true if the pool is empty.
A base class for any of a number of kinds of geometry primitives: polygons, point lights...
Definition: eggPrimitive.h:51
The set of UV&#39;s that may or may not be assigned to a vertex.
Definition: eggVertexUV.h:32
void strip_normals()
Removes all normals from primitives, and the vertices they reference, at this node and below...
bool matches(const string &candidate) const
Returns true if the candidate string matches the pattern, false otherwise.
Definition: globPattern.I:157
const Filename & get_filename() const
Returns a nonmodifiable reference to the filename.
void make_point_primitives()
Creates PointLight primitives to reference any otherwise unreferences vertices discovered in this gro...
virtual void write(ostream &out, int indent_level) const
Writes the group and all of its children to the indicated output stream in Egg format.
virtual void unify_attributes(Shading shading)
If the shading property is S_per_vertex, ensures that all vertices have a normal and a color...
static bool resolve_egg_filename(Filename &egg_filename, const DSearchPath &searchpath=DSearchPath())
Looks for the indicated filename, first along the indicated searchpath, and then along the model_path...
Definition: eggData.cxx:45
This is an iterator adaptor that converts any iterator that returns a pair (e.g.
This is our own Panda specialization on the default STL map.
Definition: pmap.h:52
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const string &default_extension=string()) const
Searches the given search path for the filename.
The base class for primitives such as triangle strips and triangle fans, which include several compon...
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:4716
virtual bool joint_has_primitives() const
Returns true if there are any primitives (e.g.
virtual void apply_first_attribute()
Sets the first vertex of the triangle (or each component) to the primitive normal and/or color...
The <CoordinateSystem> entry at the top of an egg file.
This is an egg node that contains a filename.
EggVertexPool * get_pool() const
Returns the vertex pool this vertex belongs in.
Definition: eggVertex.I:25
virtual void apply_last_attribute()
Sets the last vertex of the triangle (or each component) to the primitive normal and/or color...
virtual bool cleanup()
Cleans up modeling errors in whatever context this makes sense.
void unify_attributes(bool use_connected_shading, bool allow_per_primitive, bool recurse)
Applies per-vertex normal and color to all vertices, if they are in fact per-vertex (and different fo...
A base class for nodes in the hierarchy that are not leaf nodes.
Definition: eggGroupNode.h:51
This is a collection of materials by MRef name.
A hierarchy of directories and files that appears to be one continuous file system, even though the files may originate from several different sources that may not be related to the actual OS&#39;s file system.
int triangulate_polygons(int flags)
Replace all higher-order polygons at this point in the scene graph and below with triangles...
void get_connected_shading()
Queries the connected_shading information on all primitives at this node and below, to ensure that it has been completely filled in before we start mucking around with vertices.
void clear()
Removes all of the vertices from the primitive.
Definition: eggPrimitive.I:432
LTexCoordd get_uv() const
Returns the unnamed UV coordinate pair on the vertex.
Definition: eggVertex.I:222
Defines a texture map that may be applied to geometry.
Definition: eggTexture.h:33
void clear_connected_shading()
Resets the connected_shading information on all primitives at this node and below, so that it may be accurately rederived by the next call to get_connected_shading().
void recompute_polygon_normals(CoordinateSystem cs=CS_default)
Recomputes all the polygon normals for polygon geometry at this group node and below so that they acc...
void set_vertex(int index, EggVertex *vertex)
Replaces a particular vertex based on its index number in the list of vertices.
Definition: eggPrimitive.I:455
const EggAttributes * get_component(int i) const
Returns the attributes for the nth component triangle.
bool recompute_tangent_binormal_auto()
This function recomputes the tangent and binormal for any texture coordinate set that affects a norma...
bool add_material(EggMaterial *material)
Explicitly adds a new material to the collection.
bool test_ref_count_integrity() const
Does some easy checks to make sure that the reference count isn&#39;t completely bogus.
This is a two-component point in space.
Definition: lpoint2.h:424
This is a collection of textures by TRef name.
int get_depth() const
Returns the number of nodes above this node in the egg hierarchy.
Definition: eggNode.I:71
void apply_first_attribute(bool recurse)
Sets the first vertex of the triangle (or each component) to the primitive normal and/or color...
LVertexd get_pos3() const
Valid if get_num_dimensions() returns 3 or 4.
Definition: eggVertex.I:160
bool add_texture(EggTexture *texture)
Explicitly adds a new texture to the collection.
This is the primary interface into all the egg data, and the root of the egg file structure...
Definition: eggData.h:41
size_type size() const
Returns the number of vertices in the pool.
void set_auto_resolve_externals(bool resolve)
Indicates whether the EggData object will automatically resolve any external references when read() i...
Definition: eggData.I:70
A single point, or a collection of points as defined by a single <PointLight> entry.
Definition: eggPoint.h:27
void set_coordinate_system(CoordinateSystem coordsys)
Changes the coordinate system of the EggData.
Definition: eggData.cxx:279
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:39
static bool is_right(const LVector2d &v1, const LVector2d &v2)
Returns true if the 2-d v1 is to the right of v2.
Definition: eggGroupNode.I:22
void mesh(EggGroupNode *group, bool flat_shaded)
Accepts an EggGroupNode, which contains a set of EggPrimitives–typically, triangles and quads–as ch...
Definition: eggMesher.cxx:56
virtual string get_default_extension() const
Returns the default extension for this filename type.
bool normalize()
Normalizes the vector in place.
Definition: lvecBase3.h:2149
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
Definition: eggGroup.h:36
void set_alpha_filename(const Filename &filename)
Specifies a separate file that will be loaded in with the 1- or 3-component texture and applied as th...
Definition: eggTexture.I:820
const string & get_uv_name() const
Returns the texcoord name that has been specified for this texture, or the empty string if no texcoor...
Definition: eggTexture.I:705
virtual void reverse_vertex_ordering()
Reverses the ordering of the vertices in this primitive, if appropriate, in order to change the direc...
virtual void post_apply_flat_attribute()
Intended as a followup to apply_last_attribute(), this also sets an attribute on the first vertices o...
Collects together unrelated EggPrimitives, determines their edge connectivity, and generates a set of...
Definition: eggMesher.h:35
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:44
An instance of this class is written to the front of a Bam or Txo file to make the file a cached inst...
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal...
Definition: eggVertex.h:41
virtual bool has_primitives() const
Returns true if there are any primitives (e.g.
int rename_nodes(vector_string strip_prefix, bool recurse)
Rename by stripping out the prefix.
int remove_invalid_primitives(bool recurse)
Removes primitives at this level and below which appear to be degenerate; e.g.
bool load_externals(const DSearchPath &searchpath=DSearchPath())
Loads up all the egg files referenced by <File> entries within the egg structure, and inserts their c...
Definition: eggData.cxx:179
int remove_unused_vertices()
Removes all vertices from the pool that are not referenced by at least one primitive.
const Filename & get_alpha_filename() const
Returns the separate file assigned for the alpha channel.
Definition: eggTexture.I:858
void steal_children(EggGroupNode &other)
Moves all the children from the other node to this one.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
void mesh_triangles(int flags)
Combine triangles together into triangle strips, at this group and below.
bool read(Filename filename, string display_name=string())
Opens the indicated filename and reads the egg data contents from it.
Definition: eggData.cxx:71
int remove_unused_vertices(bool recurse)
Removes all vertices from VertexPools within this group or below that are not referenced by at least ...
void add_unused_vertices_to_prim(EggPrimitive *prim)
Adds all of the unused vertices in this vertex pool to the indicated primitive, in ascending order...
bool has_uv() const
Returns true if the vertex has an unnamed UV coordinate pair, false otherwise.
Definition: eggVertex.I:194
int get_num_components() const
Returns the number of individual component triangles within the composite.
void apply_last_attribute(bool recurse)
Sets the last vertex of the triangle (or each component) to the primitive normal and/or color...
EggNode * get_next_child()
Returns the next child in the group&#39;s list of children since the last call to get_first_child() or ge...
virtual bool is_joint() const
Returns true if this particular node represents a <Joint> entry or not.
Definition: eggNode.cxx:75
int find_used_textures(EggNode *node)
Walks the egg hierarchy beginning at the indicated node, looking for textures that are referenced by ...
string get_basename_wo_extension() const
Returns the basename part of the filename, without the file extension.
Definition: filename.I:460
virtual bool has_normals() const
Returns true if any of the primitives (e.g.
bool is_local() const
Returns true if the filename is local, e.g.
Definition: filename.I:664
A single polygon.
Definition: eggPolygon.h:26
void ref() const
Explicitly increments the reference count.
void rebuild_vertex_pools(EggVertexPools &vertex_pools, unsigned int max_vertices, bool recurse)
Copies vertices used by the primitives at this group node (and below, if recurse is true) into one or...
bool recompute_polygon_normal(CoordinateSystem cs=CS_default)
Recalculates the normal according to the order of the vertices, and sets it.
Definition: eggPolygon.I:54
EggVertex * find_matching_vertex(const EggVertex &copy)
If the EggVertexPool already has a vertex matching the indicated vertex, returns it; otherwise...
bool is_under_instance() const
Returns true if there is an <Instance> node somewhere in the egg tree at or above this node...
Definition: eggNode.I:84
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
Definition: lvector3.h:760
void replace(iterator position, PT(EggNode) x)
Replaces the node at the indicated position with the indicated node.
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
Definition: lpoint3.h:544
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
int rename_node(vector_string strip_prefix)
Rename by stripping out the prefix.
Definition: eggNode.cxx:37
void force_filenames(const Filename &directory)
Similar to resolve_filenames, but each non-absolute filename encountered is arbitrarily taken to be i...
const_uv_iterator uv_begin() const
Returns an iterator that allows walking through the complete set of named UV&#39;s on the vertex...
Definition: eggVertex.I:273
EggVertexUV * modify_uv_obj(const string &name)
Returns a modifiable pointer to the named EggVertexUV object, which defines both the UV coordinate pa...
Definition: eggVertex.cxx:321
A base class for things that may be directly added into the egg hierarchy.
Definition: eggNode.h:38
bool calculate_normal(LNormald &result, CoordinateSystem cs=CS_default) const
Calculates the true polygon normal–the vector pointing out of the front of the polygon–based on the...
Definition: eggPolygon.cxx:57
EggNode * get_first_child()
Returns the first child in the group&#39;s list of children, or NULL if the list of children is empty...
Defines a reference to another egg file which should be inserted at this point.
This class stores a list of directories that can be searched, in order, to locate a particular file...
Definition: dSearchPath.h:32
virtual Shading get_shading() const
Returns the shading properties apparent on this particular primitive.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:63
EggNode * find_child(const string &name) const
Returns the child of this node whose name is the indicated string, or NULL if there is no child of th...
void add_dependent_file(const Filename &pathname)
Adds the indicated file to the list of files that will be loaded to generate the data in this record...
void copy_grefs_from(const EggVertex &other)
Copies all the group references from the other vertex onto this one.
Definition: eggVertex.cxx:848
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
Shading get_connected_shading() const
Determines what sort of shading properties this primitive&#39;s connected neighbors have.
Definition: eggPrimitive.I:120
bool has_absolute_pathnames() const
Returns true if any nodes at this level and below include a reference to a file via an absolute pathn...
void set_component(int i, const EggAttributes *attrib)
Changes the attributes for the nth component triangle.
void post_apply_flat_attribute(bool recurse)
Intended as a followup to apply_last_attribute(), this also sets an attribute on the first vertices o...
void resolve_filenames(const DSearchPath &searchpath)
Walks the tree and attempts to resolve any filenames encountered.
EggVertex * create_unique_vertex(const EggVertex &copy)
Creates a new vertex in the pool that is a copy of the indicated one and returns it.
A collection of vertices.
Definition: eggVertexPool.h:46
EggVertex * add_vertex(EggVertex *vertex)
Adds the indicated vertex to the end of the primitive&#39;s list of vertices, and returns it...
void recompute_vertex_normals(double threshold, CoordinateSystem cs=CS_default)
Recomputes all the vertex normals for polygon geometry at this group node and below so that they accu...
EggVertex * get_vertex(int index) const
Returns a particular index based on its index number.
Definition: eggPrimitive.I:466
void reverse_vertex_ordering()
Reverses the vertex ordering of all polygons defined at this node and below.
void clear_connected_shading()
Resets the connected_shading member in this primitive, so that get_connected_shading() will recompute...
Definition: eggPrimitive.I:98
const_uv_iterator uv_end() const
Returns an iterator that allows walking through the complete set of named UV&#39;s on the vertex...
Definition: eggVertex.I:301
This class can be used to test for string matches against standard Unix-shell filename globbing conve...
Definition: globPattern.h:37
bool recompute_tangent_binormal(const GlobPattern &uv_name)
This function recomputes the tangent and binormal for the named texture coordinate set for all vertic...
bool has_alpha_filename() const
Returns true if a separate file for the alpha component has been applied, false otherwise.
Definition: eggTexture.I:846