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  */
114 bool EggVertex::
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  */
128 bool EggVertex::
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  */
141 bool EggVertex::
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  */
185 void EggVertex::
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  */
205 void EggVertex::
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  */
224 void EggVertex::
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  */
311 void EggVertex::
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  */
320 void EggVertex::
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  */
329 void EggVertex::
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  */
337 void EggVertex::
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  */
486 void EggVertex::
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  */
552 int EggVertex::
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  */
635 int EggVertex::
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  */
653 int EggVertex::
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  */
671 void EggVertex::
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  */
732 bool EggVertex::
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  */
746 void EggVertex::
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  */
771 void EggVertex::
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  */
823 int EggVertex::
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 }
A base class for any of a number of kinds of geometry primitives: polygons, point lights,...
Definition: eggPrimitive.h:47
The set of UV's that may or may not be assigned to a vertex.
Definition: eggVertexUV.h:29
GroupRef::size_type gref_size() const
Returns the number of elements between gref_begin() and gref_end().
Definition: eggVertex.cxx:724
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PrimitiveRef::size_type pref_size() const
Returns the number of elements between pref_begin() and pref_end().
Definition: eggVertex.cxx:815
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 clear_aux()
Removes all auxiliary data from the vertex.
Definition: eggVertex.I:209
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_pos(double pos)
Sets the vertex position.
Definition: eggVertex.I:42
bool has_aux() const
Returns true if the vertex has any auxiliary data, false otherwise.
Definition: eggVertex.I:166
EggVertexPool * get_pool() const
Returns the vertex pool this vertex belongs in.
Definition: eggVertex.I:19
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void write(std::ostream &out, int indent_level) const
Writes the vertex to the indicated output stream in Egg format.
Definition: eggVertex.cxx:487
LTexCoordd get_uv() const
Returns the unnamed UV coordinate pair on the vertex.
Definition: eggVertex.I:179
void transform(const LMatrix4d &mat)
Applies the indicated transformation matrix to the attributes.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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_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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool test_ref_count_integrity() const
Does some easy checks to make sure that the reference count isn't completely bogus.
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 clear_grefs()
Removes all group references from the vertex, so that it is not assigned to any group.
Definition: eggVertex.cxx:772
A single <Dxyz> or <Duv> or some such entry.
Definition: eggMorph.h:30
LColor get_color() const
Returns the color set on this particular attribute.
Definition: eggAttributes.I:91
EggVertex & operator=(const EggVertex &copy)
Copies all properties of the vertex except its vertex pool, index number, and group membership.
Definition: eggVertex.cxx:78
void write(std::ostream &out, int indent_level) const
Writes the attributes to the indicated output stream in Egg format.
void unref_vertex(EggVertex *vert)
Removes the vertex from the set of those referenced by the group.
Definition: eggGroup.cxx:640
bool has_gref(const EggGroup *group) const
Returns true if the indicated group references this vertex, false otherwise.
Definition: eggVertex.cxx:733
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
Definition: eggGroup.h:34
const LTexCoord3d & get_uvw(const std::string &name) const
Returns the named UV coordinate triple on the vertex.
Definition: eggVertex.cxx:163
The set of attributes that may be applied to vertices as well as polygons, such as surface normal and...
Definition: eggAttributes.h:33
int get_index() const
Returns the index number of the vertex within its pool.
Definition: eggVertex.I:277
void clear_uv()
Removes all UV coordinate pairs from the vertex.
Definition: eggVertex.I:201
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
bool is_local_coord() const
Returns true if this node's vertices are not in the global coordinate space.
Definition: eggNode.I:87
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
void set_uv_obj(EggVertexUV *vertex_uv)
Sets the indicated EggVertexUV on the vertex.
Definition: eggVertex.cxx:312
void transform(const LMatrix4d &mat)
Applies the indicated transformation matrix to the vertex.
Definition: eggVertex.cxx:672
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal.
Definition: eggVertex.h:39
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition: indent.cxx:20
void set_uvw(const std::string &name, const LTexCoord3d &texCoord)
Sets the indicated UV coordinate triple on the vertex.
Definition: eggVertex.cxx:206
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
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
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
bool has_uv() const
Returns true if the vertex has an unnamed UV coordinate pair, false otherwise.
Definition: eggVertex.I:158
double get_vertex_membership(const EggVertex *vert) const
Returns the amount of membership of the indicated vertex in this group.
Definition: eggGroup.cxx:677
The set of named auxiliary data that may or may not be assigned to a vertex.
Definition: eggVertexAux.h:30
int compare_to(const EggVertex &other) const
An ordering operator to compare two vertices for sorting order.
Definition: eggVertex.cxx:553
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
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
PT(EggVertex) EggVertex
Creates a new vertex that lies in between the two given vertices.
Definition: eggVertex.cxx:349
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 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
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
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
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
void set_aux_obj(EggVertexAux *vertex_aux)
Sets the indicated EggVertexAux on the vertex.
Definition: eggVertex.cxx:321
void set_aux(const std::string &name, const LVecBase4d &aux)
Sets the indicated auxiliary data quadruple on the vertex.
Definition: eggVertex.cxx:225
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LPoint4d get_pos4() const
This is always valid, regardless of the value of get_num_dimensions.
Definition: eggVertex.I:145
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
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
This is our own Panda specialization on the default STL set.
Definition: pset.h:49
const LVecBase4d & get_aux(const std::string &name) const
Returns the named auxiliary data quadruple on the vertex.
Definition: eggVertex.cxx:174
void copy_grefs_from(const EggVertex &other)
Copies all the group references from the other vertex onto this one.
Definition: eggVertex.cxx:747
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
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
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_uv(const LTexCoordd &texCoord)
Replaces the unnamed UV coordinate pair on the vertex with the indicated value.
Definition: eggVertex.I:193
A collection of vertices.
Definition: eggVertexPool.h:41
The highest-level base class in the egg directory.
Definition: eggObject.h:29
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int compare_to(const EggAttributes &other) const
An ordering operator to compare two vertices for sorting order.
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