Panda3D

cullBin.cxx

00001 // Filename: cullBin.cxx
00002 // Created by:  drose (28Feb02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "cullBin.h"
00016 #include "config_pgraph.h"
00017 #include "pandaNode.h"
00018 #include "geomNode.h"
00019 #include "cullableObject.h"
00020 #include "decalEffect.h"
00021 #include "string_utils.h"
00022 
00023 PStatCollector CullBin::_cull_bin_pcollector("Cull:Sort");
00024 
00025 TypeHandle CullBin::_type_handle;
00026 
00027 ////////////////////////////////////////////////////////////////////
00028 //     Function: CullBin::Destructor
00029 //       Access: Public, Virtual
00030 //  Description: 
00031 ////////////////////////////////////////////////////////////////////
00032 CullBin::
00033 ~CullBin() {
00034 }
00035 
00036 ////////////////////////////////////////////////////////////////////
00037 //     Function: CullBin::make_next
00038 //       Access: Public, Virtual
00039 //  Description: Returns a newly-allocated CullBin object that
00040 //               contains a copy of just the subset of the data from
00041 //               this CullBin object that is worth keeping around
00042 //               for next frame.
00043 //
00044 //               If a particular CullBin object has no data worth
00045 //               preserving till next frame, it is acceptable to
00046 //               return NULL (which is the default behavior of this
00047 //               method).
00048 ////////////////////////////////////////////////////////////////////
00049 PT(CullBin) CullBin::
00050 make_next() const {
00051   return (CullBin *)NULL;
00052 }
00053 
00054 ////////////////////////////////////////////////////////////////////
00055 //     Function: CullBin::finish_cull
00056 //       Access: Public, Virtual
00057 //  Description: Called after all the geoms have been added, this
00058 //               indicates that the cull process is finished for this
00059 //               frame and gives the bins a chance to do any
00060 //               post-processing (like sorting) before moving on to
00061 //               draw.
00062 ////////////////////////////////////////////////////////////////////
00063 void CullBin::
00064 finish_cull(SceneSetup *, Thread *) {
00065 }
00066 
00067 ////////////////////////////////////////////////////////////////////
00068 //     Function: CullBin::make_result_graph
00069 //       Access: Public
00070 //  Description: Returns a special scene graph constructed to
00071 //               represent the results of the cull.  This will be a
00072 //               single node with a list of GeomNode children, which
00073 //               represent the various geom objects discovered by the
00074 //               cull.
00075 //
00076 //               This is useful mainly for high-level debugging and
00077 //               abstraction tools; it should not be mistaken for the
00078 //               low-level cull result itself.  For the low-level cull
00079 //               result, use draw() to efficiently draw the culled
00080 //               scene.
00081 ////////////////////////////////////////////////////////////////////
00082 PT(PandaNode) CullBin::
00083 make_result_graph() {
00084   PT(PandaNode) root_node = new PandaNode(get_name());
00085   ResultGraphBuilder builder(root_node);
00086   fill_result_graph(builder);
00087   return root_node;
00088 }
00089 
00090 ////////////////////////////////////////////////////////////////////
00091 //     Function: CullBin::check_flash_color
00092 //       Access: Private
00093 //  Description: Checks the config variables for a user variable of
00094 //               the name flash-bin-binname.  If found, it defines the
00095 //               r g b color to flash geometry in this bin.
00096 ////////////////////////////////////////////////////////////////////
00097 void CullBin::
00098 check_flash_color() {
00099 #ifdef NDEBUG
00100   _has_flash_color = false;
00101 #else
00102   ConfigVariableDouble flash_bin
00103     ("flash-bin-" + _name, "", "", ConfigVariable::F_dynamic);
00104   if (flash_bin.get_num_words() == 0) {
00105     _has_flash_color = false;
00106 
00107   } else if (flash_bin.get_num_words() == 3) {
00108     _has_flash_color = true;
00109     _flash_color.set(flash_bin[0], flash_bin[1], flash_bin[2], 1.0f);
00110 
00111   } else if (flash_bin.get_num_words() == 4) {
00112     _has_flash_color = true;
00113     _flash_color.set(flash_bin[0], flash_bin[1], flash_bin[2], flash_bin[3]);
00114 
00115   } else {
00116     _has_flash_color = false;
00117     pgraph_cat.warning()
00118       << "Invalid value for flash-bin-" << _name << ": " 
00119       << flash_bin.get_string_value() << "\n";
00120   }
00121 #endif  // NDEBUG
00122 }
00123 
00124 ////////////////////////////////////////////////////////////////////
00125 //     Function: CullBin::ResultGraphBuilder::Constructor
00126 //       Access: Public
00127 //  Description: 
00128 ////////////////////////////////////////////////////////////////////
00129 CullBin::ResultGraphBuilder::
00130 ResultGraphBuilder(PandaNode *root_node) :
00131   _object_index(0),
00132   _root_node(root_node)
00133 {
00134 }
00135 
00136 ////////////////////////////////////////////////////////////////////
00137 //     Function: CullBin::ResultGraphBuilder::add_object
00138 //       Access: Public
00139 //  Description: Called in fill_result_graph() by a derived CullBin
00140 //               class to add each culled object to the result
00141 //               returned by make_result_graph().
00142 ////////////////////////////////////////////////////////////////////
00143 void CullBin::ResultGraphBuilder::
00144 add_object(CullableObject *object) {
00145   if (_current_transform != object->_modelview_transform || 
00146       _current_state != object->_state || 
00147       object->is_fancy()) {
00148     // Create a new GeomNode to hold the net transform and state.  We
00149     // choose to create a new GeomNode for each new state, to make it
00150     // clearer to the observer when the state changes.
00151     _current_transform = object->_modelview_transform;
00152     _current_state = object->_state;
00153     _current_node = new GeomNode("object_" + format_string(_object_index));
00154     _root_node->add_child(_current_node);
00155     _current_node->set_transform(_current_transform);
00156     _current_node->set_state(_current_state);
00157   }
00158 
00159   record_one_object(_current_node, object);
00160 
00161   if (object->get_next() != (CullableObject *)NULL) {
00162     // Collect the decal base pieces.
00163     CullableObject *base = object->get_next();
00164     while (base != (CullableObject *)NULL && base->_geom != (Geom *)NULL) {
00165       record_one_object(_current_node, base);
00166       base = base->get_next();
00167     }
00168 
00169     if (base != (CullableObject *)NULL) {
00170       // Now, collect all the decals.
00171       _current_node->set_effect(DecalEffect::make());
00172       int decal_index = 0;
00173 
00174       CPT(TransformState) transform;
00175       CPT(RenderState) state;
00176       PT(GeomNode) decal_node;
00177       CullableObject *decal = base->get_next();
00178       while (decal != (CullableObject *)NULL) {
00179         if (transform != decal->_modelview_transform || 
00180             state != decal->_state || 
00181             decal->get_next() != (CullableObject *)NULL) {
00182           // Create a new GeomNode to hold the net transform.
00183           transform = decal->_modelview_transform;
00184           state = decal->_state;
00185           decal_node = new GeomNode("decal_" + format_string(decal_index));
00186           _current_node->add_child(decal_node);
00187           decal_node->set_transform(transform);
00188           decal_node->set_state(state);
00189         }
00190         
00191         record_one_object(decal_node, decal);
00192         decal = decal->get_next();
00193         ++decal_index;
00194       }
00195     }
00196 
00197     // Reset the current node pointer for next time so the decal root
00198     // will remain in its own node.
00199     _current_node.clear();
00200     _current_transform.clear();
00201     _current_state.clear();
00202   }
00203 
00204   ++_object_index;
00205 }
00206 
00207 ////////////////////////////////////////////////////////////////////
00208 //     Function: CullBin::ResultGraphBuilder::record_one_object
00209 //       Access: Private
00210 //  Description: Records a single object, without regard to decalling.
00211 ////////////////////////////////////////////////////////////////////
00212 void CullBin::ResultGraphBuilder::
00213 record_one_object(GeomNode *node, CullableObject *object) {
00214   PT(Geom) new_geom = object->_geom->make_copy();
00215   new_geom->set_vertex_data(object->_munged_data);
00216   node->add_geom(new_geom);
00217 }
 All Classes Functions Variables Enumerations