00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "eggVertex.h"
00016 #include "eggVertexPool.h"
00017 #include "eggParameters.h"
00018 #include "eggGroup.h"
00019 #include "eggMiscFuncs.h"
00020 #include "eggPrimitive.h"
00021
00022 #include "indent.h"
00023 #include "luse.h"
00024 #include "lmatrix.h"
00025 #include "pandabase.h"
00026
00027 #include <math.h>
00028 #include <algorithm>
00029
00030 TypeHandle EggVertex::_type_handle;
00031
00032
00033
00034
00035
00036
00037
00038 EggVertex::
00039 EggVertex() {
00040 _pool = NULL;
00041 _forward_reference = false;
00042 _index = -1;
00043 _external_index = -1;
00044 set_pos(LPoint3d(0.0, 0.0, 0.0));
00045 test_pref_integrity();
00046 test_gref_integrity();
00047 }
00048
00049
00050
00051
00052
00053
00054
00055 EggVertex::
00056 EggVertex(const EggVertex ©)
00057 : EggObject(copy), EggAttributes(copy),
00058 _dxyzs(copy._dxyzs),
00059 _external_index(copy._external_index),
00060 _pos(copy._pos),
00061 _num_dimensions(copy._num_dimensions),
00062 _uv_map(copy._uv_map),
00063 _aux_map(copy._aux_map)
00064 {
00065 _pool = NULL;
00066 _forward_reference = false;
00067 _index = -1;
00068 test_pref_integrity();
00069 test_gref_integrity();
00070 }
00071
00072
00073
00074
00075
00076
00077
00078
00079 EggVertex &EggVertex::
00080 operator = (const EggVertex ©) {
00081 EggObject::operator = (copy);
00082 EggAttributes::operator = (copy);
00083 _dxyzs = copy._dxyzs;
00084 _external_index = copy._external_index;
00085 _pos = copy._pos;
00086 _num_dimensions = copy._num_dimensions;
00087 _uv_map = copy._uv_map;
00088 _aux_map = copy._aux_map;
00089
00090 test_pref_integrity();
00091 test_gref_integrity();
00092
00093 return *this;
00094 }
00095
00096
00097
00098
00099
00100
00101 EggVertex::
00102 ~EggVertex() {
00103
00104
00105
00106 nassertv(_pool == NULL);
00107
00108
00109
00110 nassertv(_gref.empty());
00111 nassertv(_pref.empty());
00112 }
00113
00114
00115
00116
00117
00118
00119
00120
00121 bool EggVertex::
00122 has_uv(const string &name) const {
00123 UVMap::const_iterator ui = _uv_map.find(EggVertexUV::filter_name(name));
00124 if (ui != _uv_map.end()) {
00125 EggVertexUV *uv_obj = (*ui).second;
00126 return !uv_obj->has_w();
00127 }
00128 return false;
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138 bool EggVertex::
00139 has_uvw(const string &name) const {
00140 UVMap::const_iterator ui = _uv_map.find(EggVertexUV::filter_name(name));
00141 if (ui != _uv_map.end()) {
00142 EggVertexUV *uv_obj = (*ui).second;
00143 return uv_obj->has_w();
00144 }
00145 return false;
00146 }
00147
00148
00149
00150
00151
00152
00153
00154 bool EggVertex::
00155 has_aux(const string &name) const {
00156 AuxMap::const_iterator xi = _aux_map.find(name);
00157 if (xi != _aux_map.end()) {
00158 EggVertexAux *aux_obj = (*xi).second;
00159 return true;
00160 }
00161 return false;
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171 LTexCoordd EggVertex::
00172 get_uv(const string &name) const {
00173 UVMap::const_iterator ui = _uv_map.find(EggVertexUV::filter_name(name));
00174 nassertr(ui != _uv_map.end(), LTexCoordd::zero());
00175 return (*ui).second->get_uv();
00176 }
00177
00178
00179
00180
00181
00182
00183
00184
00185 const LTexCoord3d &EggVertex::
00186 get_uvw(const string &name) const {
00187 UVMap::const_iterator ui = _uv_map.find(EggVertexUV::filter_name(name));
00188 nassertr(ui != _uv_map.end(), LTexCoord3d::zero());
00189 return (*ui).second->get_uvw();
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199 const LVecBase4d &EggVertex::
00200 get_aux(const string &name) const {
00201 AuxMap::const_iterator xi = _aux_map.find(name);
00202 nassertr(xi != _aux_map.end(), LVecBase4d::zero());
00203 return (*xi).second->get_aux();
00204 }
00205
00206
00207
00208
00209
00210
00211
00212
00213 void EggVertex::
00214 set_uv(const string &name, const LTexCoordd &uv) {
00215 string fname = EggVertexUV::filter_name(name);
00216 PT(EggVertexUV) &uv_obj = _uv_map[fname];
00217
00218 if (uv_obj.is_null()) {
00219 uv_obj = new EggVertexUV(fname, uv);
00220 } else {
00221 uv_obj = new EggVertexUV(*uv_obj);
00222 uv_obj->set_uv(uv);
00223 }
00224
00225 nassertv(get_uv(fname) == uv);
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 void EggVertex::
00237 set_uvw(const string &name, const LTexCoord3d &uvw) {
00238 string fname = EggVertexUV::filter_name(name);
00239 PT(EggVertexUV) &uv_obj = _uv_map[fname];
00240
00241 if (uv_obj.is_null()) {
00242 uv_obj = new EggVertexUV(fname, uvw);
00243 } else {
00244 uv_obj = new EggVertexUV(*uv_obj);
00245 uv_obj->set_uvw(uvw);
00246 }
00247
00248 nassertv(get_uvw(fname) == uvw);
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258 void EggVertex::
00259 set_aux(const string &name, const LVecBase4d &aux) {
00260 PT(EggVertexAux) &aux_obj = _aux_map[name];
00261
00262 if (aux_obj.is_null()) {
00263 aux_obj = new EggVertexAux(name, aux);
00264 } else {
00265 aux_obj = new EggVertexAux(*aux_obj);
00266 aux_obj->set_aux(aux);
00267 }
00268
00269 nassertv(get_aux(name) == aux);
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 const EggVertexUV *EggVertex::
00283 get_uv_obj(const string &name) const {
00284 UVMap::const_iterator ui = _uv_map.find(EggVertexUV::filter_name(name));
00285 if (ui != _uv_map.end()) {
00286 return (*ui).second;
00287 }
00288 return NULL;
00289 }
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 const EggVertexAux *EggVertex::
00301 get_aux_obj(const string &name) const {
00302 AuxMap::const_iterator xi = _aux_map.find(name);
00303 if (xi != _aux_map.end()) {
00304 return (*xi).second;
00305 }
00306 return NULL;
00307 }
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 EggVertexUV *EggVertex::
00318 modify_uv_obj(const string &name) {
00319 UVMap::iterator ui = _uv_map.find(EggVertexUV::filter_name(name));
00320 if (ui != _uv_map.end()) {
00321 if ((*ui).second->get_ref_count() != 1) {
00322
00323 (*ui).second = new EggVertexUV(*(*ui).second);
00324 }
00325 return (*ui).second;
00326 }
00327
00328 return NULL;
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 EggVertexAux *EggVertex::
00340 modify_aux_obj(const string &name) {
00341 AuxMap::iterator xi = _aux_map.find(name);
00342 if (xi != _aux_map.end()) {
00343 if ((*xi).second->get_ref_count() != 1) {
00344
00345 (*xi).second = new EggVertexAux(*(*xi).second);
00346 }
00347 return (*xi).second;
00348 }
00349
00350 return NULL;
00351 }
00352
00353
00354
00355
00356
00357
00358
00359
00360 void EggVertex::
00361 set_uv_obj(EggVertexUV *uv) {
00362 _uv_map[uv->get_name()] = uv;
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372 void EggVertex::
00373 set_aux_obj(EggVertexAux *aux) {
00374 _aux_map[aux->get_name()] = aux;
00375 }
00376
00377
00378
00379
00380
00381
00382
00383 void EggVertex::
00384 clear_uv(const string &name) {
00385 _uv_map.erase(EggVertexUV::filter_name(name));
00386 }
00387
00388
00389
00390
00391
00392
00393 void EggVertex::
00394 clear_aux(const string &name) {
00395 _aux_map.erase(name);
00396 }
00397
00398
00399
00400
00401
00402
00403
00404
00405 class GroupRefEntry {
00406 public:
00407 GroupRefEntry(EggGroup *group, double membership)
00408 : _group(group), _membership(membership) { }
00409
00410 bool operator < (const GroupRefEntry &other) const {
00411 return _group->get_name() < other._group->get_name();
00412 }
00413 void output(ostream &out) const {
00414 out << _group->get_name() << ":" << _membership;
00415 }
00416
00417 EggGroup *_group;
00418 double _membership;
00419 };
00420
00421 INLINE ostream &operator << (ostream &out, const GroupRefEntry &gre) {
00422 gre.output(out);
00423 return out;
00424 }
00425
00426
00427
00428
00429
00430
00431
00432 void EggVertex::
00433 write(ostream &out, int indent_level) const {
00434 test_pref_integrity();
00435 test_gref_integrity();
00436
00437 indent(out, indent_level)
00438 << "<Vertex> " << _index << " {\n";
00439
00440
00441
00442 indent(out, indent_level+1);
00443 for (int i = 0; i < _num_dimensions; i++) {
00444 out << " " << _pos[i];
00445 }
00446 out << "\n";
00447
00448 UVMap::const_iterator ui;
00449 for (ui = _uv_map.begin(); ui != _uv_map.end(); ++ui) {
00450 (*ui).second->write(out, indent_level + 2);
00451 }
00452
00453 AuxMap::const_iterator xi;
00454 for (xi = _aux_map.begin(); xi != _aux_map.end(); ++xi) {
00455 (*xi).second->write(out, indent_level + 2);
00456 }
00457
00458 EggAttributes::write(out, indent_level+2);
00459
00460 _dxyzs.write(out, indent_level + 2, "<Dxyz>", 3);
00461
00462
00463
00464 if (!_gref.empty()) {
00465
00466 pset<GroupRefEntry> gre;
00467
00468 GroupRef::const_iterator gi;
00469 for (gi = _gref.begin(); gi != _gref.end(); ++gi) {
00470 gre.insert(GroupRefEntry(*gi, (*gi)->get_vertex_membership(this)));
00471 }
00472
00473
00474 write_long_list(out, indent_level + 2, gre.begin(), gre.end(), "// ",
00475 "", 72);
00476 }
00477
00478 indent(out, indent_level)
00479 << "}\n";
00480 }
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504 int EggVertex::
00505 compare_to(const EggVertex &other) const {
00506 if (_external_index != other._external_index) {
00507 return (int)_external_index - (int)other._external_index;
00508 }
00509 if (_num_dimensions != other._num_dimensions) {
00510 return (int)_num_dimensions - (int)other._num_dimensions;
00511 }
00512
00513 int compare =
00514 _pos.compare_to(other._pos, egg_parameters->_pos_threshold);
00515 if (compare != 0) {
00516 return compare;
00517 }
00518 compare = _dxyzs.compare_to(other._dxyzs, egg_parameters->_pos_threshold);
00519 if (compare != 0) {
00520 return compare;
00521 }
00522
00523
00524 UVMap::const_iterator ai, bi;
00525 ai = _uv_map.begin();
00526 bi = other._uv_map.begin();
00527 while (ai != _uv_map.end() && bi != other._uv_map.end()) {
00528 if ((*ai).first < (*bi).first) {
00529 return -1;
00530
00531 } else if ((*bi).first < (*ai).first) {
00532 return 1;
00533
00534 } else {
00535 int compare = (*ai).second->compare_to(*(*bi).second);
00536 if (compare != 0) {
00537 return compare;
00538 }
00539 }
00540 ++ai;
00541 ++bi;
00542 }
00543 if (bi != other._uv_map.end()) {
00544 return -1;
00545 }
00546 if (ai != _uv_map.end()) {
00547 return 1;
00548 }
00549
00550
00551 AuxMap::const_iterator ci, di;
00552 ci = _aux_map.begin();
00553 di = other._aux_map.begin();
00554 while (ci != _aux_map.end() && di != other._aux_map.end()) {
00555 if ((*ci).first < (*di).first) {
00556 return -1;
00557
00558 } else if ((*di).first < (*ci).first) {
00559 return 1;
00560
00561 } else {
00562 int compare = (*ci).second->compare_to(*(*di).second);
00563 if (compare != 0) {
00564 return compare;
00565 }
00566 }
00567 ++ci;
00568 ++di;
00569 }
00570 if (di != other._aux_map.end()) {
00571 return -1;
00572 }
00573 if (ci != _aux_map.end()) {
00574 return 1;
00575 }
00576
00577 return EggAttributes::compare_to(other);
00578 }
00579
00580
00581
00582
00583
00584
00585
00586
00587 int EggVertex::
00588 get_num_local_coord() const {
00589 test_pref_integrity();
00590
00591 PrimitiveRef::const_iterator pri;
00592
00593 int count = 0;
00594 for (pri = pref_begin(); pri != pref_end(); ++pri) {
00595 EggPrimitive *prim = *pri;
00596 count += (prim->is_local_coord() ? 1 : 0);
00597 }
00598 return count;
00599 }
00600
00601
00602
00603
00604
00605
00606
00607
00608 int EggVertex::
00609 get_num_global_coord() const {
00610 test_pref_integrity();
00611
00612 PrimitiveRef::const_iterator pri;
00613
00614 int count = 0;
00615 for (pri = pref_begin(); pri != pref_end(); ++pri) {
00616 EggPrimitive *prim = *pri;
00617 count += (prim->is_local_coord() ? 0 : 1);
00618 }
00619 return count;
00620 }
00621
00622
00623
00624
00625
00626
00627
00628
00629 void EggVertex::
00630 transform(const LMatrix4d &mat) {
00631 _pos = _pos * mat;
00632
00633 EggMorphVertexList::iterator mi;
00634 for (mi = _dxyzs.begin(); mi != _dxyzs.end(); ++mi) {
00635
00636
00637
00638 EggMorphVertex &morph = (EggMorphVertex &)(*mi);
00639
00640 morph.set_offset((*mi).get_offset() * mat);
00641 }
00642
00643 UVMap::iterator ui;
00644 for (ui = _uv_map.begin(); ui != _uv_map.end(); ++ui) {
00645 (*ui).second->transform(mat);
00646 }
00647
00648 EggAttributes::transform(mat);
00649 }
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663 EggVertex::GroupRef::const_iterator EggVertex::
00664 gref_begin() const {
00665 return _gref.begin();
00666 }
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679 EggVertex::GroupRef::const_iterator EggVertex::
00680 gref_end() const {
00681 return _gref.end();
00682 }
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693 EggVertex::GroupRef::size_type EggVertex::
00694 gref_size() const {
00695 return _gref.size();
00696 }
00697
00698
00699
00700
00701
00702
00703
00704 bool EggVertex::
00705 has_gref(const EggGroup *group) const {
00706 return _gref.count((EggGroup *)group) != 0;
00707 }
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722 void EggVertex::
00723 copy_grefs_from(const EggVertex &other) {
00724 if (&other == this) {
00725 return;
00726 }
00727 test_gref_integrity();
00728 other.test_gref_integrity();
00729
00730 clear_grefs();
00731 test_gref_integrity();
00732
00733 GroupRef::const_iterator gri;
00734
00735 for (gri = other.gref_begin(); gri != other.gref_end(); ++gri) {
00736 EggGroup *group = *gri;
00737 nassertv(group != NULL);
00738
00739 group->ref_vertex(this, group->get_vertex_membership(&other));
00740 }
00741 }
00742
00743
00744
00745
00746
00747
00748
00749 void EggVertex::
00750 clear_grefs() {
00751 GroupRef gref_copy = _gref;
00752 GroupRef::const_iterator gri;
00753 for (gri = gref_copy.begin(); gri != gref_copy.end(); ++gri) {
00754 EggGroup *group = *gri;
00755 nassertv(group != NULL);
00756 group->unref_vertex(this);
00757 }
00758
00759
00760 nassertv(_gref.empty());
00761 }
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774 EggVertex::PrimitiveRef::const_iterator EggVertex::
00775 pref_begin() const {
00776 return _pref.begin();
00777 }
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790 EggVertex::PrimitiveRef::const_iterator EggVertex::
00791 pref_end() const {
00792 return _pref.end();
00793 }
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804 EggVertex::GroupRef::size_type EggVertex::
00805 pref_size() const {
00806 return _pref.size();
00807 }
00808
00809
00810
00811
00812
00813
00814
00815 int EggVertex::
00816 has_pref(const EggPrimitive *prim) const {
00817 return _pref.count((EggPrimitive *)prim);
00818 }
00819
00820 #ifdef _DEBUG
00821
00822
00823
00824
00825
00826
00827
00828
00829 void EggVertex::
00830 test_gref_integrity() const {
00831 test_ref_count_integrity();
00832
00833 GroupRef::const_iterator gri;
00834
00835 for (gri = gref_begin(); gri != gref_end(); ++gri) {
00836 EggGroup *group = *gri;
00837 nassertv(group != NULL);
00838 group->test_ref_count_integrity();
00839
00840 double membership = group->get_vertex_membership(this);
00841 nassertv(membership != 0.0);
00842 }
00843 }
00844
00845
00846
00847
00848
00849
00850
00851
00852 void EggVertex::
00853 test_pref_integrity() const {
00854 test_ref_count_integrity();
00855
00856 PrimitiveRef::const_iterator pri;
00857
00858 for (pri = pref_begin(); pri != pref_end(); ++pri) {
00859 EggPrimitive *prim = *pri;
00860 nassertv(prim != NULL);
00861 prim->test_ref_count_integrity();
00862
00863 EggPrimitive::iterator vi;
00864 vi = find(prim->begin(), prim->end(), this);
00865 nassertv(vi != prim->end());
00866 }
00867 }
00868
00869 #endif // NDEBUG
00870
00871
00872
00873
00874
00875
00876 void EggVertex::
00877 output(ostream &out) const {
00878 if (get_pool() == NULL) {
00879 out << "(null):" << get_index();
00880 } else {
00881 out << get_pool()->get_name() << ":" << get_index();
00882 }
00883 }