Panda3D
 All Classes Functions Variables Enumerations
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 }
A base class for any of a number of kinds of geometry primitives: polygons, point lights...
Definition: eggPrimitive.h:51
bool almost_equal(const LVecBase4f &other, float threshold) const
Returns true if two vectors are memberwise equal within a specified tolerance.
Definition: lvecBase4.h:1323
The set of UV&#39;s that may or may not be assigned to a vertex.
Definition: eggVertexUV.h:32
This is an iterator adaptor that converts any iterator that returns a pair (e.g.
void set_highest_index(int highest_index)
Artificially changes the &quot;highest index number&quot;, so that a newly created vertex will begin at this nu...
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...
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:4716
LColor get_color() const
Returns the color set on this particular attribute.
void write_header(ostream &out, int indent_level, const char *egg_keyword) const
Writes the first line of the egg object, e.g.
bool is_local_coord() const
Returns true if this node&#39;s vertices are not in the global coordinate space.
Definition: eggNode.I:109
EggVertex * add_vertex(EggVertex *vertex, int index=-1)
Adds the indicated vertex to the pool.
bool empty() const
Returns true if the pool is empty.
bool has_uv() const
Returns true if the vertex has an unnamed UV coordinate pair, false otherwise.
Definition: eggVertex.I:194
EggVertex * get_forward_vertex(int index)
Returns the vertex in the pool with the indicated index number.
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
bool has_colors() const
Returns true if any vertex in the pool has a color defined, false if none of them do...
void clear_grefs()
Removes all group references from the vertex, so that it is not assigned to any group.
Definition: eggVertex.cxx:875
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 set_row(int row, const LVecBase4d &v)
Replaces the indicated row of the matrix.
Definition: lmatrix.h:5452
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
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
bool has_aux() const
Returns true if the vertex has any auxiliary data, false otherwise.
Definition: eggVertex.I:205
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 is our own Panda specialization on the default STL vector.
Definition: pvector.h:39
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
bool has_aux() const
Returns true if any vertex in the pool has auxiliary data defined, false if none of them do...
bool has_forward_vertices() const
Returns true if any vertices in the pool are undefined forward-reference vertices, false if all vertices are defined.
iterator end() const
Returns an iterator that can be used to traverse through all the vertices in the pool.
PrimitiveRef::size_type pref_size() const
Returns the number of elements between pref_begin() and pref_end().
Definition: eggVertex.cxx:930
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 has_normals() const
Returns true if any vertex in the pool has a normal defined, false if none of them do...
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
bool has_uvs() const
Returns true if any vertex in the pool has a uv defined, false if none of them do.
int remove_unused_vertices()
Removes all vertices from the pool that are not referenced by at least one primitive.
int get_highest_index() const
Returns the highest index number used by any vertex in the pool (except forward references).
iterator find(EggVertex *vertex)
Returns the iterator pointing to the indicated vertex, or end() if the vertex is not part of the prim...
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...
The set of named auxiliary data that may or may not be assigned to a vertex.
Definition: eggVertexAux.h:33
bool has_defined_vertices() const
Returns true if any vertices in the pool are fully defined vertices, false if all vertices are forwar...
size_type size() const
Returns the number of vertices in the pool.
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:746
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
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...
int get_num_dimensions() const
Returns the number of dimensions the vertex uses.
Definition: eggVertex.I:122
void replace(iterator position, EggVertex *vertex)
Replaces the vertex at the indicated position with the indicated vertex.
Definition: eggPrimitive.I:413
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.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
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
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...
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
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 check_overall_color(bool &has_overall_color, LColor &overall_color) const
Scans the vertex pool for different colors on different vertices.
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...
iterator begin() const
Returns an iterator that can be used to traverse through all the vertices in the pool.
void transform(const LMatrix4d &mat)
Applies the indicated transformation matrix to all the vertices.
void remove_vertex(EggVertex *vertex)
Removes the vertex from the pool.
int get_index() const
Returns the index number of the vertex within its pool.
Definition: eggVertex.I:346
int get_num_dimensions() const
Returns the maximum number of dimensions used by any vertex in the pool.