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