00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "textureAttrib.h"
00016 #include "graphicsStateGuardianBase.h"
00017 #include "internalName.h"
00018 #include "bamReader.h"
00019 #include "bamWriter.h"
00020 #include "datagram.h"
00021 #include "datagramIterator.h"
00022 #include "dcast.h"
00023 #include "textureStagePool.h"
00024
00025 CPT(RenderAttrib) TextureAttrib::_empty_attrib;
00026 CPT(RenderAttrib) TextureAttrib::_all_off_attrib;
00027 TypeHandle TextureAttrib::_type_handle;
00028 int TextureAttrib::_attrib_slot;
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 CPT(RenderAttrib) TextureAttrib::
00039 make(Texture *texture) {
00040 return DCAST(TextureAttrib, make())->add_on_stage(TextureStage::get_default(), texture);
00041 }
00042
00043
00044
00045
00046
00047
00048
00049 CPT(RenderAttrib) TextureAttrib::
00050 make_off() {
00051 return make_all_off();
00052 }
00053
00054
00055
00056
00057
00058
00059
00060 CPT(RenderAttrib) TextureAttrib::
00061 make() {
00062
00063
00064 if (_empty_attrib == (RenderAttrib *)NULL) {
00065 _empty_attrib = return_new(new TextureAttrib);
00066 }
00067
00068 return _empty_attrib;
00069 }
00070
00071
00072
00073
00074
00075
00076
00077 CPT(RenderAttrib) TextureAttrib::
00078 make_all_off() {
00079
00080
00081 if (_all_off_attrib == (RenderAttrib *)NULL) {
00082 TextureAttrib *attrib = new TextureAttrib;
00083 attrib->_off_all_stages = true;
00084 _all_off_attrib = return_new(attrib);
00085 }
00086
00087 return _all_off_attrib;
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097 CPT(RenderAttrib) TextureAttrib::
00098 make_default() {
00099 return make();
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 int TextureAttrib::
00111 find_on_stage(const TextureStage *stage) const {
00112 Stages::const_iterator si = _on_stages.find(StageNode(stage));
00113 if (si != _on_stages.end()) {
00114 return (int)(si - _on_stages.begin());
00115 }
00116
00117 return -1;
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127 CPT(RenderAttrib) TextureAttrib::
00128 add_on_stage(TextureStage *stage, Texture *tex, int override) const {
00129 TextureAttrib *attrib = new TextureAttrib(*this);
00130 Stages::iterator si = attrib->_on_stages.insert(StageNode(stage)).first;
00131 (*si)._override = override;
00132 (*si)._texture = tex;
00133 (*si)._implicit_sort = attrib->_next_implicit_sort;
00134 ++(attrib->_next_implicit_sort);
00135
00136
00137 attrib->_sort_seq = UpdateSeq::old();
00138 attrib->_filtered_seq = UpdateSeq::old();
00139
00140 return return_new(attrib);
00141 }
00142
00143
00144
00145
00146
00147
00148
00149
00150 CPT(RenderAttrib) TextureAttrib::
00151 remove_on_stage(TextureStage *stage) const {
00152 TextureAttrib *attrib = new TextureAttrib(*this);
00153
00154 Stages::iterator si = attrib->_on_stages.find(StageNode(stage));
00155 if (si != attrib->_on_stages.end()) {
00156 attrib->_on_stages.erase(si);
00157
00158 attrib->_sort_seq = UpdateSeq::old();
00159 attrib->_filtered_seq = UpdateSeq::old();
00160 }
00161
00162 return return_new(attrib);
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172 CPT(RenderAttrib) TextureAttrib::
00173 add_off_stage(TextureStage *stage, int override) const {
00174 TextureAttrib *attrib = new TextureAttrib(*this);
00175 if (!_off_all_stages) {
00176 StageNode sn(stage);
00177 Stages::iterator sfi = attrib->_off_stages.insert(sn).first;
00178 (*sfi)._override = override;
00179
00180
00181 Stages::iterator si = attrib->_on_stages.find(sn);
00182 if (si != attrib->_on_stages.end()) {
00183 attrib->_on_stages.erase(si);
00184 attrib->_sort_seq = UpdateSeq::old();
00185 attrib->_filtered_seq = UpdateSeq::old();
00186 }
00187 }
00188 return return_new(attrib);
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198 CPT(RenderAttrib) TextureAttrib::
00199 remove_off_stage(TextureStage *stage) const {
00200 TextureAttrib *attrib = new TextureAttrib(*this);
00201 attrib->_off_stages.erase(StageNode(stage));
00202 return return_new(attrib);
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 CPT(RenderAttrib) TextureAttrib::
00214 unify_texture_stages(TextureStage *stage) const {
00215 PT(TextureAttrib) attrib = new TextureAttrib;
00216
00217 attrib->_off_all_stages = _off_all_stages;
00218 bool any_changed = false;
00219
00220 Stages::const_iterator si;
00221 for (si = _on_stages.begin(); si != _on_stages.end(); ++si) {
00222 TextureStage *this_stage = (*si)._stage;
00223
00224 if (this_stage->get_name() == stage->get_name()) {
00225 this_stage = stage;
00226 any_changed = true;
00227 }
00228
00229 Stages::iterator osi = attrib->_on_stages.insert(StageNode(this_stage)).first;
00230 (*osi)._texture = (*si)._texture;
00231 (*osi)._ff_tc_index = (*si)._ff_tc_index;
00232 (*osi)._implicit_sort = (*si)._implicit_sort;
00233 (*osi)._override = (*si)._override;
00234 }
00235
00236 attrib->_next_implicit_sort = _next_implicit_sort;
00237
00238 Stages::const_iterator fsi;
00239 for (fsi = _off_stages.begin(); fsi != _off_stages.end(); ++fsi) {
00240 TextureStage *this_stage = (*fsi)._stage;
00241
00242 if (this_stage != stage &&
00243 this_stage->get_name() == stage->get_name()) {
00244 this_stage = stage;
00245 any_changed = true;
00246 }
00247
00248 attrib->_off_stages.insert(StageNode(this_stage));
00249 }
00250
00251 if (!any_changed) {
00252 return this;
00253 }
00254
00255 return return_new(attrib);
00256 }
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266 CPT(TextureAttrib) TextureAttrib::
00267 filter_to_max(int max_texture_stages) const {
00268 if ((int)_on_stages.size() <= max_texture_stages) {
00269
00270 return this;
00271 }
00272
00273 if (_filtered_seq != TextureStage::get_sort_seq()) {
00274 ((TextureAttrib *)this)->_filtered.clear();
00275 ((TextureAttrib *)this)->_filtered_seq = TextureStage::get_sort_seq();
00276 }
00277
00278 Filtered::const_iterator fi;
00279 fi = _filtered.find(max_texture_stages);
00280 if (fi != _filtered.end()) {
00281
00282
00283 return (*fi).second;
00284 }
00285
00286
00287
00288
00289 check_sorted();
00290
00291 RenderStages priority_stages = _render_stages;
00292
00293
00294 sort(priority_stages.begin(), priority_stages.end(),
00295 CompareTextureStagePriorities());
00296
00297
00298 priority_stages.erase(priority_stages.begin() + max_texture_stages,
00299 priority_stages.end());
00300
00301
00302 PT(TextureAttrib) attrib = new TextureAttrib;
00303
00304 RenderStages::const_iterator ri;
00305 for (ri = priority_stages.begin(); ri != priority_stages.end(); ++ri) {
00306 attrib->_on_stages.insert(*(*ri));
00307 }
00308
00309 attrib->_next_implicit_sort = _next_implicit_sort;
00310
00311 CPT(RenderAttrib) new_attrib = return_new(attrib);
00312
00313
00314
00315 CPT(TextureAttrib) tex_attrib = (const TextureAttrib *)new_attrib.p();
00316 ((TextureAttrib *)this)->_filtered[max_texture_stages] = tex_attrib;
00317 return tex_attrib;
00318 }
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 bool TextureAttrib::
00348 lower_attrib_can_override() const {
00349
00350
00351
00352
00353
00354
00355 return true;
00356 }
00357
00358
00359
00360
00361
00362
00363 void TextureAttrib::
00364 output(ostream &out) const {
00365 check_sorted();
00366
00367 out << get_type() << ":";
00368 if (_off_stages.empty()) {
00369 if (_on_stages.empty()) {
00370 if (_off_all_stages) {
00371 out << "all off";
00372 } else {
00373 out << "identity";
00374 }
00375 } else {
00376 if (_off_all_stages) {
00377 out << "set";
00378 } else {
00379 out << "on";
00380 }
00381 }
00382
00383 } else {
00384 out << "off";
00385 Stages::const_iterator fi;
00386 for (fi = _off_stages.begin(); fi != _off_stages.end(); ++fi) {
00387 TextureStage *stage = (*fi)._stage;
00388 out << " " << stage->get_name();
00389 if ((*fi)._override != 0) {
00390 out << "^" << (*fi)._override;
00391 }
00392 }
00393
00394 if (!_on_stages.empty()) {
00395 out << " on";
00396 }
00397 }
00398
00399 RenderStages::const_iterator ri;
00400 for (ri = _render_stages.begin(); ri != _render_stages.end(); ++ri) {
00401 const StageNode &sn = *(*ri);
00402 TextureStage *stage = sn._stage;
00403 Texture *tex = sn._texture;
00404 if (tex != NULL) {
00405 out << " " << stage->get_name() << ":" << tex->get_name();
00406 } else {
00407 out << " " << stage->get_name();
00408 }
00409 if (sn._override != 0) {
00410 out << "^" << sn._override;
00411 }
00412 }
00413 }
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424 bool TextureAttrib::
00425 has_cull_callback() const {
00426 Stages::const_iterator si;
00427 for (si = _on_stages.begin(); si != _on_stages.end(); ++si) {
00428 Texture *texture = (*si)._texture;
00429 if (texture->has_cull_callback()) {
00430 return true;
00431 }
00432 }
00433
00434 return false;
00435 }
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 bool TextureAttrib::
00451 cull_callback(CullTraverser *trav, const CullTraverserData &data) const {
00452 Stages::const_iterator si;
00453 for (si = _on_stages.begin(); si != _on_stages.end(); ++si) {
00454 Texture *texture = (*si)._texture;
00455 if (!texture->cull_callback(trav, data)) {
00456 return false;
00457 }
00458 }
00459
00460 return true;
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478 int TextureAttrib::
00479 compare_to_impl(const RenderAttrib *other) const {
00480 const TextureAttrib *ta;
00481 DCAST_INTO_R(ta, other, 0);
00482
00483 if (_off_all_stages != ta->_off_all_stages) {
00484 return (int)_off_all_stages - (int)ta->_off_all_stages;
00485 }
00486
00487 Stages::const_iterator si = _on_stages.begin();
00488 Stages::const_iterator osi = ta->_on_stages.begin();
00489
00490 while (si != _on_stages.end() && osi != ta->_on_stages.end()) {
00491 TextureStage *stage = (*si)._stage;
00492 TextureStage *other_stage = (*osi)._stage;
00493
00494 if (stage != other_stage) {
00495 return stage < other_stage ? -1 : 1;
00496 }
00497
00498 Texture *texture = (*si)._texture;
00499 Texture *other_texture = (*osi)._texture;
00500
00501 if (texture != other_texture) {
00502 return texture < other_texture ? -1 : 1;
00503 }
00504
00505 int implicit_sort = (*si)._implicit_sort;
00506 int other_implicit_sort = (*osi)._implicit_sort;
00507
00508 if (implicit_sort != other_implicit_sort) {
00509 return implicit_sort < other_implicit_sort ? -1 : 1;
00510 }
00511
00512 int override = (*si)._override;
00513 int other_override = (*osi)._override;
00514
00515 if (override != other_override) {
00516 return override < other_override ? -1 : 1;
00517 }
00518
00519 ++si;
00520 ++osi;
00521 }
00522
00523 if (si != _on_stages.end()) {
00524 return 1;
00525 }
00526 if (osi != ta->_on_stages.end()) {
00527 return -1;
00528 }
00529
00530
00531 Stages::const_iterator fi = _off_stages.begin();
00532 Stages::const_iterator ofi = ta->_off_stages.begin();
00533
00534 while (fi != _off_stages.end() && ofi != ta->_off_stages.end()) {
00535 TextureStage *stage = (*fi)._stage;
00536 TextureStage *other_stage = (*ofi)._stage;
00537
00538 if (stage != other_stage) {
00539 return stage < other_stage ? -1 : 1;
00540 }
00541
00542 int override = (*fi)._override;
00543 int other_override = (*ofi)._override;
00544
00545 if (override != other_override) {
00546 return override < other_override ? -1 : 1;
00547 }
00548
00549 ++fi;
00550 ++ofi;
00551 }
00552
00553 if (fi != _off_stages.end()) {
00554 return 1;
00555 }
00556 if (ofi != ta->_off_stages.end()) {
00557 return -1;
00558 }
00559
00560 return 0;
00561 }
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580 CPT(RenderAttrib) TextureAttrib::
00581 compose_impl(const RenderAttrib *other) const {
00582 const TextureAttrib *ta;
00583 DCAST_INTO_R(ta, other, 0);
00584
00585 if (ta->_off_all_stages) {
00586
00587
00588 return ta;
00589 }
00590
00591
00592
00593
00594 Stages::const_iterator ai = _on_stages.begin();
00595 Stages::const_iterator bi = ta->_on_stages.begin();
00596 Stages::const_iterator ci = ta->_off_stages.begin();
00597
00598
00599 TextureAttrib *attrib = new TextureAttrib;
00600
00601 while (ai != _on_stages.end() &&
00602 bi != ta->_on_stages.end() &&
00603 ci != ta->_off_stages.end()) {
00604 if ((*ai)._stage < (*bi)._stage) {
00605 if ((*ai)._stage < (*ci)._stage) {
00606
00607
00608 attrib->_on_stages.insert(attrib->_on_stages.end(), *ai);
00609 ++ai;
00610
00611 } else if ((*ci)._stage < (*ai)._stage) {
00612
00613
00614 ++ci;
00615
00616 } else {
00617
00618
00619 if ((*ai)._override > (*ci)._override) {
00620
00621 attrib->_on_stages.insert(attrib->_on_stages.end(), *ai);
00622 }
00623
00624 ++ai;
00625 ++ci;
00626 }
00627
00628 } else if ((*bi)._stage < (*ai)._stage) {
00629
00630
00631 attrib->_on_stages.insert(attrib->_on_stages.end(), *bi);
00632 ++bi;
00633
00634 } else {
00635
00636 if ((*ai)._override > (*bi)._override) {
00637 attrib->_on_stages.insert(attrib->_on_stages.end(), *ai);
00638 } else {
00639 attrib->_on_stages.insert(attrib->_on_stages.end(), *bi);
00640 }
00641 ++ai;
00642 ++bi;
00643 }
00644 }
00645
00646 while (ai != _on_stages.end() && bi != ta->_on_stages.end()) {
00647 if ((*ai)._stage < (*bi)._stage) {
00648
00649
00650 attrib->_on_stages.insert(attrib->_on_stages.end(), *ai);
00651 ++ai;
00652
00653 } else if ((*bi)._stage < (*ai)._stage) {
00654
00655
00656 attrib->_on_stages.insert(attrib->_on_stages.end(), *bi);
00657 ++bi;
00658
00659 } else {
00660
00661 if ((*ai)._override > (*bi)._override) {
00662 attrib->_on_stages.insert(attrib->_on_stages.end(), *ai);
00663 } else {
00664 attrib->_on_stages.insert(attrib->_on_stages.end(), *bi);
00665 }
00666 ++ai;
00667 ++bi;
00668 }
00669 }
00670
00671 while (ai != _on_stages.end() && ci != ta->_off_stages.end()) {
00672 if ((*ai)._stage < (*ci)._stage) {
00673
00674
00675 attrib->_on_stages.insert(attrib->_on_stages.end(), *ai);
00676 ++ai;
00677
00678 } else if ((*ci)._stage < (*ai)._stage) {
00679
00680
00681 ++ci;
00682
00683 } else {
00684
00685
00686 if ((*ai)._override > (*ci)._override) {
00687
00688 attrib->_on_stages.insert(attrib->_on_stages.end(), *ai);
00689 }
00690 ++ai;
00691 ++ci;
00692 }
00693 }
00694
00695 while (ai != _on_stages.end()) {
00696 attrib->_on_stages.insert(attrib->_on_stages.end(), *ai);
00697 ++ai;
00698 }
00699
00700 while (bi != ta->_on_stages.end()) {
00701 attrib->_on_stages.insert(attrib->_on_stages.end(), *bi);
00702 ++bi;
00703 }
00704
00705 attrib->_next_implicit_sort = _next_implicit_sort + ta->_next_implicit_sort;
00706 attrib->_sort_seq = UpdateSeq::old();
00707 attrib->_filtered_seq = UpdateSeq::old();
00708
00709 return return_new(attrib);
00710 }
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721 CPT(RenderAttrib) TextureAttrib::
00722 invert_compose_impl(const RenderAttrib *other) const {
00723
00724
00725
00726 return other;
00727 }
00728
00729
00730
00731
00732
00733
00734
00735 void TextureAttrib::
00736 register_with_read_factory() {
00737 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00738 }
00739
00740
00741
00742
00743
00744
00745
00746 void TextureAttrib::
00747 write_datagram(BamWriter *manager, Datagram &dg) {
00748 RenderAttrib::write_datagram(manager, dg);
00749
00750
00751 dg.add_bool(_off_all_stages);
00752 dg.add_uint16(get_num_off_stages());
00753 Stages::const_iterator fi;
00754 for (fi = _off_stages.begin(); fi != _off_stages.end(); ++fi) {
00755 TextureStage *stage = (*fi)._stage;
00756 manager->write_pointer(dg, stage);
00757 }
00758
00759
00760 dg.add_uint16(get_num_on_stages());
00761 Stages::const_iterator si;
00762 for (si = _on_stages.begin(); si != _on_stages.end(); ++si) {
00763 TextureStage *stage = (*si)._stage;
00764 Texture *tex = (*si)._texture;
00765 nassertv(tex != (Texture *)NULL);
00766
00767 manager->write_pointer(dg, stage);
00768 manager->write_pointer(dg, tex);
00769 dg.add_uint16((*si)._implicit_sort);
00770 dg.add_int32((*si)._override);
00771 }
00772 }
00773
00774
00775
00776
00777
00778
00779
00780
00781 int TextureAttrib::
00782 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00783 int pi = RenderAttrib::complete_pointers(p_list, manager);
00784
00785 Stages::iterator ci;
00786 for (ci = _off_stages.begin(); ci != _off_stages.end(); ++ci) {
00787 TextureStage *ts = DCAST(TextureStage, p_list[pi++]);
00788 *ci = StageNode(ts);
00789 }
00790
00791 size_t sni = 0;
00792 while (sni < _on_stages.size()) {
00793
00794 PT(TextureStage) ts = DCAST(TextureStage, p_list[pi++]);
00795 ts = TextureStagePool::get_stage(ts);
00796
00797
00798
00799 Texture *tex = DCAST(Texture, p_list[pi++]);
00800
00801 if (tex != (Texture *)NULL) {
00802 StageNode &sn = _on_stages[sni];
00803 sn._stage = ts;
00804 sn._texture = tex;
00805 ++sni;
00806
00807 } else {
00808
00809
00810 _off_stages.push_back(StageNode(ts));
00811 _on_stages.erase(_on_stages.begin() + sni);
00812 }
00813 }
00814 _on_stages.sort();
00815 _sort_seq = UpdateSeq::old();
00816 _filtered_seq = UpdateSeq::old();
00817
00818 return pi;
00819 }
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829 TypedWritable *TextureAttrib::
00830 make_from_bam(const FactoryParams ¶ms) {
00831 TextureAttrib *attrib = new TextureAttrib;
00832 DatagramIterator scan;
00833 BamReader *manager;
00834
00835 parse_params(params, scan, manager);
00836 attrib->fillin(scan, manager);
00837
00838 return attrib;
00839 }
00840
00841
00842
00843
00844
00845
00846
00847
00848 void TextureAttrib::
00849 fillin(DatagramIterator &scan, BamReader *manager) {
00850 RenderAttrib::fillin(scan, manager);
00851
00852
00853 _off_all_stages = scan.get_bool();
00854 int num_off_stages = scan.get_uint16();
00855
00856
00857
00858 int i;
00859 _off_stages.reserve(num_off_stages);
00860 for (i = 0; i < num_off_stages; i++) {
00861 manager->read_pointer(scan);
00862 _off_stages.push_back(StageNode(NULL));
00863 }
00864
00865
00866 int num_on_stages = scan.get_uint16();
00867
00868
00869
00870
00871 _on_stages.reserve(num_on_stages);
00872 _next_implicit_sort = 0;
00873 for (i = 0; i < num_on_stages; i++) {
00874 manager->read_pointer(scan);
00875 manager->read_pointer(scan);
00876 unsigned int implicit_sort;
00877 if (manager->get_file_minor_ver() >= 15) {
00878 implicit_sort = scan.get_uint16();
00879 } else {
00880 implicit_sort = (unsigned int)i;
00881 }
00882 int override = 0;
00883 if (manager->get_file_minor_ver() >= 23) {
00884 override = scan.get_int32();
00885 }
00886
00887 _next_implicit_sort = max(_next_implicit_sort, implicit_sort + 1);
00888 _on_stages.push_back(StageNode(NULL, _next_implicit_sort, override));
00889 ++_next_implicit_sort;
00890 }
00891 }
00892
00893
00894
00895
00896
00897
00898
00899
00900 void TextureAttrib::
00901 sort_on_stages() {
00902 typedef pmap<const InternalName *, int> UsedTexcoordIndex;
00903 UsedTexcoordIndex used_texcoord_index;
00904
00905 _render_stages.clear();
00906 _render_ff_stages.clear();
00907
00908 Stages::iterator si;
00909 for (si = _on_stages.begin(); si != _on_stages.end(); ++si) {
00910 StageNode &sn = (*si);
00911 TextureStage *stage = sn._stage;
00912 nassertv(stage != NULL);
00913 if (stage->is_fixed_function()) {
00914 const InternalName *name = stage->get_texcoord_name();
00915
00916
00917
00918
00919
00920 UsedTexcoordIndex::iterator ti = used_texcoord_index.insert(UsedTexcoordIndex::value_type(name, (int)used_texcoord_index.size())).first;
00921 (*si)._ff_tc_index = (*ti).second;
00922
00923 _render_ff_stages.push_back(&sn);
00924 } else {
00925 (*si)._ff_tc_index = -1;
00926 }
00927
00928 _render_stages.push_back(&sn);
00929 }
00930
00931 sort(_render_stages.begin(), _render_stages.end(), CompareTextureStageSort());
00932 sort(_render_ff_stages.begin(), _render_ff_stages.end(), CompareTextureStageSort());
00933
00934
00935
00936
00937
00938
00939
00940 _sort_seq = TextureStage::get_sort_seq();
00941 }