Panda3D
eggVertexPool.cxx
1 // Filename: eggVertexPool.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 "eggVertexPool.h"
16 #include "eggPrimitive.h"
17 #include "eggUtilities.h"
18 #include <iterator>
19 
20 #include "indent.h"
21 
22 #include <iterator>
23 
24 TypeHandle EggVertexPool::_type_handle;
25 
26 ////////////////////////////////////////////////////////////////////
27 // Function: EggVertexPool::Constructor
28 // Access: Public
29 // Description:
30 ////////////////////////////////////////////////////////////////////
31 EggVertexPool::
32 EggVertexPool(const string &name) : EggNode(name) {
33  _highest_index = -1;
34 }
35 
36 ////////////////////////////////////////////////////////////////////
37 // Function: EggVertexPool::Copy Constructor
38 // Access: Public
39 // Description: Copying a vertex pool is of questionable value, since
40 // it will copy all of the vertices and assign new
41 // pointers to them all. There will be no polygons
42 // referring to the new vertices.
43 ////////////////////////////////////////////////////////////////////
44 EggVertexPool::
45 EggVertexPool(const EggVertexPool &copy) : EggNode(copy) {
46  iterator i;
47  for (i = copy.begin(); i != copy.end(); ++i) {
48  add_vertex(new EggVertex(*(*i)), (*i)->get_index());
49  }
50 }
51 
52 
53 ////////////////////////////////////////////////////////////////////
54 // Function: EggVertexPool::Destructor
55 // Access: Public
56 // Description:
57 ////////////////////////////////////////////////////////////////////
58 EggVertexPool::
59 ~EggVertexPool() {
60  // Remove all vertices from the pool when it destructs.
61 
62  // Sanity check.
63  nassertv(_index_vertices.size() == _unique_vertices.size());
64 
65  IndexVertices::iterator ivi;
66  for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
67  int index = (*ivi).first;
68  EggVertex *vertex = (*ivi).second;
69 
70  // Sanity checks on our internal data structures.
71  nassertv(vertex->_pool == this);
72  nassertv(vertex->get_index() == index);
73 
74  vertex->_pool = NULL;
75  vertex->_index = -1;
76  }
77 
78  _index_vertices.clear();
79  _unique_vertices.clear();
80 }
81 
82 ////////////////////////////////////////////////////////////////////
83 // Function: EggVertexPool::has_forward_vertices
84 // Access: Published
85 // Description: Returns true if any vertices in the pool are
86 // undefined forward-reference vertices, false if all
87 // vertices are defined.
88 ////////////////////////////////////////////////////////////////////
89 bool EggVertexPool::
91  IndexVertices::const_iterator ivi;
92  for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
93  EggVertex *vertex = (*ivi).second;
94  if (vertex->is_forward_reference()) {
95  return true;
96  }
97  }
98 
99  return false;
100 }
101 
102 ////////////////////////////////////////////////////////////////////
103 // Function: EggVertexPool::has_defined_vertices
104 // Access: Published
105 // Description: Returns true if any vertices in the pool are
106 // fully defined vertices, false if all vertices are
107 // forward references.
108 ////////////////////////////////////////////////////////////////////
109 bool EggVertexPool::
111  IndexVertices::const_iterator ivi;
112  for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
113  EggVertex *vertex = (*ivi).second;
114  if (!vertex->is_forward_reference()) {
115  return true;
116  }
117  }
118 
119  return false;
120 }
121 
122 ////////////////////////////////////////////////////////////////////
123 // Function: EggVertexPool::get_vertex
124 // Access: Public
125 // Description: Returns the vertex in the pool with the indicated
126 // index number, or NULL if no vertices have that index
127 // number.
128 ////////////////////////////////////////////////////////////////////
130 get_vertex(int index) const {
131  IndexVertices::const_iterator ivi = _index_vertices.find(index);
132 
133  if (ivi == _index_vertices.end()) {
134  return NULL;
135  } else {
136  EggVertex *vertex = (*ivi).second;
137  if (vertex->is_forward_reference()) {
138  return NULL;
139  }
140  return vertex;
141  }
142 }
143 
144 ////////////////////////////////////////////////////////////////////
145 // Function: EggVertexPool::get_forward_vertex
146 // Access: Public
147 // Description: Returns the vertex in the pool with the indicated
148 // index number. If there is not a vertex in the pool
149 // with the indicated index number, creates a special
150 // forward-reference EggVertex that has no data, on the
151 // assumption that the vertex pool has not yet been
152 // fully read and more data will be available later.
153 ////////////////////////////////////////////////////////////////////
155 get_forward_vertex(int index) {
156  nassertr(index >= 0, NULL);
157 
158  IndexVertices::const_iterator ivi = _index_vertices.find(index);
159 
160  if (ivi == _index_vertices.end()) {
161  PT(EggVertex) forward = new EggVertex;
162  forward->_forward_reference = true;
163  return add_vertex(forward, index);
164  } else {
165  return (*ivi).second;
166  }
167 }
168 
169 ////////////////////////////////////////////////////////////////////
170 // Function: EggVertexPool::get_highest_index
171 // Access: Public
172 // Description: Returns the highest index number used by any vertex
173 // in the pool (except forward references). Returns -1
174 // if the pool is empty.
175 ////////////////////////////////////////////////////////////////////
176 int EggVertexPool::
178  return _highest_index;
179 }
180 
181 ////////////////////////////////////////////////////////////////////
182 // Function: EggVertexPool::set_highest_index
183 // Access: Public
184 // Description: Artificially changes the "highest index number", so
185 // that a newly created vertex will begin at this number
186 // plus 1. This can be used to default a vertex pool to
187 // start counting at 1 (or any other index number),
188 // instead of the default of 0. Use with caution.
189 ////////////////////////////////////////////////////////////////////
190 void EggVertexPool::
191 set_highest_index(int highest_index) {
192  _highest_index = highest_index;
193 }
194 
195 ////////////////////////////////////////////////////////////////////
196 // Function: EggVertexPool::get_num_dimensions
197 // Access: Public
198 // Description: Returns the maximum number of dimensions used by any
199 // vertex in the pool.
200 ////////////////////////////////////////////////////////////////////
201 int EggVertexPool::
203  int num_dimensions = 0;
204 
205  IndexVertices::const_iterator ivi;
206  for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
207  EggVertex *vertex = (*ivi).second;
208  num_dimensions = max(num_dimensions, vertex->get_num_dimensions());
209  }
210 
211  return num_dimensions;
212 }
213 
214 ////////////////////////////////////////////////////////////////////
215 // Function: EggVertexPool::has_normals
216 // Access: Public
217 // Description: Returns true if any vertex in the pool has a normal
218 // defined, false if none of them do.
219 ////////////////////////////////////////////////////////////////////
220 bool EggVertexPool::
221 has_normals() const {
222  IndexVertices::const_iterator ivi;
223  for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
224  EggVertex *vertex = (*ivi).second;
225  if (vertex->has_normal()) {
226  return true;
227  }
228  }
229 
230  return false;
231 }
232 
233 ////////////////////////////////////////////////////////////////////
234 // Function: EggVertexPool::has_colors
235 // Access: Public
236 // Description: Returns true if any vertex in the pool has a color
237 // defined, false if none of them do.
238 ////////////////////////////////////////////////////////////////////
239 bool EggVertexPool::
240 has_colors() const {
241  IndexVertices::const_iterator ivi;
242  for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
243  EggVertex *vertex = (*ivi).second;
244  if (vertex->has_color()) {
245  return true;
246  }
247  }
248 
249  return false;
250 }
251 
252 ////////////////////////////////////////////////////////////////////
253 // Function: EggVertexPool::has_nonwhite_colors
254 // Access: Public
255 // Description: Returns true if any vertex in the pool has a color
256 // defined other than white, false if no vertices have
257 // colors, or if all colors are white.
258 ////////////////////////////////////////////////////////////////////
259 bool EggVertexPool::
261  IndexVertices::const_iterator ivi;
262  for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
263  EggVertex *vertex = (*ivi).second;
264  if (vertex->has_color() &&
265  (vertex->get_color() != LColor(1.0, 1.0, 1.0, 1.0) ||
266  !vertex->_drgbas.empty())) {
267  return true;
268  }
269  }
270 
271  return false;
272 }
273 
274 ////////////////////////////////////////////////////////////////////
275 // Function: EggVertexPool::check_overall_color
276 // Access: Public
277 // Description: Scans the vertex pool for different colors on
278 // different vertices. If all vertices are the same
279 // color, sets has_overall_color to true and fills the
280 // color into overall_color. If no vertices have any
281 // color, set has_overall_color to true and fills white
282 // into overall_color. If at least two vertices have
283 // different colors, sets has_overall_color to false.
284 ////////////////////////////////////////////////////////////////////
285 void EggVertexPool::
286 check_overall_color(bool &has_overall_color, LColor &overall_color) const {
287  if (empty()) {
288  has_overall_color = true;
289  overall_color.set(1.0f, 1.0f, 1.0f, 1.0f);
290  return;
291  }
292 
293  IndexVertices::const_iterator ivi;
294  ivi = _index_vertices.begin();
295  EggVertex *vertex = (*ivi).second;
296  overall_color = vertex->get_color();
297 
298  ++ivi;
299  while (ivi != _index_vertices.end()) {
300  vertex = (*ivi).second;
301  if (!vertex->get_color().almost_equal(overall_color)) {
302  has_overall_color = false;
303  return;
304  }
305  ++ivi;
306  }
307 
308  has_overall_color = true;
309 }
310 
311 ////////////////////////////////////////////////////////////////////
312 // Function: EggVertexPool::has_uvs
313 // Access: Public
314 // Description: Returns true if any vertex in the pool has a uv
315 // defined, false if none of them do.
316 ////////////////////////////////////////////////////////////////////
317 bool EggVertexPool::
318 has_uvs() const {
319  IndexVertices::const_iterator ivi;
320  for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
321  EggVertex *vertex = (*ivi).second;
322  if (vertex->has_uv()) {
323  return true;
324  }
325  }
326 
327  return false;
328 }
329 
330 ////////////////////////////////////////////////////////////////////
331 // Function: EggVertexPool::has_aux
332 // Access: Public
333 // Description: Returns true if any vertex in the pool has
334 // auxiliary data defined, false if none of them do.
335 ////////////////////////////////////////////////////////////////////
336 bool EggVertexPool::
337 has_aux() const {
338  IndexVertices::const_iterator ivi;
339  for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
340  EggVertex *vertex = (*ivi).second;
341  if (vertex->has_aux()) {
342  return true;
343  }
344  }
345 
346  return false;
347 }
348 
349 ////////////////////////////////////////////////////////////////////
350 // Function: EggVertexPool::get_uv_names
351 // Access: Public
352 // Description: Returns the list of UV names that are defined by any
353 // vertices in the pool, as well as the subset of UV
354 // names that actually define 3-d texture coordinates
355 // ("uvw_names"). Also returns the subset of UV/UVW
356 // names that define a tangent and binormal. It is the
357 // user's responsibility to clear both vectors before
358 // calling this method.
359 ////////////////////////////////////////////////////////////////////
360 void EggVertexPool::
361 get_uv_names(vector_string &uv_names, vector_string &uvw_names,
362  vector_string &tbn_names) const {
363  pset<string> uv_names_set, uvw_names_set, tbn_names_set;
364  IndexVertices::const_iterator ivi;
365  for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
366  EggVertex *vertex = (*ivi).second;
368  for (uvi = vertex->uv_begin(); uvi != vertex->uv_end(); ++uvi) {
369  EggVertexUV *uv_obj = (*uvi);
370  uv_names_set.insert(uv_obj->get_name());
371  if (uv_obj->has_w()) {
372  uvw_names_set.insert(uv_obj->get_name());
373  }
374  if (uv_obj->has_tangent() && uv_obj->has_binormal()) {
375  tbn_names_set.insert(uv_obj->get_name());
376  }
377  }
378  }
379 
381  for (si = uv_names_set.begin(); si != uv_names_set.end(); ++si) {
382  uv_names.push_back(*si);
383  }
384  for (si = uvw_names_set.begin(); si != uvw_names_set.end(); ++si) {
385  uvw_names.push_back(*si);
386  }
387  for (si = tbn_names_set.begin(); si != tbn_names_set.end(); ++si) {
388  tbn_names.push_back(*si);
389  }
390 }
391 
392 ////////////////////////////////////////////////////////////////////
393 // Function: EggVertexPool::get_aux_names
394 // Access: Public
395 // Description: Returns the list of auxiliary data names that are
396 // defined by any vertices in the pool.
397 ////////////////////////////////////////////////////////////////////
398 void EggVertexPool::
399 get_aux_names(vector_string &aux_names) const {
400  pset<string> aux_names_set;
401  IndexVertices::const_iterator ivi;
402  for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
403  EggVertex *vertex = (*ivi).second;
405  for (uvi = vertex->aux_begin(); uvi != vertex->aux_end(); ++uvi) {
406  EggVertexAux *aux_obj = (*uvi);
407  aux_names_set.insert(aux_obj->get_name());
408  }
409  }
410 
412  for (si = aux_names_set.begin(); si != aux_names_set.end(); ++si) {
413  aux_names.push_back(*si);
414  }
415 }
416 
417 ////////////////////////////////////////////////////////////////////
418 // Function: EggVertexPool::begin()
419 // Access: Public
420 // Description: Returns an iterator that can be used to traverse
421 // through all the vertices in the pool.
422 ////////////////////////////////////////////////////////////////////
424 begin() const {
425  nassertr(_index_vertices.size() == _unique_vertices.size(),
426  iterator(_index_vertices.begin()));
427  return iterator(_index_vertices.begin());
428 }
429 
430 ////////////////////////////////////////////////////////////////////
431 // Function: EggVertexPool::end()
432 // Access: Public
433 // Description: Returns an iterator that can be used to traverse
434 // through all the vertices in the pool.
435 ////////////////////////////////////////////////////////////////////
437 end() const {
438  return iterator(_index_vertices.end());
439 }
440 
441 ////////////////////////////////////////////////////////////////////
442 // Function: EggVertexPool::empty()
443 // Access: Public
444 // Description: Returns true if the pool is empty.
445 ////////////////////////////////////////////////////////////////////
446 bool EggVertexPool::
447 empty() const {
448  return _index_vertices.empty();
449 }
450 
451 ////////////////////////////////////////////////////////////////////
452 // Function: EggVertexPool::size()
453 // Access: Public
454 // Description: Returns the number of vertices in the pool.
455 ////////////////////////////////////////////////////////////////////
456 EggVertexPool::size_type EggVertexPool::
457 size() const {
458  nassertr(_index_vertices.size() == _unique_vertices.size(), 0);
459  return _index_vertices.size();
460 }
461 
462 ////////////////////////////////////////////////////////////////////
463 // Function: EggVertexPool::add_vertex
464 // Access: Public
465 // Description: Adds the indicated vertex to the pool. It is an
466 // error if the vertex is already a member of this or
467 // any other pool. The vertex must have been allocated
468 // from the free store; its pointer will now be owned by
469 // the vertex pool. If the index number is supplied,
470 // tries to assign that index number; it is an error if
471 // the index number is already in use.
472 //
473 // It is possible that a forward reference to this
474 // vertex was requested in the past; if so, the data
475 // from the supplied vertex is copied onto the forward
476 // reference, which becomes the actual vertex. In this
477 // case, a different pointer is saved (and returned)
478 // than the one actually passed in. In the usual case,
479 // however, the vertex pointer passed in is the one that
480 // is saved in the vertex pool and returned from this
481 // method.
482 ////////////////////////////////////////////////////////////////////
484 add_vertex(EggVertex *vertex, int index) {
485  // Save a pointer to the vertex.
486  PT(EggVertex) vertex_keep = vertex;
487 
488  // Don't try to add a vertex while it still belongs to another pool.
489  nassertr(vertex->_pool == NULL, NULL);
490 
491  if (index == -1) {
492  index = get_highest_index() + 1;
493  }
494  // Always supply an index number >= 0.
495  nassertr(index >= 0, NULL);
496 
497  // Check for a forward reference.
498  IndexVertices::const_iterator ivi = _index_vertices.find(index);
499 
500  if (ivi != _index_vertices.end()) {
501  EggVertex *orig_vertex = (*ivi).second;
502  if (orig_vertex->is_forward_reference() &&
503  !vertex->is_forward_reference()) {
504  (*orig_vertex) = (*vertex);
505  orig_vertex->_forward_reference = false;
506  _highest_index = max(_highest_index, index);
507  return orig_vertex;
508  }
509 
510  // Oops, you duplicated a vertex index.
511  nassertr(false, NULL);
512  }
513 
514  _unique_vertices.insert(vertex);
515  _index_vertices[index] = vertex;
516 
517  if (!vertex->is_forward_reference()) {
518  _highest_index = max(_highest_index, index);
519  }
520 
521  vertex->_pool = this;
522  vertex->_index = index;
523 
524  return vertex;
525 }
526 
527 
528 ////////////////////////////////////////////////////////////////////
529 // Function: EggVertexPool::create_unique_vertex
530 // Access: Public
531 // Description: Creates a new vertex in the pool that is a copy of
532 // the indicated one and returns it. If there is
533 // already a vertex in the pool like the indicated one,
534 // simply returns that one.
535 ////////////////////////////////////////////////////////////////////
538  UniqueVertices::iterator uvi;
539  uvi = _unique_vertices.find((EggVertex *)&copy);
540 
541  if (uvi != _unique_vertices.end()) {
542  // There was already such a vertex. Return it.
543  return (*uvi);
544  }
545 
546  // Create a new vertex.
547  return add_vertex(new EggVertex(copy));
548 }
549 
550 ////////////////////////////////////////////////////////////////////
551 // Function: EggVertexPool::find_matching_vertex
552 // Access: Public
553 // Description: If the EggVertexPool already has a vertex matching
554 // the indicated vertex, returns it; otherwise, returns
555 // NULL. This is similar to create_unique_vertex()
556 // except that a new vertex is never created.
557 ////////////////////////////////////////////////////////////////////
560  UniqueVertices::iterator uvi;
561  uvi = _unique_vertices.find((EggVertex *)&copy);
562 
563  if (uvi != _unique_vertices.end()) {
564  // There was already such a vertex. Return it.
565  return (*uvi);
566  }
567 
568  // No matching vertex.
569  return NULL;
570 }
571 
572 
573 ////////////////////////////////////////////////////////////////////
574 // Function: EggVertexPool::remove_vertex
575 // Access: Public
576 // Description: Removes the vertex from the pool. It is an error if
577 // the vertex is not already a member of the pool.
578 ////////////////////////////////////////////////////////////////////
579 void EggVertexPool::
581  // Make sure the vertex is already a member of this pool.
582  nassertv(vertex->_pool == this);
583 
584  // Sanity check. Is the vertex actually in the pool?
585  nassertv(get_vertex(vertex->_index) == vertex);
586 
587  // Removing the vertex from the indexed list is simple.
588  _index_vertices.erase(vertex->_index);
589 
590  if (_highest_index == vertex->_index) {
591  // Find the new highest vertex index.
592  if (_index_vertices.empty()) {
593  _highest_index = -1;
594  } else {
595  IndexVertices::reverse_iterator ivi = _index_vertices.rbegin();
596  while (ivi != _index_vertices.rend() &&
597  (*ivi).second->is_forward_reference()) {
598  ++ivi;
599  }
600  if (ivi != _index_vertices.rend()) {
601  _highest_index = (*ivi).first;
602  } else {
603  _highest_index = -1;
604  }
605  }
606  }
607 
608  // Removing the vertex from the unique list is a bit trickier--there
609  // might be several other vertices that are considered identical to
610  // this one, and so we have to walk through all the identical
611  // vertices until we find the right one.
612  UniqueVertices::iterator uvi;
613  uvi = _unique_vertices.find(vertex);
614 
615  // Sanity check. Is the vertex actually in the pool?
616  nassertv(uvi != _unique_vertices.end());
617 
618  while ((*uvi) != vertex) {
619  ++uvi;
620  // Sanity check. Is the vertex actually in the pool?
621  nassertv(uvi != _unique_vertices.end());
622  }
623 
624  _unique_vertices.erase(uvi);
625 
626  vertex->_pool = NULL;
627 }
628 
629 ////////////////////////////////////////////////////////////////////
630 // Function: EggVertexPool::remove_unused_vertices
631 // Access: Public
632 // Description: Removes all vertices from the pool that are not
633 // referenced by at least one primitive. Also collapses
634 // together equivalent vertices, and renumbers all
635 // vertices after the operation so their indices are
636 // consecutive, beginning at zero. Returns the number
637 // of vertices removed.
638 ////////////////////////////////////////////////////////////////////
639 int EggVertexPool::
641  int num_removed = 0;
642 
643  UniqueVertices new_unique_vertices;
644  IndexVertices new_index_vertices;
645 
646  IndexVertices::const_iterator ivi;
647  for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
648  EggVertex *vertex = (*ivi).second;
649  if (vertex->pref_size() == 0) {
650  // This vertex is not used. Don't add it to the new lists.
651  vertex->clear_grefs();
652  vertex->_pool = NULL;
653  num_removed++;
654 
655  } else {
656  // The vertex *is* used somewhere. Is it identical to an
657  // existing vertex?
658  UniqueVertices::iterator uvi;
659  uvi = new_unique_vertices.find(vertex);
660  if (uvi != new_unique_vertices.end()) {
661  // Yes, there's already another vertex just like this one.
662  // Redirect all the primitives currently referencing this
663  // vertex to reference the other one instead.
664  EggVertex *orig_vertex = (*uvi);
665 
666  EggVertex::PrimitiveRef pref = vertex->_pref;
667  EggVertex::PrimitiveRef::iterator pi;
668  for (pi = pref.begin(); pi != pref.end(); ++pi) {
669  EggPrimitive *prim = (*pi);
670  EggPrimitive::iterator pvi = prim->find(vertex);
671  nassertr(pvi != prim->end(), 0);
672  prim->replace(pvi, orig_vertex);
673  }
674  vertex->test_pref_integrity();
675  orig_vertex->test_pref_integrity();
676  nassertr(vertex->pref_size() == 0, 0);
677  vertex->clear_grefs();
678  vertex->_pool = NULL;
679  num_removed++;
680 
681  } else {
682  // It's a unique vertex. Renumber it and add it to the new
683  // lists.
684  vertex->_index = new_index_vertices.size();
685  new_index_vertices.insert(IndexVertices::value_type(vertex->_index, vertex));
686  new_unique_vertices.insert(vertex);
687  }
688  }
689  }
690 
691  // All done. Lose the old lists.
692  _unique_vertices.swap(new_unique_vertices);
693  _index_vertices.swap(new_index_vertices);
694  _highest_index = (int)_index_vertices.size() - 1;
695 
696  nassertr(_index_vertices.size() == _unique_vertices.size(), num_removed);
697 
698  return num_removed;
699 }
700 
701 ////////////////////////////////////////////////////////////////////
702 // Function: EggVertexPool::add_unused_vertices_to_prim
703 // Access: Public
704 // Description: Adds all of the unused vertices in this vertex pool
705 // to the indicated primitive, in ascending order.
706 ////////////////////////////////////////////////////////////////////
707 void EggVertexPool::
709  IndexVertices::iterator ivi;
710  for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
711  EggVertex *vertex = (*ivi).second;
712  if (vertex->pref_size() == 0) {
713  prim->add_vertex(vertex);
714  }
715  }
716 }
717 
718 // A function object for split_vertex(), used in transform(), below.
720 public:
721  int operator () (const EggPrimitive *prim) const {
722  return (prim->is_local_coord() ? 1 : 0);
723  }
724 };
725 
726 ////////////////////////////////////////////////////////////////////
727 // Function: EggVertexPool::transform
728 // Access: Public
729 // Description: Applies the indicated transformation matrix to all
730 // the vertices. However, vertices that are attached to
731 // primitives that believe their vertices are in a local
732 // coordinate system are transformed only by the scale
733 // and rotation component. If a vertex happens to be
734 // attached both to a local and a global primitive, and
735 // the transformation includes a translation component,
736 // the vertex will be split.
737 ////////////////////////////////////////////////////////////////////
738 void EggVertexPool::
739 transform(const LMatrix4d &mat) {
740  LVector3d translation = mat.get_row3(3);
741 
742  if (translation == LVector3d(0.0, 0.0, 0.0)) {
743  // If the matrix does not have a translation component, we can
744  // treat the local and global vertices the same. This makes
745  // things much easier.
746  iterator i;
747  for (i = begin(); i != end(); ++i) {
748  EggVertex *vert = *i;
749  vert->transform(mat);
750  }
751 
752  } else {
753  // The matrix does have a translation component. That means we
754  // have to treat the global and local vertices differently.
755  // Yucky.
756 
757  // First, transform the global vertices. Get a copy of the list
758  // of vertices in this pool. We must have a copy because we might
759  // be modifying the list as we traverse it.
760 
761  typedef pvector<EggVertex *> Verts;
762  Verts verts;
763  verts.reserve(size());
764  copy(begin(), end(), back_inserter(verts));
765 
766  Verts::const_iterator vi;
767  for (vi = verts.begin(); vi != verts.end(); ++vi) {
768  EggVertex *vert = *vi;
769  int num_local_coord = vert->get_num_local_coord();
770  int num_global_coord = vert->get_num_global_coord();
771 
772  if (num_global_coord != 0) {
773  // This vertex will be transformed.
774  if (num_local_coord != 0) {
775  // It also needs to be split! Yuck.
776  split_vertex(vert, IsLocalVertexSplitter());
777  }
778 
779  vert->transform(mat);
780  }
781  }
782 
783  // Now transform the local vertices. We can walk through the list
784  // directly now, because we won't be modifying the list this time.
785  LMatrix4d local_mat = mat;
786  local_mat.set_row(3, LVector3d(0.0, 0.0, 0.0));
787 
788  iterator i;
789  for (i = begin(); i != end(); ++i) {
790  EggVertex *vert = *i;
791  if (vert->get_num_local_coord() != 0) {
792 
793  // This should be guaranteed by the vertex-splitting logic
794  // above.
795  nassertv(vert->get_num_global_coord() == 0);
796  vert->transform(local_mat);
797  }
798  }
799  }
800 }
801 
802 
803 // A function object for sort_by_external_index(), below.
805 public:
806  bool operator () (EggVertex *a, EggVertex *b) const {
807  int ai = a->get_external_index();
808  int bi = b->get_external_index();
809  if (ai != bi) {
810  return ai < bi;
811  }
812  return a->get_index() < b->get_index();
813  }
814 };
815 
816 ////////////////////////////////////////////////////////////////////
817 // Function: EggVertexPool::sort_by_external_index
818 // Access: Published
819 // Description: Re-orders (and re-numbers) the vertices in this
820 // vertex pool so that they appear in increasing order
821 // by the optional external_index that has been assigned
822 // to each vertex.
823 ////////////////////////////////////////////////////////////////////
824 void EggVertexPool::
826  // Copy the vertices into a vector for sorting.
827  typedef pvector<EggVertex *> SortedVertices;
828  SortedVertices sorted_vertices;
829  sorted_vertices.reserve(size());
830  iterator i;
831  for (i = begin(); i != end(); ++i) {
832  sorted_vertices.push_back(*i);
833  }
834 
835  ::sort(sorted_vertices.begin(), sorted_vertices.end(), SortByExternalIndex());
836 
837  // Now reassign the indices, and copy them into a new index map.
838  IndexVertices new_index_vertices;
839  int vi;
840  for (vi = 0; vi < (int)sorted_vertices.size(); ++vi) {
841  EggVertex *vertex = sorted_vertices[vi];
842  vertex->_index = vi;
843  new_index_vertices[vi] = vertex;
844  }
845 
846  // Finally, assign the new index map.
847  _index_vertices.swap(new_index_vertices);
848 }
849 
850 ////////////////////////////////////////////////////////////////////
851 // Function: EggVertexPool::write
852 // Access: Public
853 // Description: Writes the vertex pool to the indicated output stream
854 // in Egg format.
855 ////////////////////////////////////////////////////////////////////
856 void EggVertexPool::
857 write(ostream &out, int indent_level) const {
858  write_header(out, indent_level, "<VertexPool>");
859 
860  iterator i;
861  for (i = begin(); i != end(); ++i) {
862  (*i)->write(out, indent_level+2);
863  }
864 
865  indent(out, indent_level)
866  << "}\n";
867 }
868 
869 
870 ////////////////////////////////////////////////////////////////////
871 // Function: EggVertexPool::r_transform
872 // Access: Protected, Virtual
873 // Description: This is called from within the egg code by
874 // transform(). It applies a transformation matrix
875 // to the current node in some sensible way, then
876 // continues down the tree.
877 //
878 // The first matrix is the transformation to apply; the
879 // second is its inverse. The third parameter is the
880 // coordinate system we are changing to, or CS_default
881 // if we are not changing coordinate systems.
882 ////////////////////////////////////////////////////////////////////
883 void EggVertexPool::
884 r_transform(const LMatrix4d &mat, const LMatrix4d &, CoordinateSystem) {
885 }
886 
887 ////////////////////////////////////////////////////////////////////
888 // Function: EggVertexPool::r_transform_vertices
889 // Access: Protected, Virtual
890 // Description: This is called from within the egg code by
891 // transform_vertices_only()(). It applies a
892 // transformation matrix to the current node in some
893 // sensible way (if the current node is a vertex pool
894 // with vertices), then continues down the tree.
895 ////////////////////////////////////////////////////////////////////
896 void EggVertexPool::
897 r_transform_vertices(const LMatrix4d &mat) {
898  transform(mat);
899 }
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
bool has_uvs() const
Returns true if any vertex in the pool has a uv defined, false if none of them do.
This is an iterator adaptor that converts any iterator that returns a pair (e.g.
PrimitiveRef::size_type pref_size() const
Returns the number of elements between pref_begin() and pref_end().
Definition: eggVertex.cxx:930
void set_highest_index(int highest_index)
Artificially changes the "highest index number", so that a newly created vertex will begin at this nu...
int get_num_dimensions() const
Returns the number of dimensions the vertex uses.
Definition: eggVertex.I:122
int get_num_dimensions() const
Returns the maximum number of dimensions used by any vertex in the pool.
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:4716
EggVertex * add_vertex(EggVertex *vertex, int index=-1)
Adds the indicated vertex to the pool.
bool has_aux() const
Returns true if the vertex has any auxiliary data, false otherwise.
Definition: eggVertex.I:205
EggVertex * get_vertex(int index) const
Returns the vertex in the pool with the indicated index number, or NULL if no vertices have that inde...
EggVertex * get_forward_vertex(int index)
Returns the vertex in the pool with the indicated index number.
void check_overall_color(bool &has_overall_color, LColor &overall_color) const
Scans the vertex pool for different colors on different vertices.
const_aux_iterator aux_end() const
Returns an iterator that allows walking through the complete set of auxiliary data on the vertex...
Definition: eggVertex.I:315
void clear_grefs()
Removes all group references from the vertex, so that it is not assigned to any group.
Definition: eggVertex.cxx:875
LColor get_color() const
Returns the color set on this particular attribute.
size_type size() const
Returns the number of vertices in the pool.
bool has_normals() const
Returns true if any vertex in the pool has a normal defined, false if none of them do...
iterator end() const
Returns an iterator that can be used to traverse through all the vertices in the pool.
void set_row(int row, const LVecBase4d &v)
Replaces the indicated row of the matrix.
Definition: lmatrix.h:5452
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:39
iterator begin() const
Returns an iterator that can be used to traverse through all the vertices in the pool.
bool has_aux() const
Returns true if any vertex in the pool has auxiliary data defined, false if none of them do...
int get_index() const
Returns the index number of the vertex within its pool.
Definition: eggVertex.I:346
int get_highest_index() const
Returns the highest index number used by any vertex in the pool (except forward references).
bool has_w() const
Returns true if the texture coordinate has a third, w component, false if it is just a normal 2-d tex...
Definition: eggVertexUV.I:63
void get_uv_names(vector_string &uv_names, vector_string &uvw_names, vector_string &tbn_names) const
Returns the list of UV names that are defined by any vertices in the pool, as well as the subset of U...
bool is_local_coord() const
Returns true if this node&#39;s vertices are not in the global coordinate space.
Definition: eggNode.I:109
bool has_defined_vertices() const
Returns true if any vertices in the pool are fully defined vertices, false if all vertices are forwar...
bool has_colors() const
Returns true if any vertex in the pool has a color defined, false if none of them do...
void transform(const LMatrix4d &mat)
Applies the indicated transformation matrix to the vertex.
Definition: eggVertex.cxx:755
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal...
Definition: eggVertex.h:41
bool almost_equal(const LVecBase4f &other, float threshold) const
Returns true if two vectors are memberwise equal within a specified tolerance.
Definition: lvecBase4.h:1339
int remove_unused_vertices()
Removes all vertices from the pool that are not referenced by at least one primitive.
iterator find(EggVertex *vertex)
Returns the iterator pointing to the indicated vertex, or end() if the vertex is not part of the prim...
LVecBase3d get_row3(int row) const
Retrieves the row column of the matrix as a 3-component vector, ignoring the last column...
Definition: lmatrix.h:5577
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
void write_header(ostream &out, int indent_level, const char *egg_keyword) const
Writes the first line of the egg object, e.g.
The set of named auxiliary data that may or may not be assigned to a vertex.
Definition: eggVertexAux.h:33
const_aux_iterator aux_begin() const
Returns an iterator that allows walking through the complete set of auxiliary data on the vertex...
Definition: eggVertex.I:287
This is the base class for all three-component vectors and points.
Definition: lvecBase4.h:111
EggVertex * find_matching_vertex(const EggVertex &copy)
If the EggVertexPool already has a vertex matching the indicated vertex, returns it; otherwise...
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
Definition: lvector3.h:760
bool is_forward_reference() const
Returns true if the vertex is a forward reference to some vertex that hasn&#39;t been defined yet...
Definition: eggVertex.I:43
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
A base class for things that may be directly added into the egg hierarchy.
Definition: eggNode.h:38
void sort_by_external_index()
Re-orders (and re-numbers) the vertices in this vertex pool so that they appear in increasing order b...
void write(ostream &out, int indent_level) const
Writes the vertex pool to the indicated output stream in Egg format.
int get_external_index() const
Returns the number set by set_external_index().
Definition: eggVertex.I:376
void replace(iterator position, EggVertex *vertex)
Replaces the vertex at the indicated position with the indicated vertex.
Definition: eggPrimitive.I:413
int get_num_global_coord() const
Returns the number of primitives that own this vertex whose vertices are interpreted in the global co...
Definition: eggVertex.cxx:734
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
int get_num_local_coord() const
Returns the number of primitives that own this vertex whose vertices are interpreted to be in a local...
Definition: eggVertex.cxx:713
void get_aux_names(vector_string &aux_names) const
Returns the list of auxiliary data names that are defined by any vertices in the pool.
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 transform(const LMatrix4d &mat)
Applies the indicated transformation matrix to all the vertices.
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
bool has_forward_vertices() const
Returns true if any vertices in the pool are undefined forward-reference vertices, false if all vertices are defined.
bool has_nonwhite_colors() const
Returns true if any vertex in the pool has a color defined other than white, false if no vertices hav...
void remove_vertex(EggVertex *vertex)
Removes the vertex from the pool.