Panda3D
Loading...
Searching...
No Matches
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
23using std::string;
24
25TypeHandle EggVertexPool::_type_handle;
26
27/**
28 *
29 */
30EggVertexPool::
31EggVertexPool(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 */
40EggVertexPool::
41EggVertexPool(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 */
52EggVertexPool::
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 */
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 */
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 */
115get_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 */
137get_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 */
156get_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 */
167set_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 */
175get_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 */
192has_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 */
209has_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 */
226has_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 */
248check_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 */
278has_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 */
295has_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 */
315get_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 */
351get_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 */
374begin() 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 */
385end() const {
386 return iterator(_index_vertices.end());
387}
388
389/**
390 * Returns true if the pool is empty.
391 */
393empty() const {
394 return _index_vertices.empty();
395}
396
397/**
398 * Returns the number of vertices in the pool.
399 */
400EggVertexPool::size_type EggVertexPool::
401size() 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 */
421add_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 */
472create_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 */
491find_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 */
510remove_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.
642class IsLocalVertexSplitter {
643public:
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 */
658transform(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.
728class SortByExternalIndex {
729public:
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 */
775write(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 */
797void EggVertexPool::
798r_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 */
807void EggVertexPool::
808r_transform_vertices(const LMatrix4d &mat) {
809 transform(mat);
810}
LColor get_color() const
Returns the color set on this particular attribute.
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,...
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.
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.
A collection of vertices.
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.
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.
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().
int get_num_local_coord() const
Returns the number of primitives that own this vertex whose vertices are interpreted to be in a local...
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...
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 ...
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.