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