Panda3D
Loading...
Searching...
No Matches
eggVertex.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 eggVertex.cxx
10 * @author drose
11 * @date 1999-01-16
12 */
13
14#include "eggVertex.h"
15#include "eggVertexPool.h"
16#include "eggParameters.h"
17#include "eggGroup.h"
18#include "eggMiscFuncs.h"
19#include "eggPrimitive.h"
20
21#include "indent.h"
22#include "luse.h"
23#include "lmatrix.h"
24#include "pandabase.h"
25
26#include <math.h>
27#include <algorithm>
28
29using std::ostream;
30using std::string;
31
32TypeHandle EggVertex::_type_handle;
33
34
35/**
36 *
37 */
38EggVertex::
39EggVertex() {
40 _pool = nullptr;
41 _forward_reference = false;
42 _index = -1;
43 _external_index = -1;
44 _external_index2 = -1;
45 set_pos(LPoint3d(0.0, 0.0, 0.0));
46 test_pref_integrity();
47 test_gref_integrity();
48}
49
50/**
51 * Copies all properties of the vertex except its vertex pool, index number,
52 * and group membership.
53 */
54EggVertex::
55EggVertex(const EggVertex &copy)
56 : EggObject(copy), EggAttributes(copy),
57 _dxyzs(copy._dxyzs),
58 _external_index(copy._external_index),
59 _external_index2(copy._external_index2),
60 _pos(copy._pos),
61 _num_dimensions(copy._num_dimensions),
62 _uv_map(copy._uv_map),
63 _aux_map(copy._aux_map)
64{
65 _pool = nullptr;
66 _forward_reference = false;
67 _index = -1;
68 test_pref_integrity();
69 test_gref_integrity();
70}
71
72
73/**
74 * Copies all properties of the vertex except its vertex pool, index number,
75 * and group membership.
76 */
78operator = (const EggVertex &copy) {
79 EggObject::operator = (copy);
80 EggAttributes::operator = (copy);
81 _dxyzs = copy._dxyzs;
82 _external_index = copy._external_index;
83 _external_index2 = copy._external_index2;
84 _pos = copy._pos;
85 _num_dimensions = copy._num_dimensions;
86 _uv_map = copy._uv_map;
87 _aux_map = copy._aux_map;
88
89 test_pref_integrity();
90 test_gref_integrity();
91
92 return *this;
93}
94
95/**
96 *
97 */
98EggVertex::
99~EggVertex() {
100 // We should never destruct a vertex while it still thinks it belongs to a
101 // VertexPool. If we do, we've probably lost a reference count somewhere.
102 nassertv(_pool == nullptr);
103
104 // Also, a vertex shouldn't be destructed while it's being referenced by a
105 // group or a primitive, for the same reason.
106 nassertv(_gref.empty());
107 nassertv(_pref.empty());
108}
109
110/**
111 * Returns true if the vertex has the named UV coordinate pair, and the named
112 * UV coordinate pair is 2-d, false otherwise.
113 */
115has_uv(const string &name) const {
116 UVMap::const_iterator ui = _uv_map.find(EggVertexUV::filter_name(name));
117 if (ui != _uv_map.end()) {
118 EggVertexUV *uv_obj = (*ui).second;
119 return !uv_obj->has_w();
120 }
121 return false;
122}
123
124/**
125 * Returns true if the vertex has the named UV coordinate triple, and the
126 * named UV coordinate triple is 3-d, false otherwise.
127 */
129has_uvw(const string &name) const {
130 UVMap::const_iterator ui = _uv_map.find(EggVertexUV::filter_name(name));
131 if (ui != _uv_map.end()) {
132 EggVertexUV *uv_obj = (*ui).second;
133 return uv_obj->has_w();
134 }
135 return false;
136}
137
138/**
139 * Returns true if the vertex has the named auxiliary data quadruple.
140 */
142has_aux(const string &name) const {
143 AuxMap::const_iterator xi = _aux_map.find(name);
144 return (xi != _aux_map.end());
145}
146
147/**
148 * Returns the named UV coordinate pair on the vertex. It is an error to call
149 * this if has_uv(name) returned false.
150 */
151LTexCoordd EggVertex::
152get_uv(const string &name) const {
153 UVMap::const_iterator ui = _uv_map.find(EggVertexUV::filter_name(name));
154 nassertr(ui != _uv_map.end(), LTexCoordd::zero());
155 return (*ui).second->get_uv();
156}
157
158/**
159 * Returns the named UV coordinate triple on the vertex. It is an error to
160 * call this if has_uvw(name) returned false.
161 */
162const LTexCoord3d &EggVertex::
163get_uvw(const string &name) const {
164 UVMap::const_iterator ui = _uv_map.find(EggVertexUV::filter_name(name));
165 nassertr(ui != _uv_map.end(), LTexCoord3d::zero());
166 return (*ui).second->get_uvw();
167}
168
169/**
170 * Returns the named auxiliary data quadruple on the vertex. It is an error
171 * to call this if has_aux(name) returned false.
172 */
173const LVecBase4d &EggVertex::
174get_aux(const string &name) const {
175 AuxMap::const_iterator xi = _aux_map.find(name);
176 nassertr(xi != _aux_map.end(), LVecBase4d::zero());
177 return (*xi).second->get_aux();
178}
179
180/**
181 * Sets the indicated UV coordinate pair on the vertex. This replaces any UV
182 * coordinate pair with the same name already on the vertex, but preserves UV
183 * morphs.
184 */
186set_uv(const string &name, const LTexCoordd &uv) {
187 string fname = EggVertexUV::filter_name(name);
188 PT(EggVertexUV) &uv_obj = _uv_map[fname];
189
190 if (uv_obj.is_null()) {
191 uv_obj = new EggVertexUV(fname, uv);
192 } else {
193 uv_obj = new EggVertexUV(*uv_obj);
194 uv_obj->set_uv(uv);
195 }
196
197 nassertv(get_uv(fname) == uv);
198}
199
200/**
201 * Sets the indicated UV coordinate triple on the vertex. This replaces any
202 * UV coordinate pair or triple with the same name already on the vertex, but
203 * preserves UV morphs.
204 */
206set_uvw(const string &name, const LTexCoord3d &uvw) {
207 string fname = EggVertexUV::filter_name(name);
208 PT(EggVertexUV) &uv_obj = _uv_map[fname];
209
210 if (uv_obj.is_null()) {
211 uv_obj = new EggVertexUV(fname, uvw);
212 } else {
213 uv_obj = new EggVertexUV(*uv_obj);
214 uv_obj->set_uvw(uvw);
215 }
216
217 nassertv(get_uvw(fname) == uvw);
218}
219
220/**
221 * Sets the indicated auxiliary data quadruple on the vertex. This replaces
222 * any auxiliary data with the same name already on the vertex.
223 */
225set_aux(const string &name, const LVecBase4d &aux) {
226 PT(EggVertexAux) &aux_obj = _aux_map[name];
227
228 if (aux_obj.is_null()) {
229 aux_obj = new EggVertexAux(name, aux);
230 } else {
231 aux_obj = new EggVertexAux(*aux_obj);
232 aux_obj->set_aux(aux);
233 }
234
235 nassertv(get_aux(name) == aux);
236}
237
238/**
239 * Returns the named EggVertexUV object, which defines both the UV coordinate
240 * pair for this name and the UV morphs. This object might be shared between
241 * multiple vertices. You should not attempt to modify this object; instead,
242 * call modify_uv_object to return a modifiable pointer.
243 */
245get_uv_obj(const string &name) const {
246 UVMap::const_iterator ui = _uv_map.find(EggVertexUV::filter_name(name));
247 if (ui != _uv_map.end()) {
248 return (*ui).second;
249 }
250 return nullptr;
251}
252
253/**
254 * Returns the named EggVertexAux object, which defines the auxiliary data for
255 * this name. This object might be shared between multiple vertices. You
256 * should not attempt to modify this object; instead, call modify_aux_object
257 * to return a modifiable pointer.
258 */
260get_aux_obj(const string &name) const {
261 AuxMap::const_iterator xi = _aux_map.find(name);
262 if (xi != _aux_map.end()) {
263 return (*xi).second;
264 }
265 return nullptr;
266}
267
268/**
269 * Returns a modifiable pointer to the named EggVertexUV object, which defines
270 * both the UV coordinate pair for this name and the UV morphs. Returns NULL
271 * if there is no such named UV object.
272 */
274modify_uv_obj(const string &name) {
275 UVMap::iterator ui = _uv_map.find(EggVertexUV::filter_name(name));
276 if (ui != _uv_map.end()) {
277 if ((*ui).second->get_ref_count() != 1) {
278 // Copy on write.
279 (*ui).second = new EggVertexUV(*(*ui).second);
280 }
281 return (*ui).second;
282 }
283
284 return nullptr;
285}
286
287/**
288 * Returns a modifiable pointer to the named EggVertexAux object, which
289 * defines the auxiliary data for this name. Returns NULL if there is no such
290 * named UV object.
291 */
293modify_aux_obj(const string &name) {
294 AuxMap::iterator xi = _aux_map.find(name);
295 if (xi != _aux_map.end()) {
296 if ((*xi).second->get_ref_count() != 1) {
297 // Copy on write.
298 (*xi).second = new EggVertexAux(*(*xi).second);
299 }
300 return (*xi).second;
301 }
302
303 return nullptr;
304}
305
306/**
307 * Sets the indicated EggVertexUV on the vertex. This replaces any UV
308 * coordinate pair with the same name already on the vertex, including UV
309 * morphs.
310 */
313 _uv_map[uv->get_name()] = uv;
314}
315
316/**
317 * Sets the indicated EggVertexAux on the vertex. This replaces any auxiliary
318 * data with the same name already on the vertex.
319 */
322 _aux_map[aux->get_name()] = aux;
323}
324
325/**
326 * Removes the named UV coordinate pair from the vertex, along with any UV
327 * morphs.
328 */
330clear_uv(const string &name) {
331 _uv_map.erase(EggVertexUV::filter_name(name));
332}
333
334/**
335 * Removes the named auxiliary data from the vertex.
336 */
338clear_aux(const string &name) {
339 _aux_map.erase(name);
340}
341
342/**
343 * Creates a new vertex that lies in between the two given vertices. The
344 * attributes for the UV sets they have in common are averaged.
345 *
346 * Both vertices need to be either in no pool, or in the same pool. In the
347 * latter case, the new vertex will be placed in that pool.
348 */
349PT(EggVertex) EggVertex::
350make_average(const EggVertex *first, const EggVertex *second) {
351 PT(EggVertexPool) pool = first->get_pool();
352 nassertr(pool == second->get_pool(), nullptr);
353
354 // If both vertices are in a pool, the new vertex will be part of the pool
355 // as well.
356 PT(EggVertex) middle;
357 if (pool == nullptr) {
358 middle = new EggVertex;
359 } else {
360 middle = pool->make_new_vertex();
361 }
362
363 middle->set_pos4((first->get_pos4() + second->get_pos4()) / 2);
364
365 if (first->has_normal() && second->has_normal()) {
366 LNormald normal = (first->get_normal() + second->get_normal()) / 2;
367 normal.normalize();
368 middle->set_normal(normal);
369 }
370 if (first->has_color() && second->has_color()) {
371 middle->set_color((first->get_color() + second->get_color()) / 2);
372 }
373
374 // Average out the EggVertexUV objects, but only for the UV sets that they
375 // have in common.
376 const_uv_iterator it;
377 for (it = first->uv_begin(); it != first->uv_end(); ++it) {
378 const EggVertexUV *first_uv = it->second;
379 const EggVertexUV *second_uv = second->get_uv_obj(it->first);
380
381 if (first_uv != nullptr && second_uv != nullptr) {
382 middle->set_uv_obj(EggVertexUV::make_average(first_uv, second_uv));
383 }
384 }
385
386 // Same for EggVertexAux.
387 const_aux_iterator ai;
388 for (ai = first->aux_begin(); ai != first->aux_end(); ++ai) {
389 const EggVertexAux *first_aux = ai->second;
390 const EggVertexAux *second_aux = second->get_aux_obj(ai->first);
391
392 if (first_aux != nullptr && second_aux != nullptr) {
393 middle->set_aux_obj(EggVertexAux::make_average(first_aux, second_aux));
394 }
395 }
396
397 // Now process the morph targets.
398 EggMorphVertexList::const_iterator vi, vi2;
399 for (vi = first->_dxyzs.begin(); vi != first->_dxyzs.end(); ++vi) {
400 for (vi2 = second->_dxyzs.begin(); vi2 != second->_dxyzs.end(); ++vi2) {
401 if (vi->get_name() == vi2->get_name()) {
402 middle->_dxyzs.insert(EggMorphVertex(vi->get_name(),
403 (vi->get_offset() + vi2->get_offset()) / 2));
404 break;
405 }
406 }
407 }
408
409 EggMorphNormalList::const_iterator ni, ni2;
410 for (ni = first->_dxyzs.begin(); ni != first->_dxyzs.end(); ++ni) {
411 for (ni2 = second->_dxyzs.begin(); ni2 != second->_dxyzs.end(); ++ni2) {
412 if (ni->get_name() == ni2->get_name()) {
413 middle->_dnormals.insert(EggMorphNormal(ni->get_name(),
414 (ni->get_offset() + ni2->get_offset()) / 2));
415 break;
416 }
417 }
418 }
419
420 EggMorphColorList::const_iterator ci, ci2;
421 for (ci = first->_drgbas.begin(); ci != first->_drgbas.end(); ++ci) {
422 for (ci2 = second->_drgbas.begin(); ci2 != second->_drgbas.end(); ++ci2) {
423 if (ci->get_name() == ci2->get_name()) {
424 middle->_drgbas.insert(EggMorphColor(ci->get_name(),
425 (ci->get_offset() + ci2->get_offset()) / 2));
426 break;
427 }
428 }
429 }
430
431 // Now merge the vertex memberships.
432 GroupRef::iterator gi;
433 for (gi = first->_gref.begin(); gi != first->_gref.end(); ++gi) {
434 EggGroup *group = *gi;
435 if (second->_gref.count(group)) {
436 group->set_vertex_membership(middle,
437 (group->get_vertex_membership(first) +
438 group->get_vertex_membership(second)) / 2.);
439 } else {
440 // Hmm, unfortunate, only one of the vertices is member of this group,
441 // so we can't make an average. We'll have to assign the only group
442 // membership we have.
443 group->set_vertex_membership(middle, group->get_vertex_membership(first));
444 }
445 }
446 // Also assign memberships to the grefs in the second vertex that aren't
447 // part of the first vertex.
448 for (gi = second->_gref.begin(); gi != second->_gref.end(); ++gi) {
449 EggGroup *group = *gi;
450 if (second->_gref.count(group) == 0) {
451 group->set_vertex_membership(middle, group->get_vertex_membership(second));
452 }
453 }
454
455 return middle;
456}
457
458/**
459 * A temporary class used in EggVertex::write(), below, to hold the groups
460 * that reference each vertex prior to outputting them as a formatted list.
461 */
462class GroupRefEntry {
463public:
464 GroupRefEntry(EggGroup *group, double membership)
465 : _group(group), _membership(membership) { }
466
467 bool operator < (const GroupRefEntry &other) const {
468 return _group->get_name() < other._group->get_name();
469 }
470 void output(ostream &out) const {
471 out << _group->get_name() << ":" << _membership;
472 }
473
474 EggGroup *_group;
475 double _membership;
476};
477
478INLINE ostream &operator << (ostream &out, const GroupRefEntry &gre) {
479 gre.output(out);
480 return out;
481}
482
483/**
484 * Writes the vertex to the indicated output stream in Egg format.
485 */
487write(ostream &out, int indent_level) const {
488 test_pref_integrity();
489 test_gref_integrity();
490
491 indent(out, indent_level)
492 << "<Vertex> " << _index << " {\n";
493
494 // Now output the position. This might have any number of dimensions up to
495 // 4.
496 indent(out, indent_level+1);
497 for (int i = 0; i < _num_dimensions; i++) {
498 out << " " << _pos[i];
499 }
500 out << "\n";
501
502 UVMap::const_iterator ui;
503 for (ui = _uv_map.begin(); ui != _uv_map.end(); ++ui) {
504 (*ui).second->write(out, indent_level + 2);
505 }
506
507 AuxMap::const_iterator xi;
508 for (xi = _aux_map.begin(); xi != _aux_map.end(); ++xi) {
509 (*xi).second->write(out, indent_level + 2);
510 }
511
512 EggAttributes::write(out, indent_level+2);
513
514 _dxyzs.write(out, indent_level + 2, "<Dxyz>", 3);
515
516 // If the vertex is referenced by one or more groups, write that as a
517 // helpful comment.
518 if (!_gref.empty()) {
519 // We need to build a list of group entries.
521
522 GroupRef::const_iterator gi;
523 for (gi = _gref.begin(); gi != _gref.end(); ++gi) {
524 gre.insert(GroupRefEntry(*gi, (*gi)->get_vertex_membership(this)));
525 }
526
527 // Now output the list.
528 write_long_list(out, indent_level + 2, gre.begin(), gre.end(), "// ",
529 "", 72);
530 }
531
532 indent(out, indent_level)
533 << "}\n";
534}
535
536
537/**
538 * An ordering operator to compare two vertices for sorting order. This
539 * imposes an arbitrary ordering useful to identify unique vertices.
540 *
541 * Group membership is not considered in this comparison. This is somewhat
542 * problematic, but cannot easily be helped, because considering group
543 * membership would make it difficult to add and remove groups from vertices.
544 * It also makes it impossible to meaningfully compare with a concrete
545 * EggVertex object (which cannot have group memberships).
546 *
547 * However, this is not altogether bad, because two vertices that are
548 * identical in all other properties should generally also be identical in
549 * group memberships, else the vertices will tend to fly apart when the joints
550 * animate.
551 */
553compare_to(const EggVertex &other) const {
554 if (_external_index != other._external_index) {
555 return (int)_external_index - (int)other._external_index;
556 }
557 if (_external_index2 != other._external_index2) {
558 return (int)_external_index2 - (int)other._external_index2;
559 }
560 if (_num_dimensions != other._num_dimensions) {
561 return (int)_num_dimensions - (int)other._num_dimensions;
562 }
563
564 int compare =
565 _pos.compare_to(other._pos, egg_parameters->_pos_threshold);
566 if (compare != 0) {
567 return compare;
568 }
569 compare = _dxyzs.compare_to(other._dxyzs, egg_parameters->_pos_threshold);
570 if (compare != 0) {
571 return compare;
572 }
573
574 // Merge-compare the uv maps.
575 UVMap::const_iterator ai, bi;
576 ai = _uv_map.begin();
577 bi = other._uv_map.begin();
578 while (ai != _uv_map.end() && bi != other._uv_map.end()) {
579 if ((*ai).first < (*bi).first) {
580 return -1;
581
582 } else if ((*bi).first < (*ai).first) {
583 return 1;
584
585 } else {
586 int compare = (*ai).second->compare_to(*(*bi).second);
587 if (compare != 0) {
588 return compare;
589 }
590 }
591 ++ai;
592 ++bi;
593 }
594 if (bi != other._uv_map.end()) {
595 return -1;
596 }
597 if (ai != _uv_map.end()) {
598 return 1;
599 }
600
601 // Merge-compare the aux maps.
602 AuxMap::const_iterator ci, di;
603 ci = _aux_map.begin();
604 di = other._aux_map.begin();
605 while (ci != _aux_map.end() && di != other._aux_map.end()) {
606 if ((*ci).first < (*di).first) {
607 return -1;
608
609 } else if ((*di).first < (*ci).first) {
610 return 1;
611
612 } else {
613 int compare = (*ci).second->compare_to(*(*di).second);
614 if (compare != 0) {
615 return compare;
616 }
617 }
618 ++ci;
619 ++di;
620 }
621 if (di != other._aux_map.end()) {
622 return -1;
623 }
624 if (ci != _aux_map.end()) {
625 return 1;
626 }
627
628 return EggAttributes::compare_to(other);
629}
630
631/**
632 * Returns the number of primitives that own this vertex whose vertices are
633 * interpreted to be in a local coordinate system.
634 */
636get_num_local_coord() const {
637 test_pref_integrity();
638
639 PrimitiveRef::const_iterator pri;
640
641 int count = 0;
642 for (pri = pref_begin(); pri != pref_end(); ++pri) {
643 EggPrimitive *prim = *pri;
644 count += (prim->is_local_coord() ? 1 : 0);
645 }
646 return count;
647}
648
649/**
650 * Returns the number of primitives that own this vertex whose vertices are
651 * interpreted in the global coordinate system.
652 */
654get_num_global_coord() const {
655 test_pref_integrity();
656
657 PrimitiveRef::const_iterator pri;
658
659 int count = 0;
660 for (pri = pref_begin(); pri != pref_end(); ++pri) {
661 EggPrimitive *prim = *pri;
662 count += (prim->is_local_coord() ? 0 : 1);
663 }
664 return count;
665}
666
667
668/**
669 * Applies the indicated transformation matrix to the vertex.
670 */
672transform(const LMatrix4d &mat) {
673 _pos = _pos * mat;
674
675 EggMorphVertexList::iterator mi;
676 for (mi = _dxyzs.begin(); mi != _dxyzs.end(); ++mi) {
677 // We can safely cast the morph object to a non-const, because we're not
678 // changing its name, which is the only thing the set cares about
679 // preserving.
680 EggMorphVertex &morph = (EggMorphVertex &)(*mi);
681
682 morph.set_offset((*mi).get_offset() * mat);
683 }
684
685 UVMap::iterator ui;
686 for (ui = _uv_map.begin(); ui != _uv_map.end(); ++ui) {
687 (*ui).second->transform(mat);
688 }
689
691}
692
693
694/**
695 * Returns an iterator that can, in conjunction with gref_end(), be used to
696 * traverse the entire set of groups that reference this vertex. Each
697 * iterator returns a pointer to a group.
698 *
699 * This interface is not safe to use outside of PANDAEGG.DLL.
700 */
701EggVertex::GroupRef::const_iterator EggVertex::
702gref_begin() const {
703 return _gref.begin();
704}
705
706/**
707 * Returns an iterator that can, in conjunction with gref_begin(), be used to
708 * traverse the entire set of groups that reference this vertex. Each
709 * iterator returns a pointer to a group.
710 *
711 * This interface is not safe to use outside of PANDAEGG.DLL.
712 */
713EggVertex::GroupRef::const_iterator EggVertex::
714gref_end() const {
715 return _gref.end();
716}
717
718/**
719 * Returns the number of elements between gref_begin() and gref_end().
720 *
721 * This interface is not safe to use outside of PANDAEGG.DLL.
722 */
723EggVertex::GroupRef::size_type EggVertex::
724gref_size() const {
725 return _gref.size();
726}
727
728/**
729 * Returns true if the indicated group references this vertex, false
730 * otherwise.
731 */
733has_gref(const EggGroup *group) const {
734 return _gref.count((EggGroup *)group) != 0;
735}
736
737/**
738 * Copies all the group references from the other vertex onto this one. This
739 * assigns the current vertex to exactly the same groups, with exactly the
740 * same memberships, as the given one.
741 *
742 * Warning: only an EggVertex allocated from the free store may have groups
743 * assigned to it. Do not attempt to call this on a temporary concrete
744 * EggVertex object; a core dump will certainly result.
745 */
747copy_grefs_from(const EggVertex &other) {
748 if (&other == this) {
749 return;
750 }
751 test_gref_integrity();
752 other.test_gref_integrity();
753
754 clear_grefs();
755 test_gref_integrity();
756
757 GroupRef::const_iterator gri;
758
759 for (gri = other.gref_begin(); gri != other.gref_end(); ++gri) {
760 EggGroup *group = *gri;
761 nassertv(group != nullptr);
762
763 group->ref_vertex(this, group->get_vertex_membership(&other));
764 }
765}
766
767/**
768 * Removes all group references from the vertex, so that it is not assigned to
769 * any group.
770 */
772clear_grefs() {
773 GroupRef gref_copy = _gref;
774 GroupRef::const_iterator gri;
775 for (gri = gref_copy.begin(); gri != gref_copy.end(); ++gri) {
776 EggGroup *group = *gri;
777 nassertv(group != nullptr);
778 group->unref_vertex(this);
779 }
780
781 // Now we should have no more refs.
782 nassertv(_gref.empty());
783}
784
785/**
786 * Returns an iterator that can, in conjunction with pref_end(), be used to
787 * traverse the entire set of primitives that reference this vertex. Each
788 * iterator returns a pointer to a primitive.
789 *
790 * This interface is not safe to use outside of PANDAEGG.DLL.
791 */
792EggVertex::PrimitiveRef::const_iterator EggVertex::
793pref_begin() const {
794 return _pref.begin();
795}
796
797/**
798 * Returns an iterator that can, in conjunction with pref_begin(), be used to
799 * traverse the entire set of primitives that reference this vertex. Each
800 * iterator returns a pointer to a primitive.
801 *
802 * This interface is not safe to use outside of PANDAEGG.DLL.
803 */
804EggVertex::PrimitiveRef::const_iterator EggVertex::
805pref_end() const {
806 return _pref.end();
807}
808
809/**
810 * Returns the number of elements between pref_begin() and pref_end().
811 *
812 * This interface is not safe to use outside of PANDAEGG.DLL.
813 */
814EggVertex::GroupRef::size_type EggVertex::
815pref_size() const {
816 return _pref.size();
817}
818
819/**
820 * Returns the number of times the vertex appears in the indicated primitive,
821 * or 0 if it does not appear.
822 */
824has_pref(const EggPrimitive *prim) const {
825 return _pref.count((EggPrimitive *)prim);
826}
827
828#ifdef _DEBUG
829
830/**
831 * Verifies that the gref list is correct and that all the groups included
832 * actually exist and do reference the vertex.
833 */
834void EggVertex::
835test_gref_integrity() const {
837
838 GroupRef::const_iterator gri;
839
840 for (gri = gref_begin(); gri != gref_end(); ++gri) {
841 EggGroup *group = *gri;
842 nassertv(group != nullptr);
844
845 double membership = group->get_vertex_membership(this);
846 nassertv(membership != 0.0);
847 }
848}
849
850/**
851 * Verifies that the pref list is correct and that all the primitives included
852 * actually exist and do reference the vertex.
853 */
854void EggVertex::
855test_pref_integrity() const {
857
858 PrimitiveRef::const_iterator pri;
859
860 for (pri = pref_begin(); pri != pref_end(); ++pri) {
861 EggPrimitive *prim = *pri;
862 nassertv(prim != nullptr);
864
865 EggPrimitive::iterator vi;
866 vi = find(prim->begin(), prim->end(), this);
867 nassertv(vi != prim->end());
868 }
869}
870
871#endif // NDEBUG
872
873/**
874 *
875 */
876void EggVertex::
877output(ostream &out) const {
878 if (get_pool() == nullptr) {
879 out << "(null):" << get_index();
880 } else {
881 out << get_pool()->get_name() << ":" << get_index();
882 }
883}
The set of attributes that may be applied to vertices as well as polygons, such as surface normal and...
void transform(const LMatrix4d &mat)
Applies the indicated transformation matrix to the attributes.
int compare_to(const EggAttributes &other) const
An ordering operator to compare two vertices for sorting order.
LColor get_color() const
Returns the color set on this particular attribute.
void write(std::ostream &out, int indent_level) const
Writes the attributes to the indicated output stream in Egg format.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
Definition eggGroup.h:34
void unref_vertex(EggVertex *vert)
Removes the vertex from the set of those referenced by the group.
Definition eggGroup.cxx:640
void set_vertex_membership(EggVertex *vert, double membership)
Explicitly sets the net membership of the indicated vertex in this group to the given value.
Definition eggGroup.cxx:692
void ref_vertex(EggVertex *vert, double membership=1.0)
Adds the vertex to the set of those referenced by the group, at the indicated membership level.
Definition eggGroup.cxx:608
double get_vertex_membership(const EggVertex *vert) const
Returns the amount of membership of the indicated vertex in this group.
Definition eggGroup.cxx:677
int compare_to(const EggMorphList< MorphType > &other, double threshold) const
compare_to() compares a different space than the operator methods, which only check the morph's name.
A single <Dxyz> or <Duv> or some such entry.
Definition eggMorph.h:30
bool is_local_coord() const
Returns true if this node's vertices are not in the global coordinate space.
Definition eggNode.I:87
The highest-level base class in the egg directory.
Definition eggObject.h:29
A base class for any of a number of kinds of geometry primitives: polygons, point lights,...
The set of named auxiliary data that may or may not be assigned to a vertex.
A collection of vertices.
The set of UV's that may or may not be assigned to a vertex.
Definition eggVertexUV.h:29
static std::string filter_name(const std::string &name)
Returns the actual name that should be set for a given name string.
Definition eggVertexUV.I:20
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
const EggVertexUV * get_uv_obj(const std::string &name) const
Returns the named EggVertexUV object, which defines both the UV coordinate pair for this name and the...
void set_uv_obj(EggVertexUV *vertex_uv)
Sets the indicated EggVertexUV on the vertex.
void set_pos4(const LPoint4d &pos)
This special flavor of set_pos() sets the vertex as a four-component value, but does not change the s...
Definition eggVertex.I:89
const EggVertexAux * get_aux_obj(const std::string &name) const
Returns the named EggVertexAux object, which defines the auxiliary data for this name.
bool has_uvw(const std::string &name) const
Returns true if the vertex has the named UV coordinate triple, and the named UV coordinate triple is ...
bool has_gref(const EggGroup *group) const
Returns true if the indicated group references this vertex, false otherwise.
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
int has_pref(const EggPrimitive *prim) const
Returns the number of times the vertex appears in the indicated primitive, or 0 if it does not appear...
EggVertexUV * modify_uv_obj(const std::string &name)
Returns a modifiable pointer to the named EggVertexUV object, which defines both the UV coordinate pa...
int compare_to(const EggVertex &other) const
An ordering operator to compare two vertices for sorting order.
bool has_aux() const
Returns true if the vertex has any auxiliary data, false otherwise.
Definition eggVertex.I:166
void set_aux(const std::string &name, const LVecBase4d &aux)
Sets the indicated auxiliary data quadruple on the vertex.
void transform(const LMatrix4d &mat)
Applies the indicated transformation matrix to the vertex.
PrimitiveRef::const_iterator pref_begin() const
Returns an iterator that can, in conjunction with pref_end(), be used to traverse the entire set of p...
EggVertex & operator=(const EggVertex &copy)
Copies all properties of the vertex except its vertex pool, index number, and group membership.
Definition eggVertex.cxx:78
EggVertexPool * get_pool() const
Returns the vertex pool this vertex belongs in.
Definition eggVertex.I:19
LTexCoordd get_uv() const
Returns the unnamed UV coordinate pair on the vertex.
Definition eggVertex.I:179
PrimitiveRef::const_iterator pref_end() const
Returns an iterator that can, in conjunction with pref_begin(), be used to traverse the entire set of...
const LTexCoord3d & get_uvw(const std::string &name) const
Returns the named UV coordinate triple on the vertex.
GroupRef::const_iterator gref_end() const
Returns an iterator that can, in conjunction with gref_begin(), be used to traverse the entire set of...
void set_pos(double pos)
Sets the vertex position.
Definition eggVertex.I:42
GroupRef::size_type gref_size() const
Returns the number of elements between gref_begin() and gref_end().
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
void set_uvw(const std::string &name, const LTexCoord3d &texCoord)
Sets the indicated UV coordinate triple on the vertex.
void clear_uv()
Removes all UV coordinate pairs from the vertex.
Definition eggVertex.I:201
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().
void copy_grefs_from(const EggVertex &other)
Copies all the group references from the other vertex onto this one.
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
EggVertexAux * modify_aux_obj(const std::string &name)
Returns a modifiable pointer to the named EggVertexAux object, which defines the auxiliary data for t...
void clear_aux()
Removes all auxiliary data from the vertex.
Definition eggVertex.I:209
GroupRef::const_iterator gref_begin() const
Returns an iterator that can, in conjunction with gref_end(), be used to traverse the entire set of g...
void write(std::ostream &out, int indent_level) const
Writes the vertex to the indicated output stream in Egg format.
void set_uv(const LTexCoordd &texCoord)
Replaces the unnamed UV coordinate pair on the vertex with the indicated value.
Definition eggVertex.I:193
LPoint4d get_pos4() const
This is always valid, regardless of the value of get_num_dimensions.
Definition eggVertex.I:145
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
const LVecBase4d & get_aux(const std::string &name) const
Returns the named auxiliary data quadruple on the vertex.
int get_num_global_coord() const
Returns the number of primitives that own this vertex whose vertices are interpreted in the global co...
void set_aux_obj(EggVertexAux *vertex_aux)
Sets the indicated EggVertexAux on the vertex.
bool test_ref_count_integrity() const
Does some easy checks to make sure that the reference count isn't completely bogus.
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
void write_long_list(std::ostream &out, int indent_level, InputIterator ifirst, InputIterator ilast, std::string first_prefix="", std::string later_prefix="", int max_col=72)
Writes a list of things to the indicated output stream, with a space separating each item.
Definition indent.I:22
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.