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 */
80 bool EggVertexPool::
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 */
97 bool EggVertexPool::
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 */
114 EggVertex *EggVertexPool::
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 */
136 EggVertex *EggVertexPool::
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 */
155 int EggVertexPool::
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 */
166 void EggVertexPool::
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 */
174 int EggVertexPool::
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 */
191 bool EggVertexPool::
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 */
208 bool EggVertexPool::
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 */
225 bool EggVertexPool::
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 */
247 void EggVertexPool::
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 */
277 bool EggVertexPool::
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 */
294 bool EggVertexPool::
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 */
314 void EggVertexPool::
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;
321 EggVertex::const_uv_iterator uvi;
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
334 pset<string>::const_iterator si;
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 */
350 void EggVertexPool::
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;
356 EggVertex::const_aux_iterator uvi;
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
363 pset<string>::const_iterator si;
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 */
373 EggVertexPool::iterator EggVertexPool::
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 */
384 EggVertexPool::iterator EggVertexPool::
385 end() const {
386 return iterator(_index_vertices.end());
387 }
388
389 /**
390 * Returns true if the pool is empty.
391 */
392 bool EggVertexPool::
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 */
420 EggVertex *EggVertexPool::
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 */
471 EggVertex *EggVertexPool::
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 */
490 EggVertex *EggVertexPool::
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 */
509 void EggVertexPool::
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 */
565 int EggVertexPool::
566 remove_unused_vertices() {
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 */
630 void EggVertexPool::
631 add_unused_vertices_to_prim(EggPrimitive *prim) {
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 */
657 void EggVertexPool::
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 */
745 void EggVertexPool::
746 sort_by_external_index() {
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 */
774 void EggVertexPool::
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 }
EggAttributes::get_color
LColor get_color() const
Returns the color set on this particular attribute.
Definition: eggAttributes.I:91
EggNamedObject::write_header
void write_header(std::ostream &out, int indent_level, const char *egg_keyword) const
Writes the first line of the egg object, e.g.
Definition: eggNamedObject.cxx:39
EggNode
A base class for things that may be directly added into the egg hierarchy.
Definition: eggNode.h:36
EggNode::is_local_coord
bool is_local_coord() const
Returns true if this node's vertices are not in the global coordinate space.
Definition: eggNode.I:87
EggPrimitive
A base class for any of a number of kinds of geometry primitives: polygons, point lights,...
Definition: eggPrimitive.h:49
EggPrimitive::add_vertex
EggVertex * add_vertex(EggVertex *vertex)
Adds the indicated vertex to the end of the primitive's list of vertices, and returns it.
Definition: eggPrimitive.cxx:654
EggPrimitive::replace
void replace(iterator position, EggVertex *vertex)
Replaces the vertex at the indicated position with the indicated vertex.
Definition: eggPrimitive.I:335
EggPrimitive::find
iterator find(EggVertex *vertex)
Returns the iterator pointing to the indicated vertex, or end() if the vertex is not part of the prim...
Definition: eggPrimitive.cxx:643
EggVertexAux
The set of named auxiliary data that may or may not be assigned to a vertex.
Definition: eggVertexAux.h:30
EggVertexPool
A collection of vertices.
Definition: eggVertexPool.h:41
EggVertexPool::has_colors
bool has_colors() const
Returns true if any vertex in the pool has a color defined, false if none of them do.
Definition: eggVertexPool.cxx:209
EggVertexPool::remove_vertex
void remove_vertex(EggVertex *vertex)
Removes the vertex from the pool.
Definition: eggVertexPool.cxx:510
EggVertexPool::has_normals
bool has_normals() const
Returns true if any vertex in the pool has a normal defined, false if none of them do.
Definition: eggVertexPool.cxx:192
EggVertexPool::remove_unused_vertices
int remove_unused_vertices()
Removes all vertices from the pool that are not referenced by at least one primitive.
Definition: eggVertexPool.cxx:566
EggVertexPool::get_highest_index
int get_highest_index() const
Returns the highest index number used by any vertex in the pool (except forward references).
Definition: eggVertexPool.cxx:156
EggVertexPool::find_matching_vertex
EggVertex * find_matching_vertex(const EggVertex &copy)
If the EggVertexPool already has a vertex matching the indicated vertex, returns it; otherwise,...
Definition: eggVertexPool.cxx:491
EggVertexPool::has_defined_vertices
bool has_defined_vertices() const
Returns true if any vertices in the pool are fully defined vertices, false if all vertices are forwar...
Definition: eggVertexPool.cxx:98
EggVertexPool::sort_by_external_index
void sort_by_external_index()
Re-orders (and re-numbers) the vertices in this vertex pool so that they appear in increasing order b...
Definition: eggVertexPool.cxx:746
EggVertexPool::has_aux
bool has_aux() const
Returns true if any vertex in the pool has auxiliary data defined, false if none of them do.
Definition: eggVertexPool.cxx:295
EggVertexPool::add_unused_vertices_to_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.
Definition: eggVertexPool.cxx:631
EggVertexPool::size
size_type size() const
Returns the number of vertices in the pool.
Definition: eggVertexPool.cxx:401
EggVertexPool::has_nonwhite_colors
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...
Definition: eggVertexPool.cxx:226
EggVertexPool::has_uvs
bool has_uvs() const
Returns true if any vertex in the pool has a uv defined, false if none of them do.
Definition: eggVertexPool.cxx:278
EggVertexPool::end
iterator end() const
Returns an iterator that can be used to traverse through all the vertices in the pool.
Definition: eggVertexPool.cxx:385
EggVertexPool::check_overall_color
void check_overall_color(bool &has_overall_color, LColor &overall_color) const
Scans the vertex pool for different colors on different vertices.
Definition: eggVertexPool.cxx:248
EggVertexPool::get_aux_names
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.
Definition: eggVertexPool.cxx:351
EggVertexPool::get_uv_names
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...
Definition: eggVertexPool.cxx:315
EggVertexPool::get_vertex
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...
Definition: eggVertexPool.cxx:115
EggVertexPool::get_num_dimensions
int get_num_dimensions() const
Returns the maximum number of dimensions used by any vertex in the pool.
Definition: eggVertexPool.cxx:175
EggVertexPool::begin
iterator begin() const
Returns an iterator that can be used to traverse through all the vertices in the pool.
Definition: eggVertexPool.cxx:374
EggVertexPool::set_highest_index
void set_highest_index(int highest_index)
Artificially changes the "highest index number", so that a newly created vertex will begin at this nu...
Definition: eggVertexPool.cxx:167
EggVertexPool::add_vertex
EggVertex * add_vertex(EggVertex *vertex, int index=-1)
Adds the indicated vertex to the pool.
Definition: eggVertexPool.cxx:421
EggVertexPool::create_unique_vertex
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.
Definition: eggVertexPool.cxx:472
EggVertexPool::has_forward_vertices
bool has_forward_vertices() const
Returns true if any vertices in the pool are undefined forward-reference vertices,...
Definition: eggVertexPool.cxx:81
EggVertexPool::empty
bool empty() const
Returns true if the pool is empty.
Definition: eggVertexPool.cxx:393
EggVertexPool::transform
void transform(const LMatrix4d &mat)
Applies the indicated transformation matrix to all the vertices.
Definition: eggVertexPool.cxx:658
EggVertexPool::get_forward_vertex
EggVertex * get_forward_vertex(int index)
Returns the vertex in the pool with the indicated index number.
Definition: eggVertexPool.cxx:137
EggVertexPool::write
void write(std::ostream &out, int indent_level) const
Writes the vertex pool to the indicated output stream in Egg format.
Definition: eggVertexPool.cxx:775
EggVertexUV
The set of UV's that may or may not be assigned to a vertex.
Definition: eggVertexUV.h:29
EggVertexUV::has_w
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
EggVertex
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal.
Definition: eggVertex.h:39
EggVertex::has_uv
bool has_uv() const
Returns true if the vertex has an unnamed UV coordinate pair, false otherwise.
Definition: eggVertex.I:158
EggVertex::clear_grefs
void clear_grefs()
Removes all group references from the vertex, so that it is not assigned to any group.
Definition: eggVertex.cxx:772
EggVertex::get_index
int get_index() const
Returns the index number of the vertex within its pool.
Definition: eggVertex.I:277
EggVertex::has_aux
bool has_aux() const
Returns true if the vertex has any auxiliary data, false otherwise.
Definition: eggVertex.I:166
EggVertex::transform
void transform(const LMatrix4d &mat)
Applies the indicated transformation matrix to the vertex.
Definition: eggVertex.cxx:672
EggVertex::get_external_index
int get_external_index() const
Returns the number set by set_external_index().
Definition: eggVertex.I:300
EggVertex::is_forward_reference
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
EggVertex::aux_begin
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
EggVertex::uv_end
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
EggVertex::pref_size
PrimitiveRef::size_type pref_size() const
Returns the number of elements between pref_begin() and pref_end().
Definition: eggVertex.cxx:815
EggVertex::get_num_local_coord
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
EggVertex::uv_begin
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
EggVertex::get_num_dimensions
int get_num_dimensions() const
Returns the number of dimensions the vertex uses.
Definition: eggVertex.I:99
EggVertex::aux_end
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
EggVertex::get_num_global_coord
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
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
pmap< int, PT_EggVertex >
pmultiset< EggVertex *, UniqueEggVertices >
pset
This is our own Panda specialization on the default STL set.
Definition: pset.h:49
pvector
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
second_of_pair_iterator
This is an iterator adaptor that converts any iterator that returns a pair (e.g.
Definition: iterator_types.h:43
eggPrimitive.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggUtilities.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
split_vertex
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
eggVertexPool.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
indent
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition: indent.cxx:20
indent.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.