Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/pgraph/cullBinManager.cxx

Go to the documentation of this file.
00001 // Filename: cullBinManager.cxx
00002 // Created by:  drose (28Feb02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
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 //     Function: CullBinManager::Constructor
00034 //       Access: Protected
00035 //  Description: The constructor is not intended to be called
00036 //               directly; there is only one CullBinManager and it
00037 //               constructs itself.  This could have been a private
00038 //               constructor, but gcc issues a spurious warning if the
00039 //               constructor is private and the class has no friends.
00040 ////////////////////////////////////////////////////////////////////
00041 CullBinManager::
00042 CullBinManager() {
00043   _bins_are_sorted = true;
00044   _unused_bin_index = false;
00045 
00046   setup_initial_bins();
00047 }
00048 
00049 ////////////////////////////////////////////////////////////////////
00050 //     Function: CullBinManager::Destructor
00051 //       Access: Protected
00052 //  Description: Don't call the destructor.
00053 ////////////////////////////////////////////////////////////////////
00054 CullBinManager::
00055 ~CullBinManager() {
00056 }
00057 
00058 ////////////////////////////////////////////////////////////////////
00059 //     Function: CullBinManager::add_bin
00060 //       Access: Published
00061 //  Description: Defines a new bin with the indicated name, and
00062 //               returns the new bin_index.  If there is already a bin
00063 //               with the same name returns its bin_index if it had
00064 //               the same properties; otherwise, reports an error and
00065 //               returns -1.
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     // We already have such a bin.  This is not a problem if the bin
00072     // has the same properties.
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     // Nope, the old bin had different properties.  Too bad.
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   // No bin by that name already; choose a bin_index to assign to the
00089   // newly created bin.
00090   int new_bin_index = -1;
00091   if (_unused_bin_index) {
00092     // If there is some bin index that's not being used, we can claim
00093     // it.
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       // Oops, maybe we've used up all the unused indices already.
00103       _unused_bin_index = false;
00104     }
00105   }
00106 
00107   if (new_bin_index == -1) {
00108     // Slot a new index on the end of the vector.
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 //     Function: CullBinManager::remove_bin
00128 //       Access: Published
00129 //  Description: Permanently removes the indicated bin.  This
00130 //               operation is not protected from the pipeline and will
00131 //               disturb whatever is currently rendering in draw.  You
00132 //               should not call this during the normal course of
00133 //               rendering a frame; it is intended only as an aid to
00134 //               development, to allow the developer to interactively
00135 //               fiddle with the set of bins.
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   // Now we have to make sure all of the data objects in the world
00150   // that had cached this bin index or have a bin object are correctly
00151   // updated.
00152   
00153   // First, tell all the RenderStates in the world to reset their bin
00154   // index cache.
00155   RenderState::bin_removed(bin_index);
00156 
00157   // Now tell all the CullResults to clear themselves up too.
00158   CullResult::bin_removed(bin_index);
00159 }
00160 
00161 ////////////////////////////////////////////////////////////////////
00162 //     Function: CullBinManager::find_bin
00163 //       Access: Published
00164 //  Description: Returns the bin_index associated with the bin of the
00165 //               given name, or -1 if no bin has that name.
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 //     Function: CullBinManager::get_global_ptr
00179 //       Access: Published, Static
00180 //  Description: Returns the pointer to the global CullBinManager
00181 //               object.
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 //     Function: CullBinManager::make_new_bin
00193 //       Access: Public
00194 //  Description: Intended to be called by CullResult when a new
00195 //               CullBin pointer corresponding to the indicated
00196 //               bin_index is required.  It allocates and returns a
00197 //               brand new CullBin object of the appropriate type.
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 //     Function: CullBinManager::do_sort_bins
00221 //       Access: Private
00222 //  Description: Puts the _sorted_bins vector in proper rendering
00223 //               order.
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 //     Function: CullBinManager::setup_initial_bins
00233 //       Access: Private
00234 //  Description: Called only at construction time to create the
00235 //               default bins and the bins specified in the Configrc
00236 //               file.
00237 ////////////////////////////////////////////////////////////////////
00238 void CullBinManager::
00239 setup_initial_bins() {
00240   // First, add all of the bins specified in the Configrc file.
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     // This is a string in three tokens, separated by whitespace:
00249     //    bin_name sort type
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   // Now add the default bins, unless the names have already been
00279   // specified explicitly in the Config file, above.
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 //     Function: CullBinManager::parse_bin_type
00299 //       Access: Private, Static
00300 //  Description: Given the name of a bin type, returns the
00301 //               corresponding BinType value, or BT_invalid if it is
00302 //               an unknown type.
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 }

Generated on Fri May 2 00:41:26 2003 for Panda by doxygen1.3