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