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