Panda3D
cullResult.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 cullResult.cxx
10  * @author drose
11  * @date 2002-02-28
12  */
13 
14 #include "cullResult.h"
15 #include "cullBinManager.h"
16 #include "cullBinAttrib.h"
17 #include "textureAttrib.h"
18 #include "lightAttrib.h"
19 #include "colorAttrib.h"
20 #include "alphaTestAttrib.h"
21 #include "depthWriteAttrib.h"
22 #include "colorScaleAttrib.h"
23 #include "fogAttrib.h"
24 #include "transparencyAttrib.h"
25 #include "renderState.h"
26 #include "rescaleNormalAttrib.h"
27 #include "clockObject.h"
28 #include "config_pgraph.h"
29 #include "depthOffsetAttrib.h"
30 #include "colorBlendAttrib.h"
31 
32 TypeHandle CullResult::_type_handle;
33 
34 /*
35  * This value is used instead of 1.0 to represent the alpha level of a pixel
36  * that is to be considered "opaque" for the purposes of M_dual. Ideally, 1.0
37  * is the only correct value for this. Realistically, we have to fudge it
38  * lower for two reasons: (1) The modelers tend to paint textures with very
39  * slight transparency levels in places that are not intended to be
40  * transparent, without realizing it. These very faint transparency regions
41  * are normally (almost) invisible, but when rendered with M_dual they may be
42  * revealed as regions of poor alpha sorting. (2) There seems to be some
43  * problem in DX where, in certain circumstances apparently related to
44  * automatic texture management, it spontaneously drops out the bottom two
45  * bits of an eight-bit alpha channel, causing a value of 255 to become a
46  * value of 252 instead. We use 256 as the denominator here (instead of, say,
47  * 255) because a fractional power of two will have a terminating
48  * representation in base 2, and thus will be more likely to have a precise
49  * value in whatever internal representation the graphics API will use.
50  */
51 static const PN_stdfloat dual_opaque_level = 252.0 / 256.0;
52 static const double bin_color_flash_rate = 1.0; // 1 state change per second
53 
54 /**
55  *
56  */
57 CullResult::
58 CullResult(GraphicsStateGuardianBase *gsg,
59  const PStatCollector &draw_region_pcollector) :
60  _gsg(gsg),
61  _draw_region_pcollector(draw_region_pcollector)
62 {
63 #ifdef DO_MEMORY_USAGE
64  MemoryUsage::update_type(this, get_class_type());
65 #endif
66 
67 #ifndef NDEBUG
68  _show_transparency = show_transparency.get_value();
69 #endif
70 }
71 
72 /**
73  * Returns a newly-allocated CullResult object that contains a copy of just
74  * the subset of the data from this CullResult object that is worth keeping
75  * around for next frame.
76  */
77 PT(CullResult) CullResult::
78 make_next() const {
79  PT(CullResult) new_result = new CullResult(_gsg, _draw_region_pcollector);
80  new_result->_bins.reserve(_bins.size());
81 
83 
84  for (size_t i = 0; i < _bins.size(); ++i) {
85  CullBin *old_bin = _bins[i];
86  if (old_bin == nullptr ||
87  old_bin->get_bin_type() != bin_manager->get_bin_type(i)) {
88  new_result->_bins.push_back(nullptr);
89  } else {
90  new_result->_bins.push_back(old_bin->make_next());
91  }
92  }
93 
94  return new_result;
95 }
96 
97 /**
98  * Adds the indicated CullableObject to the appropriate bin. The bin becomes
99  * the owner of the object pointer, and will eventually delete it.
100  */
101 void CullResult::
102 add_object(CullableObject *object, const CullTraverser *traverser) {
103  static const LColor flash_alpha_color(0.92, 0.96, 0.10, 1.0f);
104  static const LColor flash_binary_color(0.21f, 0.67f, 0.24, 1.0f);
105  static const LColor flash_multisample_color(0.78f, 0.05f, 0.81f, 1.0f);
106  static const LColor flash_dual_color(0.92, 0.01f, 0.01f, 1.0f);
107 
108  nassertv(object->_draw_callback != nullptr || object->_geom != nullptr);
109 
110  bool force = !traverser->get_effective_incomplete_render();
111  Thread *current_thread = traverser->get_current_thread();
113 
114  // This is probably a good time to check for an auto rescale setting.
115  const RescaleNormalAttrib *rescale;
116  object->_state->get_attrib_def(rescale);
117  if (rescale->get_mode() == RescaleNormalAttrib::M_auto) {
118  RescaleNormalAttrib::Mode mode;
119 
120  if (object->_internal_transform->has_identity_scale()) {
121  mode = RescaleNormalAttrib::M_none;
122  } else if (object->_internal_transform->has_uniform_scale()) {
123  mode = RescaleNormalAttrib::M_rescale;
124  } else {
125  mode = RescaleNormalAttrib::M_normalize;
126  }
127 
128  object->_state = object->_state->compose(get_rescale_normal_state(mode));
129  }
130 
131  // Check for a special wireframe setting.
132  const RenderModeAttrib *rmode;
133  if (object->_state->get_attrib(rmode)) {
134  if (rmode->get_mode() == RenderModeAttrib::M_filled_wireframe) {
135  CullableObject *wireframe_part = new CullableObject(*object);
136  wireframe_part->_state = get_wireframe_overlay_state(rmode);
137 
138  if (wireframe_part->munge_geom
139  (_gsg, _gsg->get_geom_munger(wireframe_part->_state, current_thread),
140  traverser, force)) {
141  int wireframe_bin_index = bin_manager->find_bin("fixed");
142  CullBin *bin = get_bin(wireframe_bin_index);
143  nassertv(bin != nullptr);
144  check_flash_bin(wireframe_part->_state, bin_manager, wireframe_bin_index);
145  bin->add_object(wireframe_part, current_thread);
146  } else {
147  delete wireframe_part;
148  }
149 
150  object->_state = object->_state->compose(get_wireframe_filled_state());
151  }
152  }
153 
154  // Check to see if there's a special transparency setting.
155  const TransparencyAttrib *trans;
156  if (object->_state->get_attrib(trans)) {
157  switch (trans->get_mode()) {
158  case TransparencyAttrib::M_alpha:
159  case TransparencyAttrib::M_premultiplied_alpha:
160  // M_alpha implies an alpha-write test, so we don't waste time writing
161  // 0-valued pixels.
162  object->_state = object->_state->compose(get_alpha_state());
163  check_flash_transparency(object->_state, flash_alpha_color);
164  break;
165 
166  case TransparencyAttrib::M_binary:
167  // M_binary is implemented by explicitly setting the alpha test.
168  object->_state = object->_state->compose(get_binary_state());
169  check_flash_transparency(object->_state, flash_binary_color);
170  break;
171 
172  case TransparencyAttrib::M_multisample:
173  case TransparencyAttrib::M_multisample_mask:
174  // The multisample modes are implemented using M_binary if the GSG in
175  // use doesn't support multisample.
176  if (!_gsg->get_supports_multisample()) {
177  object->_state = object->_state->compose(get_binary_state());
178  }
179  check_flash_transparency(object->_state, flash_multisample_color);
180  break;
181 
182  case TransparencyAttrib::M_dual:
183 #ifndef NDEBUG
184  check_flash_transparency(object->_state, flash_dual_color);
185 #endif
186  if (!m_dual) {
187  // If m_dual is configured off, it becomes M_alpha.
188  break;
189  }
190 
191  // M_dual is implemented by drawing the opaque parts first, without
192  // transparency, then drawing the transparent parts later. This means
193  // we must copy the object and add it to both bins. We can only do this
194  // if we do not have an explicit bin already applied; otherwise, M_dual
195  // falls back to M_alpha.
196  {
197  const CullBinAttrib *bin_attrib;
198  if (!object->_state->get_attrib(bin_attrib) ||
199  bin_attrib->get_bin_name().empty()) {
200  // We make a copy of the object to draw the transparent part; this
201  // gets placed in the transparent bin.
202 #ifndef NDEBUG
203  if (m_dual_transparent)
204 #endif
205  {
206  CullableObject *transparent_part = new CullableObject(*object);
207  CPT(RenderState) transparent_state = get_dual_transparent_state();
208  transparent_part->_state = object->_state->compose(transparent_state);
209  if (transparent_part->munge_geom
210  (_gsg, _gsg->get_geom_munger(transparent_part->_state, current_thread),
211  traverser, force)) {
212  int transparent_bin_index = transparent_part->_state->get_bin_index();
213  CullBin *bin = get_bin(transparent_bin_index);
214  nassertv(bin != nullptr);
215  check_flash_bin(transparent_part->_state, bin_manager, transparent_bin_index);
216  bin->add_object(transparent_part, current_thread);
217  } else {
218  delete transparent_part;
219  }
220  }
221 
222  // Now we can draw the opaque part. This will end up in the opaque
223  // bin.
224  object->_state = object->_state->compose(get_dual_opaque_state());
225 #ifndef NDEBUG
226  if (!m_dual_opaque) {
227  delete object;
228  return;
229  }
230 #endif
231  }
232  // The object is assigned to a specific bin; M_dual becomes M_alpha.
233  }
234  break;
235 
236  default:
237  // Other kinds of transparency need no special handling.
238  break;
239  }
240  }
241 
242  int bin_index = object->_state->get_bin_index();
243  CullBin *bin = get_bin(bin_index);
244  nassertv(bin != nullptr);
245  check_flash_bin(object->_state, bin_manager, bin_index);
246 
247  // Munge vertices as needed for the GSG's requirements, and the object's
248  // current state.
249  if (object->munge_geom(_gsg, _gsg->get_geom_munger(object->_state, current_thread), traverser, force)) {
250  // The object may or may not now be fully resident, but this may not
251  // matter, since the GSG may have the necessary buffers already loaded.
252  // We'll let the GSG ultimately decide whether to render it.
253  bin->add_object(object, current_thread);
254  } else {
255  delete object;
256  }
257 }
258 
259 /**
260  * Called after all the geoms have been added, this indicates that the cull
261  * process is finished for this frame and gives the bins a chance to do any
262  * post-processing (like sorting) before moving on to draw.
263  */
264 void CullResult::
265 finish_cull(SceneSetup *scene_setup, Thread *current_thread) {
267 
268  for (size_t i = 0; i < _bins.size(); ++i) {
269  if (!bin_manager->get_bin_active(i)) {
270  // If the bin isn't active, don't sort it, and don't draw it. In fact,
271  // clear it.
272  _bins[i] = nullptr;
273 
274  } else {
275  CullBin *bin = _bins[i];
276  if (bin != nullptr) {
277  bin->finish_cull(scene_setup, current_thread);
278  }
279  }
280  }
281 }
282 
283 /**
284  * Asks all the bins to draw themselves in the correct order.
285  */
286 void CullResult::
287 draw(Thread *current_thread) {
288  bool force = !_gsg->get_effective_incomplete_render();
289 
290  // Ask the bin manager for the correct order to draw all the bins.
292  int num_bins = bin_manager->get_num_bins();
293  for (int i = 0; i < num_bins; i++) {
294  int bin_index = bin_manager->get_bin(i);
295  nassertv(bin_index >= 0);
296 
297  if (bin_index < (int)_bins.size() && _bins[bin_index] != nullptr) {
298 
299  _gsg->push_group_marker(_bins[bin_index]->get_name());
300  _bins[bin_index]->draw(force, current_thread);
301  _gsg->pop_group_marker();
302  }
303  }
304 }
305 
306 /**
307  * Returns a special scene graph constructed to represent the results of the
308  * cull. This will be a hierarchy of nodes, one node for each bin, each of
309  * which will in term be a parent of a number of GeomNodes, representing the
310  * geometry drawn in each bin.
311  *
312  * This is useful mainly for high-level debugging and abstraction tools; it
313  * should not be mistaken for the low-level cull result itself. For the low-
314  * level cull result, use draw() to efficiently draw the culled scene.
315  */
316 PT(PandaNode) CullResult::
317 make_result_graph() {
318  PT(PandaNode) root_node = new PandaNode("cull_result");
319 
320  // Ask the bin manager for the correct order to draw all the bins.
322  int num_bins = bin_manager->get_num_bins();
323  for (int i = 0; i < num_bins; i++) {
324  int bin_index = bin_manager->get_bin(i);
325  nassertr(bin_index >= 0, nullptr);
326 
327  if (bin_index < (int)_bins.size() && _bins[bin_index] != nullptr) {
328  root_node->add_child(_bins[bin_index]->make_result_graph());
329  }
330  }
331 
332  return root_node;
333 }
334 
335 /**
336  * Intended to be called by CullBinManager::remove_bin(), this informs all the
337  * CullResults in the world to remove the indicated bin_index from their cache
338  * if it has been cached.
339  */
340 void CullResult::
341 bin_removed(int bin_index) {
342  // Do something here.
343  nassertv(false);
344 }
345 
346 /**
347  * Allocates a new CullBin for the given bin_index and stores it for next
348  * time.
349  */
350 CullBin *CullResult::
351 make_new_bin(int bin_index) {
353  PT(CullBin) bin = bin_manager->make_new_bin(bin_index, _gsg,
354  _draw_region_pcollector);
355  CullBin *bin_ptr = bin.p();
356 
357  if (bin_ptr != nullptr) {
358  // Now store it in the vector.
359  while (bin_index >= (int)_bins.size()) {
360  _bins.push_back(nullptr);
361  }
362  nassertr(bin_index >= 0 && bin_index < (int)_bins.size(), nullptr);
363 
364  // Prevent unnecessary refunref by swapping the PointerTos.
365  std::swap(_bins[bin_index], bin);
366  }
367 
368  return bin_ptr;
369 }
370 
371 /**
372  * Returns a RenderState containing the given rescale normal attribute.
373  */
374 const RenderState *CullResult::
375 get_rescale_normal_state(RescaleNormalAttrib::Mode mode) {
376  static CPT(RenderState) states[RescaleNormalAttrib::M_auto + 1];
377  if (states[mode].is_null()) {
378  states[mode] = RenderState::make(RescaleNormalAttrib::make(mode),
379  RenderState::get_max_priority());
380  }
381  return states[mode].p();
382 }
383 
384 /**
385  * Returns a RenderState that changes the alpha test to > 0, for implementing
386  * M_alpha.
387  */
388 const RenderState *CullResult::
389 get_alpha_state() {
390  static CPT(RenderState) state = nullptr;
391  if (state == nullptr) {
392  // We don't monkey with the priority, since we want to allow the user to
393  // override this if he desires.
394  state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_greater, 0.0f));
395  }
396  return state.p();
397 }
398 
399 /**
400  * Returns a RenderState that applies the effects of M_binary.
401  */
402 const RenderState *CullResult::
403 get_binary_state() {
404  static CPT(RenderState) state = nullptr;
405  if (state == nullptr) {
406  state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_greater_equal, 0.5f),
407  TransparencyAttrib::make(TransparencyAttrib::M_none),
408  RenderState::get_max_priority());
409  }
410  return state.p();
411 }
412 
413 #ifndef NDEBUG
414 /**
415  * Update the object's state to flash the geometry with a solid color.
416  */
417 void CullResult::
418 apply_flash_color(CPT(RenderState) &state, const LColor &flash_color) {
419  int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate);
420  if ((cycle & 1) == 0) {
421  state = state->remove_attrib(TextureAttrib::get_class_slot());
422  state = state->remove_attrib(LightAttrib::get_class_slot());
423  state = state->remove_attrib(ColorScaleAttrib::get_class_slot());
424  state = state->remove_attrib(FogAttrib::get_class_slot());
425  state = state->add_attrib(ColorAttrib::make_flat(flash_color),
426  RenderState::get_max_priority());
427  }
428 }
429 #endif // NDEBUG
430 
431 /**
432  * Returns a RenderState that renders only the transparent parts of an object,
433  * in support of M_dual.
434  */
435 const RenderState *CullResult::
436 get_dual_transparent_state() {
437  static CPT(RenderState) state = nullptr;
438  if (state == nullptr) {
439  // The alpha test for > 0 prevents us from drawing empty pixels, and hence
440  // filling up the depth buffer with large empty spaces that may obscure
441  // other things. However, this does mean we draw pixels twice where the
442  // alpha == 1.0 (since they were already drawn in the opaque pass). This
443  // is not normally a problem.
444  state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_greater, 0.0f),
445  TransparencyAttrib::make(TransparencyAttrib::M_alpha),
446  DepthWriteAttrib::make(DepthWriteAttrib::M_off),
447  RenderState::get_max_priority());
448  }
449 
450 #ifndef NDEBUG
451  if (m_dual_flash) {
452  int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate);
453  if ((cycle & 1) == 0) {
454  static CPT(RenderState) flash_state = nullptr;
455  if (flash_state == nullptr) {
456  flash_state = state->add_attrib(ColorAttrib::make_flat(LColor(0.8f, 0.2, 0.2, 1.0f)),
457  RenderState::get_max_priority());
458 
459  flash_state = flash_state->add_attrib(ColorScaleAttrib::make(LVecBase4(1.0f, 1.0f, 1.0f, 1.0f)),
460  RenderState::get_max_priority());
461 
462  flash_state = flash_state->add_attrib(AlphaTestAttrib::make(AlphaTestAttrib::M_less, 1.0f),
463  RenderState::get_max_priority());
464  }
465  return flash_state.p();
466  }
467  }
468 #endif // NDEBUG
469 
470  return state.p();
471 }
472 
473 /**
474  * Returns a RenderState that renders only the opaque parts of an object, in
475  * support of M_dual.
476  */
477 const RenderState *CullResult::
478 get_dual_opaque_state() {
479  static CPT(RenderState) state = nullptr;
480  if (state == nullptr) {
481  state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_greater_equal, dual_opaque_level),
482  TransparencyAttrib::make(TransparencyAttrib::M_none),
483  RenderState::get_max_priority());
484  }
485 
486 #ifndef NDEBUG
487  if (m_dual_flash) {
488  int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate);
489  if ((cycle & 1) == 0) {
490  static CPT(RenderState) flash_state = nullptr;
491  if (flash_state == nullptr) {
492  flash_state = state->add_attrib(ColorAttrib::make_flat(LColor(0.2, 0.2, 0.8f, 1.0f)),
493  RenderState::get_max_priority());
494  flash_state = flash_state->add_attrib(ColorScaleAttrib::make(LVecBase4(1.0f, 1.0f, 1.0f, 1.0f)),
495  RenderState::get_max_priority());
496 
497  }
498  return flash_state.p();
499  }
500  }
501 #endif // NDEBUG
502 
503  return state.p();
504 }
505 
506 /**
507  * Returns a RenderState that is composed with the filled part of an
508  * M_filled_wireframe model.
509  */
510 const RenderState *CullResult::
511 get_wireframe_filled_state() {
512  static CPT(RenderState) state = RenderState::make(
513  RenderModeAttrib::make(RenderModeAttrib::M_filled),
514  RenderState::get_max_priority());
515  return state.p();
516 }
517 
518 /**
519  * Returns a RenderState that renders only the wireframe part of an
520  * M_filled_wireframe model.
521  */
522 CPT(RenderState) CullResult::
523 get_wireframe_overlay_state(const RenderModeAttrib *rmode) {
524  return RenderState::make(
525  DepthOffsetAttrib::make(1, 0, 0.99999f),
526  ColorAttrib::make_flat(rmode->get_wireframe_color()),
527  ColorBlendAttrib::make(ColorBlendAttrib::M_add,
528  ColorBlendAttrib::O_incoming_alpha,
529  ColorBlendAttrib::O_one_minus_incoming_alpha),
530  RenderModeAttrib::make(RenderModeAttrib::M_wireframe,
531  rmode->get_thickness(),
532  rmode->get_perspective()));
533 }
CPT(RenderState) CullResult
Returns a RenderState that renders only the wireframe part of an M_filled_wireframe model.
Definition: cullResult.cxx:522
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:215
PT(CullResult) CullResult
Returns a newly-allocated CullResult object that contains a copy of just the subset of the data from ...
Definition: cullResult.cxx:77
A basic node of the scene graph or data graph.
Definition: pandaNode.h:64
get_mode
Returns the transparency mode.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A collection of Geoms and their associated state, for a particular scene.
Definition: cullBin.h:40
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Thread * get_current_thread() const
Returns the currently-executing thread object, as passed to the CullTraverser constructor.
Definition: cullTraverser.I:27
This controls the enabling of transparency.
get_mode
Returns the render mode.
get_bin_name
Returns the name of the bin this attribute specifies.
Definition: cullBinAttrib.h:39
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_value
Returns the variable's value.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void finish_cull(SceneSetup *scene_setup, Thread *current_thread)
Called after all the geoms have been added, this indicates that the cull process is finished for this...
Definition: cullResult.cxx:265
static CullBinManager * get_global_ptr()
Returns the pointer to the global CullBinManager object.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool get_effective_incomplete_render() const
Returns true if the cull traversal is effectively in incomplete_render state, considering both the GS...
A lightweight class that represents a single element that may be timed and/or counted via stats.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The smallest atom of cull.
get_frame_time
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
Definition: clockObject.h:91
CullBin * get_bin(int bin_index)
Returns the CullBin associated with the indicated bin_index, or NULL if the bin_index is invalid.
Definition: cullResult.I:27
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool munge_geom(GraphicsStateGuardianBase *gsg, GeomMunger *munger, const CullTraverser *traverser, bool force)
Uses the indicated GeomMunger to transform the geom and/or its vertices.
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:341
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
static void update_type(ReferenceCount *ptr, TypeHandle type)
Associates the indicated type with the given pointer.
Definition: memoryUsage.I:55
Assigns geometry to a particular bin by name.
Definition: cullBinAttrib.h:27
bool get_bin_active(int bin_index) const
Returns the active flag of the bin with the indicated bin_index (where bin_index was retrieved by get...
get_num_bins
Returns the number of bins in the world.
This stores the result of a BinCullHandler traversal: an ordered collection of CullBins,...
Definition: cullResult.h:44
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_bin
Returns the bin_index of the nth bin in the set, where n is a number between 0 and get_num_bins().
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
get_mode
Returns the render mode.
A thread; that is, a lightweight process.
Definition: thread.h:46
get_wireframe_color
Returns the color that is used in M_filled_wireframe mode to distinguish the wireframe from the rest ...
Specifies how polygons are to be drawn.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_thickness
Returns the line width or point thickness.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_perspective
Returns the perspective flag.
Specifies how polygons are to be drawn.
void draw(Thread *current_thread)
Asks all the bins to draw themselves in the correct order.
Definition: cullResult.cxx:287
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This object holds the camera position, etc., and other general setup information for rendering a part...
Definition: sceneSetup.h:32
This is a global object that maintains the collection of named CullBins in the world.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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() ...