Panda3D

cullBinManager.cxx
Go to the documentation of this file.
1 /**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file cullBinManager.cxx
10 * @author drose
11 * @date 2002-02-28
12 */
13
14 #include "cullBinManager.h"
15 #include "renderState.h"
16 #include "cullResult.h"
17 #include "config_pgraph.h"
18 #include "string_utils.h"
19 #include "configVariableColor.h"
20
21 using std::string;
22
23 CullBinManager *CullBinManager::_global_ptr = nullptr;
24
25 /**
26 * The constructor is not intended to be called directly; there is only one
27 * CullBinManager and it constructs itself. This could have been a private
28 * constructor, but gcc issues a spurious warning if the constructor is
29 * private and the class has no friends.
30 */
31 CullBinManager::
32 CullBinManager() {
33 _bins_are_sorted = true;
34 _unused_bin_index = false;
35
36 setup_initial_bins();
37 }
38
39 /**
40 * Don't call the destructor.
41 */
42 CullBinManager::
43 ~CullBinManager() {
44 }
45
46 /**
47 * Defines a new bin with the indicated name, and returns the new bin_index.
48 * If there is already a bin with the same name returns its bin_index if it
49 * had the same properties; otherwise, reports an error and returns -1.
50 */
51 int CullBinManager::
52 add_bin(const string &name, BinType type, int sort) {
53 BinsByName::const_iterator bni = _bins_by_name.find(name);
54 if (bni != _bins_by_name.end()) {
55 // We already have such a bin. This is not a problem if the bin has the
56 // same properties.
57 int bin_index = (*bni).second;
58 nassertr(bin_index >= 0 && bin_index < (int)_bin_definitions.size(), -1);
59 const BinDefinition &def = _bin_definitions[bin_index];
60 nassertr(def._in_use, -1);
61 if (def._type == type && def._sort == sort) {
62 return bin_index;
63 }
64
65 // Nope, the old bin had different properties. Too bad.
66 pgraph_cat.warning()
67 << "Cannot create a bin named " << name
68 << "; already have a bin by that name.\n";
69 return -1;
70 }
71
72 // No bin by that name already; choose a bin_index to assign to the newly
73 // created bin.
74 int new_bin_index = -1;
75 if (_unused_bin_index) {
76 // If there is some bin index that's not being used, we can claim it.
77 int i = 0;
78 for (i = 0; i < (int)_bin_definitions.size() && new_bin_index == -1; i++) {
79 if (!_bin_definitions[i]._in_use) {
80 new_bin_index = i;
81 }
82 }
83
84 if (new_bin_index == -1) {
85 // Oops, maybe we've used up all the unused indices already.
86 _unused_bin_index = false;
87 }
88 }
89
90 if (new_bin_index == -1) {
91 // Slot a new index on the end of the vector.
92 new_bin_index = _bin_definitions.size();
93 _bin_definitions.push_back(BinDefinition());
94 }
95
96 BinDefinition &def = _bin_definitions[new_bin_index];
97 def._in_use = true;
98 def._name = name;
99 def._type = type;
100 def._sort = sort;
101 def._active = true;
102
103 #ifndef NDEBUG
104 // Check if there was a flash color configured for this bin name.
105 ConfigVariableColor flash_bin
106 ("flash-bin-" + name, "", "", ConfigVariable::F_dynamic);
107 if (flash_bin.get_num_words() == 0) {
108 def._flash_active = false;
109 } else {
110 def._flash_active = true;
111 def._flash_color = flash_bin.get_value();
112 }
113 #endif
114
115 _bins_by_name.insert(BinsByName::value_type(name, new_bin_index));
116 _sorted_bins.push_back(new_bin_index);
117 _bins_are_sorted = false;
118
119 return new_bin_index;
120 }
121
122 /**
123 * Permanently removes the indicated bin. This operation is not protected
124 * from the pipeline and will disturb whatever is currently rendering in draw.
125 * You should not call this during the normal course of rendering a frame; it
126 * is intended only as an aid to development, to allow the developer to
127 * interactively fiddle with the set of bins.
128 */
129 void CullBinManager::
130 remove_bin(int bin_index) {
131 nassertv(bin_index >= 0 && bin_index < (int)_bin_definitions.size());
132 nassertv(_bin_definitions[bin_index]._in_use);
133
134 _bin_definitions[bin_index]._in_use = false;
135 SortedBins::iterator si =
136 find(_sorted_bins.begin(), _sorted_bins.end(), bin_index);
137 nassertv(si != _sorted_bins.end());
138 _sorted_bins.erase(si);
139 _bins_by_name.erase(_bin_definitions[bin_index]._name);
140
141 // Now we have to make sure all of the data objects in the world that had
142 // cached this bin index or have a bin object are correctly updated.
143
144 // First, tell all the RenderStates in the world to reset their bin index
145 // cache.
146 RenderState::bin_removed(bin_index);
147
148 // Now tell all the CullResults to clear themselves up too.
149 CullResult::bin_removed(bin_index);
150 }
151
152 /**
153 * Returns the bin_index associated with the bin of the given name, or -1 if
154 * no bin has that name.
155 */
156 int CullBinManager::
157 find_bin(const string &name) const {
158 BinsByName::const_iterator bni;
159 bni = _bins_by_name.find(name);
160 if (bni != _bins_by_name.end()) {
161 return (*bni).second;
162 }
163 return -1;
164 }
165
166 /**
167 *
168 */
169 void CullBinManager::
170 write(std::ostream &out) const {
171 if (!_bins_are_sorted) {
172 ((CullBinManager *)this)->do_sort_bins();
173 }
174 SortedBins::const_iterator sbi;
175 for (sbi = _sorted_bins.begin(); sbi != _sorted_bins.end(); ++sbi) {
176 int bin_index = (*sbi);
177 out << get_bin_name(bin_index) << ", " << get_bin_type(bin_index)
178 << ", " << get_bin_sort(bin_index) << "\n";
179 }
180 }
181
182 /**
183 * Intended to be called by CullResult when a new CullBin pointer
184 * corresponding to the indicated bin_index is required. It allocates and
185 * returns a brand new CullBin object of the appropriate type.
186 */
187 PT(CullBin) CullBinManager::
188 make_new_bin(int bin_index, GraphicsStateGuardianBase *gsg,
189 const PStatCollector &draw_region_pcollector) {
190 nassertr(bin_index >= 0 && bin_index < (int)_bin_definitions.size(), nullptr);
191 nassertr(_bin_definitions[bin_index]._in_use, nullptr);
192 string name = get_bin_name(bin_index);
193
194 BinType type = _bin_definitions[bin_index]._type;
195 BinConstructors::const_iterator ci = _bin_constructors.find(type);
196 if (ci != _bin_constructors.end()) {
197 BinConstructor *constructor = (*ci).second;
198 return constructor(name, gsg, draw_region_pcollector);
199 }
200
201 // Hmm, unknown (or unregistered) bin type.
202 nassert_raise("unknown bin type");
203 return nullptr;
204 }
205
206 /**
207 * Intended to be called at startup type by each CullBin type, to register the
208 * constructor for each type.
209 */
210 void CullBinManager::
211 register_bin_type(BinType type, CullBinManager::BinConstructor *constructor) {
212 bool inserted = _bin_constructors.insert(BinConstructors::value_type(type, constructor)).second;
213 nassertv(inserted);
214 }
215
216 /**
217 * Puts the _sorted_bins vector in proper rendering order.
218 */
219 void CullBinManager::
220 do_sort_bins() {
221 sort(_sorted_bins.begin(), _sorted_bins.end(), SortBins(this));
222 _bins_are_sorted = true;
223 }
224
225 /**
226 * Called only at construction time to create the default bins and the bins
227 * specified in the Configrc file.
228 */
229 void CullBinManager::
230 setup_initial_bins() {
231 ConfigVariableList cull_bin
232 ("cull-bin",
233 PRC_DESC("Creates a new cull bin by name, with the specified properties. "
234 "This is a string in three tokens, separated by whitespace: "
235 "'bin_name sort type'."));
236
237 // First, add all of the bins specified in the Configrc file.
238 int num_bins = cull_bin.get_num_unique_values();
239
240 for (int bi = 0; bi < num_bins; bi++) {
241 string def = cull_bin.get_unique_value(bi);
242
243 // This is a string in three tokens, separated by whitespace: bin_name
244 // sort type
245
246 vector_string words;
247 extract_words(def, words);
248
249 if (words.size() != 3) {
250 pgraph_cat.error()
251 << "Invalid cull-bin definition: " << def << "\n"
252 << "Definition should be three words: bin_name sort type\n";
253 } else {
254 int sort;
255 if (!string_to_int(words[1], sort)) {
256 pgraph_cat.error()
257 << "Invalid cull-bin definition: " << def << "\n"
258 << "Sort token " << words[1] << " is not an integer.\n";
259
260 } else {
261 BinType type = parse_bin_type(words[2]);
262 if (type == BT_invalid) {
263 pgraph_cat.error()
264 << "Invalid cull-bin definition: " << def << "\n"
265 << "Bin type " << words[2] << " is not known.\n";
266 } else {
267 add_bin(words[0], type, sort);
268 }
269 }
270 }
271 }
272
273 // Now add the default bins, unless the names have already been specified
274 // explicitly in the Config file, above.
275 if (find_bin("background") == -1) {
276 add_bin("background", BT_fixed, 10);
277 }
278 if (find_bin("opaque") == -1) {
279 add_bin("opaque", BT_state_sorted, 20);
280 }
281 if (find_bin("transparent") == -1) {
282 add_bin("transparent", BT_back_to_front, 30);
283 }
284 if (find_bin("fixed") == -1) {
285 add_bin("fixed", BT_fixed, 40);
286 }
287 if (find_bin("unsorted") == -1) {
288 add_bin("unsorted", BT_unsorted, 50);
289 }
290 }
291
292 /**
293 * Given the name of a bin type, returns the corresponding BinType value, or
294 * BT_invalid if it is an unknown type.
295 */
296 CullBinManager::BinType CullBinManager::
297 parse_bin_type(const string &bin_type) {
298 if (cmp_nocase_uh(bin_type, "unsorted") == 0) {
299 return BT_unsorted;
300
301 } else if (cmp_nocase_uh(bin_type, "state_sorted") == 0) {
302 return BT_state_sorted;
303
304 } else if (cmp_nocase_uh(bin_type, "fixed") == 0) {
305 return BT_fixed;
306
307 } else if (cmp_nocase_uh(bin_type, "back_to_front") == 0) {
308 return BT_back_to_front;
309
310 } else if (cmp_nocase_uh(bin_type, "front_to_back") == 0) {
311 return BT_front_to_back;
312
313 } else {
314 return BT_invalid;
315 }
316 }
317
318 /**
319 *
320 */
321 std::ostream &
322 operator << (std::ostream &out, CullBinManager::BinType bin_type) {
323 switch (bin_type) {
324 case CullBinManager::BT_invalid:
325 return out << "invalid";
326
327 case CullBinManager::BT_unsorted:
328 return out << "unsorted";
329
330 case CullBinManager::BT_state_sorted:
331 return out << "state_sorted";
332
333 case CullBinManager::BT_back_to_front:
334 return out << "back_to_front";
335
336 case CullBinManager::BT_front_to_back:
337 return out << "front_to_back";
338
339 case CullBinManager::BT_fixed:
340 return out << "fixed";
341 }
342
343 return out << "**invalid BinType(" << (int)bin_type << ")**";
344 }
ConfigVariableColor
This is a convenience class to specialize ConfigVariable as a set of floating-point types representin...
Definition: configVariableColor.h:35
ConfigVariableColor::get_value
const LColor & get_value() const
Returns the variable's value.
Definition: configVariableColor.I:103
ConfigVariableList
This class is similar to ConfigVariable, but it reports its value as a list of strings.
Definition: configVariableList.h:31
ConfigVariable::get_num_words
size_t get_num_words() const
Returns the number of words in the variable's value.
Definition: configVariable.I:100
CullBinManager
This is a global object that maintains the collection of named CullBins in the world.
Definition: cullBinManager.h:34
CullBinManager::get_bin_type
BinType get_bin_type(int bin_index) const
Returns the type of the bin with the indicated bin_index (where bin_index was retrieved by get_bin() ...
Definition: cullBinManager.I:78
CullBinManager::register_bin_type
void register_bin_type(BinType type, BinConstructor *constructor)
Intended to be called at startup type by each CullBin type, to register the constructor for each type...
Definition: cullBinManager.cxx:211
CullBinManager::remove_bin
void remove_bin(int bin_index)
Permanently removes the indicated bin.
Definition: cullBinManager.cxx:130
CullBinManager::get_bin_sort
int get_bin_sort(int bin_index) const
Returns the sort order of the bin with the indicated bin_index (where bin_index was retrieved by get_...
Definition: cullBinManager.I:129
CullBinManager::get_bin_name
std::string get_bin_name(int bin_index) const
Returns the name of the bin with the indicated bin_index (where bin_index was retrieved by get_bin() ...
Definition: cullBinManager.I:67
CullBinManager::add_bin
int add_bin(const std::string &name, BinType type, int sort)
Defines a new bin with the indicated name, and returns the new bin_index.
Definition: cullBinManager.cxx:52
CullBinManager::find_bin
int find_bin(const std::string &name) const
Returns the bin_index associated with the bin of the given name, or -1 if no bin has that name.
Definition: cullBinManager.cxx:157
CullBin
A collection of Geoms and their associated state, for a particular scene.
Definition: cullBin.h:40
CullResult::bin_removed
static void bin_removed(int bin_index)
Intended to be called by CullBinManager::remove_bin(), this informs all the CullResults in the world ...
Definition: cullResult.cxx:344
GraphicsStateGuardianBase
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
Definition: graphicsStateGuardianBase.h:110
PStatCollector
A lightweight class that represents a single element that may be timed and/or counted via stats.
Definition: pStatCollector.h:43
RenderState::bin_removed
static void bin_removed(int bin_index)
Intended to be called by CullBinManager::remove_bin(), this informs all the RenderStates in the world...
Definition: renderState.cxx:1187
configVariableColor.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
config_pgraph.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PT
PT(CullBin) CullBinManager
Intended to be called by CullResult when a new CullBin pointer corresponding to the indicated bin_ind...
Definition: cullBinManager.cxx:187
cullBinManager.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
cullResult.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
renderState.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
extract_words
int extract_words(const string &str, vector_string &words)
Divides the string into a number of words according to whitespace.
Definition: string_utils.cxx:105
string_to_int
int string_to_int(const string &str, string &tail)
A string-interface wrapper around the C library strtol().
Definition: string_utils.cxx:324
string_utils.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.