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