Panda3D
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 
29 using std::ostream;
30 using std::string;
31 
32 TypeHandle EggVertex::_type_handle;
33 
34 
35 /**
36  *
37  */
38 EggVertex::
39 EggVertex() {
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  */
54 EggVertex::
55 EggVertex(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  */
78 operator = (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  */
98 EggVertex::
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  */
115 has_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  */
129 has_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  */
142 has_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  */
151 LTexCoordd EggVertex::
152 get_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  */
162 const LTexCoord3d &EggVertex::
163 get_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  */
173 const LVecBase4d &EggVertex::
174 get_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  */
186 set_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  */
206 set_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  */
225 set_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  */
245 get_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  */
260 get_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  */
274 modify_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  */
293 modify_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  */
312 set_uv_obj(EggVertexUV *uv) {
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  */
330 clear_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  */
338 clear_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  */
349 PT(EggVertex) EggVertex::
350 make_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  */
462 class GroupRefEntry {
463 public:
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 
478 INLINE 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  */
487 write(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  */
553 compare_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  */
636 get_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  */
654 get_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  */
672 transform(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  */
701 EggVertex::GroupRef::const_iterator EggVertex::
702 gref_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  */
713 EggVertex::GroupRef::const_iterator EggVertex::
714 gref_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  */
723 EggVertex::GroupRef::size_type EggVertex::
724 gref_size() const {
725  return _gref.size();
726 }
727 
728 /**
729  * Returns true if the indicated group references this vertex, false
730  * otherwise.
731  */
733 has_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  */
747 copy_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  */
772 clear_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  */
792 EggVertex::PrimitiveRef::const_iterator EggVertex::
793 pref_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  */
804 EggVertex::PrimitiveRef::const_iterator EggVertex::
805 pref_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  */
814 EggVertex::GroupRef::size_type EggVertex::
815 pref_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  */
824 has_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  */
834 void EggVertex::
835 test_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);
843  group->test_ref_count_integrity();
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  */
854 void EggVertex::
855 test_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);
863  prim->test_ref_count_integrity();
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  */
876 void EggVertex::
877 output(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...
Definition: eggAttributes.h:33
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.
Definition: eggAttributes.I:91
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.
Definition: eggMorphList.I:83
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,...
Definition: eggPrimitive.h:49
The set of named auxiliary data that may or may not be assigned to a vertex.
Definition: eggVertexAux.h:30
A collection of vertices.
Definition: eggVertexPool.h:41
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...
Definition: eggVertex.cxx:245
void set_uv_obj(EggVertexUV *vertex_uv)
Sets the indicated EggVertexUV on the vertex.
Definition: eggVertex.cxx:312
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.
Definition: eggVertex.cxx:260
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 ...
Definition: eggVertex.cxx:129
bool has_gref(const EggGroup *group) const
Returns true if the indicated group references this vertex, false otherwise.
Definition: eggVertex.cxx:733
bool has_uv() const
Returns true if the vertex has an unnamed UV coordinate pair, false otherwise.
Definition: eggVertex.I:158
void clear_grefs()
Removes all group references from the vertex, so that it is not assigned to any group.
Definition: eggVertex.cxx:772
int get_index() const
Returns the index number of the vertex within its pool.
Definition: eggVertex.I:277
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...
Definition: eggVertex.cxx:824
EggVertexUV * modify_uv_obj(const std::string &name)
Returns a modifiable pointer to the named EggVertexUV object, which defines both the UV coordinate pa...
Definition: eggVertex.cxx:274
int compare_to(const EggVertex &other) const
An ordering operator to compare two vertices for sorting order.
Definition: eggVertex.cxx:553
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.
Definition: eggVertex.cxx:225
void transform(const LMatrix4d &mat)
Applies the indicated transformation matrix to the vertex.
Definition: eggVertex.cxx:672
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...
Definition: eggVertex.cxx:793
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...
Definition: eggVertex.cxx:805
const LTexCoord3d & get_uvw(const std::string &name) const
Returns the named UV coordinate triple on the vertex.
Definition: eggVertex.cxx:163
GroupRef::const_iterator gref_end() const
Returns an iterator that can, in conjunction with gref_begin(), be used to traverse the entire set of...
Definition: eggVertex.cxx:714
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().
Definition: eggVertex.cxx:724
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.
Definition: eggVertex.cxx:206
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().
Definition: eggVertex.cxx:815
void copy_grefs_from(const EggVertex &other)
Copies all the group references from the other vertex onto this one.
Definition: eggVertex.cxx:747
int get_num_local_coord() const
Returns the number of primitives that own this vertex whose vertices are interpreted to be in a local...
Definition: eggVertex.cxx:636
const_uv_iterator uv_begin() const
Returns an iterator that allows walking through the complete set of named UV's on the vertex.
Definition: eggVertex.I:220
EggVertexAux * modify_aux_obj(const std::string &name)
Returns a modifiable pointer to the named EggVertexAux object, which defines the auxiliary data for t...
Definition: eggVertex.cxx:293
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...
Definition: eggVertex.cxx:702
void write(std::ostream &out, int indent_level) const
Writes the vertex to the indicated output stream in Egg format.
Definition: eggVertex.cxx:487
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.
Definition: eggVertex.cxx:174
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
void set_aux_obj(EggVertexAux *vertex_aux)
Sets the indicated EggVertexAux on the vertex.
Definition: eggVertex.cxx:321
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.
PT(EggVertex) EggVertex
Creates a new vertex that lies in between the two given vertices.
Definition: eggVertex.cxx:349
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.