00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "cullBinManager.h"
00020 #include "cullBinBackToFront.h"
00021 #include "cullBinFrontToBack.h"
00022 #include "cullBinFixed.h"
00023 #include "cullBinUnsorted.h"
00024 #include "renderState.h"
00025 #include "cullResult.h"
00026 #include "config_pgraph.h"
00027 #include "string_utils.h"
00028
00029
00030 CullBinManager *CullBinManager::_global_ptr = (CullBinManager *)NULL;
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 CullBinManager::
00042 CullBinManager() {
00043 _bins_are_sorted = true;
00044 _unused_bin_index = false;
00045
00046 setup_initial_bins();
00047 }
00048
00049
00050
00051
00052
00053
00054 CullBinManager::
00055 ~CullBinManager() {
00056 }
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 int CullBinManager::
00068 add_bin(const string &name, BinType type, int sort) {
00069 BinsByName::const_iterator bni = _bins_by_name.find(name);
00070 if (bni != _bins_by_name.end()) {
00071
00072
00073 int bin_index = (*bni).second;
00074 nassertr(bin_index >= 0 && bin_index < (int)_bin_definitions.size(), -1);
00075 const BinDefinition &def = _bin_definitions[bin_index];
00076 nassertr(def._in_use, -1);
00077 if (def._type == type && def._sort == sort) {
00078 return bin_index;
00079 }
00080
00081
00082 pgraph_cat.warning()
00083 << "Cannot create a bin named " << name
00084 << "; already have a bin by that name.\n";
00085 return -1;
00086 }
00087
00088
00089
00090 int new_bin_index = -1;
00091 if (_unused_bin_index) {
00092
00093
00094 int i = 0;
00095 for (i = 0; i < (int)_bin_definitions.size() && new_bin_index == -1; i++) {
00096 if (!_bin_definitions[i]._in_use) {
00097 new_bin_index = i;
00098 }
00099 }
00100
00101 if (new_bin_index == -1) {
00102
00103 _unused_bin_index = false;
00104 }
00105 }
00106
00107 if (new_bin_index == -1) {
00108
00109 new_bin_index = _bin_definitions.size();
00110 _bin_definitions.push_back(BinDefinition());
00111 }
00112
00113 BinDefinition &def = _bin_definitions[new_bin_index];
00114 def._in_use = true;
00115 def._name = name;
00116 def._type = type;
00117 def._sort = sort;
00118
00119 _bins_by_name.insert(BinsByName::value_type(name, new_bin_index));
00120 _sorted_bins.push_back(new_bin_index);
00121 _bins_are_sorted = false;
00122
00123 return new_bin_index;
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 void CullBinManager::
00138 remove_bin(int bin_index) {
00139 nassertv(bin_index >= 0 && bin_index < (int)_bin_definitions.size());
00140 nassertv(_bin_definitions[bin_index]._in_use);
00141
00142 _bin_definitions[bin_index]._in_use = false;
00143 SortedBins::iterator si =
00144 find(_sorted_bins.begin(), _sorted_bins.end(), bin_index);
00145 nassertv(si != _sorted_bins.end());
00146 _sorted_bins.erase(si);
00147 _bins_by_name.erase(_bin_definitions[bin_index]._name);
00148
00149
00150
00151
00152
00153
00154
00155 RenderState::bin_removed(bin_index);
00156
00157
00158 CullResult::bin_removed(bin_index);
00159 }
00160
00161
00162
00163
00164
00165
00166
00167 int CullBinManager::
00168 find_bin(const string &name) const {
00169 BinsByName::const_iterator bni;
00170 bni = _bins_by_name.find(name);
00171 if (bni != _bins_by_name.end()) {
00172 return (*bni).second;
00173 }
00174 return -1;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183 CullBinManager *CullBinManager::
00184 get_global_ptr() {
00185 if (_global_ptr == (CullBinManager *)NULL) {
00186 _global_ptr = new CullBinManager;
00187 }
00188 return _global_ptr;
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 PT(CullBin) CullBinManager::
00200 make_new_bin(int bin_index, GraphicsStateGuardianBase *gsg) {
00201 nassertr(bin_index >= 0 && bin_index < (int)_bin_definitions.size(), NULL);
00202 nassertr(_bin_definitions[bin_index]._in_use, NULL);
00203
00204 switch (_bin_definitions[bin_index]._type) {
00205 case BT_back_to_front:
00206 return new CullBinBackToFront(gsg);
00207
00208 case BT_front_to_back:
00209 return new CullBinFrontToBack(gsg);
00210
00211 case BT_fixed:
00212 return new CullBinFixed(gsg);
00213
00214 default:
00215 return new CullBinUnsorted(gsg);
00216 }
00217 }
00218
00219
00220
00221
00222
00223
00224
00225 void CullBinManager::
00226 do_sort_bins() {
00227 sort(_sorted_bins.begin(), _sorted_bins.end(), SortBins(this));
00228 _bins_are_sorted = true;
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238 void CullBinManager::
00239 setup_initial_bins() {
00240
00241 Config::ConfigTable::Symbol cull_bins;
00242 config_pgraph.GetAll("cull-bin", cull_bins);
00243
00244 Config::ConfigTable::Symbol::iterator bi;
00245 for (bi = cull_bins.begin(); bi != cull_bins.end(); ++bi) {
00246 ConfigString def = (*bi).Val();
00247
00248
00249
00250
00251 vector_string words;
00252 extract_words(def, words);
00253
00254 if (words.size() != 3) {
00255 pgraph_cat.error()
00256 << "Invalid cull-bin definition: " << def << "\n"
00257 << "Definition should be three words: bin_name sort type\n";
00258 } else {
00259 int sort;
00260 if (!string_to_int(words[1], sort)) {
00261 pgraph_cat.error()
00262 << "Invalid cull-bin definition: " << def << "\n"
00263 << "Sort token " << words[1] << " is not an integer.\n";
00264
00265 } else {
00266 BinType type = parse_bin_type(words[2]);
00267 if (type == BT_invalid) {
00268 pgraph_cat.error()
00269 << "Invalid cull-bin definition: " << def << "\n"
00270 << "Bin type " << words[2] << " is not known.\n";
00271 } else {
00272 add_bin(words[0], type, sort);
00273 }
00274 }
00275 }
00276 }
00277
00278
00279
00280 if (find_bin("background") == -1) {
00281 add_bin("background", BT_fixed, 10);
00282 }
00283 if (find_bin("opaque") == -1) {
00284 add_bin("opaque", BT_state_sorted, 20);
00285 }
00286 if (find_bin("transparent") == -1) {
00287 add_bin("transparent", BT_back_to_front, 30);
00288 }
00289 if (find_bin("fixed") == -1) {
00290 add_bin("fixed", BT_fixed, 40);
00291 }
00292 if (find_bin("unsorted") == -1) {
00293 add_bin("unsorted", BT_unsorted, 50);
00294 }
00295 }
00296
00297
00298
00299
00300
00301
00302
00303
00304 CullBinManager::BinType CullBinManager::
00305 parse_bin_type(const string &bin_type) {
00306 if (cmp_nocase_uh(bin_type, "unsorted") == 0) {
00307 return BT_unsorted;
00308
00309 } else if (cmp_nocase_uh(bin_type, "state_sorted") == 0) {
00310 return BT_state_sorted;
00311
00312 } else if (cmp_nocase_uh(bin_type, "statesorted") == 0) {
00313 return BT_state_sorted;
00314
00315 } else if (cmp_nocase_uh(bin_type, "fixed") == 0) {
00316 return BT_fixed;
00317
00318 } else if (cmp_nocase_uh(bin_type, "back_to_front") == 0) {
00319 return BT_back_to_front;
00320
00321 } else if (cmp_nocase_uh(bin_type, "backtofront") == 0) {
00322 return BT_back_to_front;
00323
00324 } else if (cmp_nocase_uh(bin_type, "front_to_back") == 0) {
00325 return BT_front_to_back;
00326
00327 } else if (cmp_nocase_uh(bin_type, "fronttoback") == 0) {
00328 return BT_front_to_back;
00329
00330 } else {
00331 return BT_invalid;
00332 }
00333 }