Browse Source

DisplayRegion::make_cull_result_graph()

David Rose 18 years ago
parent
commit
3b528350bb

+ 14 - 0
panda/src/cull/cullBinBackToFront.cxx

@@ -110,3 +110,17 @@ draw(bool force, Thread *current_thread) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CullBinBackToFront::fill_result_graph
+//       Access: Protected, Virtual
+//  Description: Called by CullBin::make_result_graph() to add all the
+//               geoms to the special cull result scene graph.
+////////////////////////////////////////////////////////////////////
+void CullBinBackToFront::
+fill_result_graph(CullBin::ResultGraphBuilder &builder) {
+  Objects::const_iterator oi;
+  for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
+    CullableObject *object = (*oi)._object;
+    builder.add_object(object);
+  }
+}

+ 3 - 0
panda/src/cull/cullBinBackToFront.h

@@ -51,6 +51,9 @@ public:
   virtual void finish_cull(SceneSetup *scene_setup, Thread *current_thread);
   virtual void finish_cull(SceneSetup *scene_setup, Thread *current_thread);
   virtual void draw(bool force, Thread *current_thread);
   virtual void draw(bool force, Thread *current_thread);
 
 
+protected:
+  virtual void fill_result_graph(ResultGraphBuilder &builder);
+
 private:
 private:
   class ObjectData {
   class ObjectData {
   public:
   public:

+ 14 - 0
panda/src/cull/cullBinFixed.cxx

@@ -96,3 +96,17 @@ draw(bool force, Thread *current_thread) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CullBinFixed::fill_result_graph
+//       Access: Protected, Virtual
+//  Description: Called by CullBin::make_result_graph() to add all the
+//               geoms to the special cull result scene graph.
+////////////////////////////////////////////////////////////////////
+void CullBinFixed::
+fill_result_graph(CullBin::ResultGraphBuilder &builder) {
+  Objects::const_iterator oi;
+  for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
+    CullableObject *object = (*oi)._object;
+    builder.add_object(object);
+  }
+}

+ 3 - 0
panda/src/cull/cullBinFixed.h

@@ -53,6 +53,9 @@ public:
   virtual void finish_cull(SceneSetup *scene_setup, Thread *current_thread);
   virtual void finish_cull(SceneSetup *scene_setup, Thread *current_thread);
   virtual void draw(bool force, Thread *current_thread);
   virtual void draw(bool force, Thread *current_thread);
 
 
+protected:
+  virtual void fill_result_graph(ResultGraphBuilder &builder);
+
 private:
 private:
   class ObjectData {
   class ObjectData {
   public:
   public:

+ 14 - 0
panda/src/cull/cullBinFrontToBack.cxx

@@ -110,3 +110,17 @@ draw(bool force, Thread *current_thread) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CullBinFrontToBack::fill_result_graph
+//       Access: Protected, Virtual
+//  Description: Called by CullBin::make_result_graph() to add all the
+//               geoms to the special cull result scene graph.
+////////////////////////////////////////////////////////////////////
+void CullBinFrontToBack::
+fill_result_graph(CullBin::ResultGraphBuilder &builder) {
+  Objects::const_iterator oi;
+  for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
+    CullableObject *object = (*oi)._object;
+    builder.add_object(object);
+  }
+}

+ 3 - 0
panda/src/cull/cullBinFrontToBack.h

@@ -51,6 +51,9 @@ public:
   virtual void finish_cull(SceneSetup *scene_setup, Thread *current_thread);
   virtual void finish_cull(SceneSetup *scene_setup, Thread *current_thread);
   virtual void draw(bool force, Thread *current_thread);
   virtual void draw(bool force, Thread *current_thread);
 
 
+protected:
+  virtual void fill_result_graph(ResultGraphBuilder &builder);
+
 private:
 private:
   class ObjectData {
   class ObjectData {
   public:
   public:

+ 14 - 0
panda/src/cull/cullBinStateSorted.cxx

@@ -95,3 +95,17 @@ draw(bool force, Thread *current_thread) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CullBinStateSorted::fill_result_graph
+//       Access: Protected, Virtual
+//  Description: Called by CullBin::make_result_graph() to add all the
+//               geoms to the special cull result scene graph.
+////////////////////////////////////////////////////////////////////
+void CullBinStateSorted::
+fill_result_graph(CullBin::ResultGraphBuilder &builder) {
+  Objects::const_iterator oi;
+  for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
+    CullableObject *object = (*oi)._object;
+    builder.add_object(object);
+  }
+}

+ 3 - 0
panda/src/cull/cullBinStateSorted.h

@@ -55,6 +55,9 @@ public:
   virtual void finish_cull(SceneSetup *scene_setup, Thread *current_thread);
   virtual void finish_cull(SceneSetup *scene_setup, Thread *current_thread);
   virtual void draw(bool force, Thread *current_thread);
   virtual void draw(bool force, Thread *current_thread);
 
 
+protected:
+  virtual void fill_result_graph(ResultGraphBuilder &builder);
+
 private:
 private:
   class ObjectData {
   class ObjectData {
   public:
   public:

+ 14 - 0
panda/src/cull/cullBinUnsorted.cxx

@@ -76,3 +76,17 @@ draw(bool force, Thread *current_thread) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CullBinUnsorted::fill_result_graph
+//       Access: Protected, Virtual
+//  Description: Called by CullBin::make_result_graph() to add all the
+//               geoms to the special cull result scene graph.
+////////////////////////////////////////////////////////////////////
+void CullBinUnsorted::
+fill_result_graph(CullBin::ResultGraphBuilder &builder) {
+  Objects::const_iterator oi;
+  for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
+    CullableObject *object = (*oi);
+    builder.add_object(object);
+  }
+}

+ 3 - 0
panda/src/cull/cullBinUnsorted.h

@@ -45,6 +45,9 @@ public:
   virtual void add_object(CullableObject *object, Thread *current_thread);
   virtual void add_object(CullableObject *object, Thread *current_thread);
   virtual void draw(bool force, Thread *current_thread);
   virtual void draw(bool force, Thread *current_thread);
 
 
+protected:
+  virtual void fill_result_graph(ResultGraphBuilder &builder);
+
 private:
 private:
   typedef pvector<CullableObject *> Objects;
   typedef pvector<CullableObject *> Objects;
   Objects _objects;
   Objects _objects;

+ 30 - 0
panda/src/display/displayRegion.cxx

@@ -524,6 +524,36 @@ get_screenshot(PNMImage &image) {
   return true;
   return true;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::make_cull_result_graph
+//       Access: Public
+//  Description: Returns a special scene graph constructed to
+//               represent the results of the last frame's cull
+//               operation.
+//
+//               This will be a hierarchy of nodes, one node for each
+//               bin, each of which will in term be a parent of a
+//               number of GeomNodes, representing the geometry drawn
+//               in each bin.
+//
+//               This is useful mainly for high-level debugging and
+//               abstraction tools; it should not be mistaken for the
+//               low-level cull result itself, which is constructed
+//               and maintained internally.  No such scene graph is
+//               normally constructed during the rendering of a frame;
+//               this is an artificial construct created for the
+//               purpose of making it easy to analyze the results of
+//               the cull operation.
+////////////////////////////////////////////////////////////////////
+PT(PandaNode) DisplayRegion::
+make_cull_result_graph() {
+  CullResult *cull_result = get_cull_result(Thread::get_current_thread());
+  if (cull_result == (CullResult *)NULL) {
+    return NULL;
+  }
+  return cull_result->make_result_graph();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DisplayRegion::win_display_regions_changed
 //     Function: DisplayRegion::win_display_regions_changed
 //       Access: Private
 //       Access: Private

+ 2 - 0
panda/src/display/displayRegion.h

@@ -125,6 +125,8 @@ PUBLISHED:
     const Filename &filename, const string &image_comment = "");
     const Filename &filename, const string &image_comment = "");
   bool get_screenshot(PNMImage &image);
   bool get_screenshot(PNMImage &image);
 
 
+  PT(PandaNode) make_cull_result_graph();
+
 public:
 public:
   INLINE void set_cull_result(CullResult *cull_result, SceneSetup *scene_setup,
   INLINE void set_cull_result(CullResult *cull_result, SceneSetup *scene_setup,
                               Thread *current_thread);
                               Thread *current_thread);

+ 19 - 0
panda/src/framework/pandaFramework.cxx

@@ -845,6 +845,7 @@ do_enable_default_keys() {
   define_key("shift-c", "toggle collision surfaces", event_C, this);
   define_key("shift-c", "toggle collision surfaces", event_C, this);
   define_key("shift-b", "report bounding volume", event_B, this);
   define_key("shift-b", "report bounding volume", event_B, this);
   define_key("shift-l", "list hierarchy", event_L, this);
   define_key("shift-l", "list hierarchy", event_L, this);
+  define_key("shift-a", "analyze hierarchy", event_A, this);
   define_key("h", "highlight node", event_h, this);
   define_key("h", "highlight node", event_h, this);
   define_key("arrow_up", "move highlight to parent", event_arrow_up, this);
   define_key("arrow_up", "move highlight to parent", event_arrow_up, this);
   define_key("arrow_down", "move highlight to child", event_arrow_down, this);
   define_key("arrow_down", "move highlight to child", event_arrow_down, this);
@@ -1110,6 +1111,24 @@ event_L(const Event *, void *data) {
   node.ls();
   node.ls();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: PandaFramework::event_A
+//       Access: Public, Static
+//  Description: Default handler for shift-A key: analyze the contents
+//               of the scene graph, or the highlighted node.
+////////////////////////////////////////////////////////////////////
+void PandaFramework::
+event_A(const Event *, void *data) {
+  PandaFramework *self = (PandaFramework *)data;
+
+  NodePath node = self->get_highlight();
+  if (node.is_empty()) {
+    node = self->get_models();
+  }
+
+  node.analyze();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PandaFramework::event_h
 //     Function: PandaFramework::event_h
 //       Access: Public, Static
 //       Access: Public, Static

+ 1 - 0
panda/src/framework/pandaFramework.h

@@ -136,6 +136,7 @@ public:
   static void event_C(const Event *, void *data);
   static void event_C(const Event *, void *data);
   static void event_B(const Event *, void *data);
   static void event_B(const Event *, void *data);
   static void event_L(const Event *, void *data);
   static void event_L(const Event *, void *data);
+  static void event_A(const Event *, void *data);
   static void event_h(const Event *, void *data);
   static void event_h(const Event *, void *data);
   static void event_arrow_up(const Event *, void *data);
   static void event_arrow_up(const Event *, void *data);
   static void event_arrow_down(const Event *, void *data);
   static void event_arrow_down(const Event *, void *data);

+ 123 - 0
panda/src/pgraph/cullBin.cxx

@@ -18,6 +18,11 @@
 
 
 #include "cullBin.h"
 #include "cullBin.h"
 #include "config_pgraph.h"
 #include "config_pgraph.h"
+#include "pandaNode.h"
+#include "geomNode.h"
+#include "cullableObject.h"
+#include "decalEffect.h"
+#include "string_utils.h"
 
 
 PStatCollector CullBin::_cull_bin_pcollector("Cull:Sort");
 PStatCollector CullBin::_cull_bin_pcollector("Cull:Sort");
 
 
@@ -63,6 +68,29 @@ void CullBin::
 finish_cull(SceneSetup *, Thread *) {
 finish_cull(SceneSetup *, Thread *) {
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CullBin::make_result_graph
+//       Access: Public
+//  Description: Returns a special scene graph constructed to
+//               represent the results of the cull.  This will be a
+//               single node with a list of GeomNode children, which
+//               represent the various geom objects discovered by the
+//               cull.
+//
+//               This is useful mainly for high-level debugging and
+//               abstraction tools; it should not be mistaken for the
+//               low-level cull result itself.  For the low-level cull
+//               result, use draw() to efficiently draw the culled
+//               scene.
+////////////////////////////////////////////////////////////////////
+PT(PandaNode) CullBin::
+make_result_graph() {
+  PT(PandaNode) root_node = new PandaNode(get_name());
+  ResultGraphBuilder builder(root_node);
+  fill_result_graph(builder);
+  return root_node;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CullBin::check_flash_color
 //     Function: CullBin::check_flash_color
 //       Access: Private
 //       Access: Private
@@ -96,3 +124,98 @@ check_flash_color() {
   }
   }
 #endif  // NDEBUG
 #endif  // NDEBUG
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: CullBin::ResultGraphBuilder::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CullBin::ResultGraphBuilder::
+ResultGraphBuilder(PandaNode *root_node) :
+  _root_node(root_node),
+  _object_index(0)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CullBin::ResultGraphBuilder::add_object
+//       Access: Public
+//  Description: Called in fill_result_graph() by a derived CullBin
+//               class to add each culled object to the result
+//               returned by make_result_graph().
+////////////////////////////////////////////////////////////////////
+void CullBin::ResultGraphBuilder::
+add_object(CullableObject *object) {
+  if (_current_transform != object->_modelview_transform || 
+      _current_state != object->_state || 
+      object->_next != (CullableObject *)NULL) {
+    // Create a new GeomNode to hold the net transform and state.  We
+    // choose to create a new GeomNode for each new state, to make it
+    // clearer to the observer when the state changes.
+    _current_transform = object->_modelview_transform;
+    _current_state = object->_state;
+    _current_node = new GeomNode("object_" + format_string(_object_index));
+    _root_node->add_child(_current_node);
+    _current_node->set_transform(_current_transform);
+    _current_node->set_state(_current_state);
+  }
+
+  record_one_object(_current_node, object);
+
+  if (object->_next != (CullableObject *)NULL) {
+    // Collect the decal base pieces.
+    CullableObject *base = object->_next;
+    while (base != (CullableObject *)NULL && base->_geom != (Geom *)NULL) {
+      record_one_object(_current_node, base);
+      base = base->_next;
+    }
+
+    if (base != (CullableObject *)NULL) {
+      // Now, collect all the decals.
+      _current_node->set_effect(DecalEffect::make());
+      int decal_index = 0;
+
+      CPT(TransformState) transform;
+      CPT(RenderState) state;
+      PT(GeomNode) decal_node;
+      CullableObject *decal = base->_next;
+      while (decal != (CullableObject *)NULL) {
+        if (transform != decal->_modelview_transform || 
+            state != decal->_state || 
+            decal->_next != (CullableObject *)NULL) {
+          // Create a new GeomNode to hold the net transform.
+          transform = decal->_modelview_transform;
+          state = decal->_state;
+          decal_node = new GeomNode("decal_" + format_string(decal_index));
+          _current_node->add_child(decal_node);
+          decal_node->set_transform(transform);
+          decal_node->set_state(state);
+        }
+        
+        record_one_object(decal_node, decal);
+        decal = decal->_next;
+        ++decal_index;
+      }
+    }
+
+    // Reset the current node pointer for next time so the decal root
+    // will remain in its own node.
+    _current_node.clear();
+    _current_transform.clear();
+    _current_state.clear();
+  }
+
+  ++_object_index;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CullBin::ResultGraphBuilder::record_one_object
+//       Access: Private
+//  Description: Records a single object, without regard to decalling.
+////////////////////////////////////////////////////////////////////
+void CullBin::ResultGraphBuilder::
+record_one_object(GeomNode *node, CullableObject *object) {
+  PT(Geom) new_geom = object->_geom->make_copy();
+  new_geom->set_vertex_data(object->_munged_data);
+  node->add_geom(new_geom);
+}

+ 27 - 0
panda/src/pgraph/cullBin.h

@@ -29,6 +29,10 @@
 class CullableObject;
 class CullableObject;
 class GraphicsStateGuardianBase;
 class GraphicsStateGuardianBase;
 class SceneSetup;
 class SceneSetup;
+class TransformState;
+class RenderState;
+class PandaNode;
+class GeomNode;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : CullBin
 //       Class : CullBin
@@ -60,9 +64,15 @@ public:
 
 
   virtual void draw(bool force, Thread *current_thread)=0;
   virtual void draw(bool force, Thread *current_thread)=0;
 
 
+  PT(PandaNode) make_result_graph();
+
   INLINE bool has_flash_color() const;
   INLINE bool has_flash_color() const;
   INLINE const Colorf &get_flash_color() const;
   INLINE const Colorf &get_flash_color() const;
 
 
+protected:
+  class ResultGraphBuilder;
+  virtual void fill_result_graph(ResultGraphBuilder &builder)=0;
+
 private:
 private:
   void check_flash_color();
   void check_flash_color();
 
 
@@ -74,6 +84,23 @@ protected:
   bool _has_flash_color;
   bool _has_flash_color;
   Colorf _flash_color;
   Colorf _flash_color;
 
 
+  // Used in make_result_graph() and fill_result_graph().
+  class ResultGraphBuilder {
+  public:
+    ResultGraphBuilder(PandaNode *root_node);
+    void add_object(CullableObject *object);
+
+  private:
+    void record_one_object(GeomNode *node, CullableObject *object);
+
+  private:
+    int _object_index;
+    CPT(TransformState) _current_transform;
+    CPT(RenderState) _current_state;
+    PT(PandaNode) _root_node;
+    PT(GeomNode) _current_node;
+  };
+
   static PStatCollector _cull_bin_pcollector;
   static PStatCollector _cull_bin_pcollector;
   PStatCollector _cull_this_pcollector;
   PStatCollector _cull_this_pcollector;
   PStatCollector _draw_this_pcollector;
   PStatCollector _draw_this_pcollector;

+ 35 - 0
panda/src/pgraph/cullResult.cxx

@@ -270,6 +270,41 @@ draw(Thread *current_thread) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CullResult::make_result_graph
+//       Access: Public
+//  Description: Returns a special scene graph constructed to
+//               represent the results of the cull.  This will be a
+//               hierarchy of nodes, one node for each bin, each of
+//               which will in term be a parent of a number of
+//               GeomNodes, representing the geometry drawn in each
+//               bin.
+//
+//               This is useful mainly for high-level debugging and
+//               abstraction tools; it should not be mistaken for the
+//               low-level cull result itself.  For the low-level cull
+//               result, use draw() to efficiently draw the culled
+//               scene.
+////////////////////////////////////////////////////////////////////
+PT(PandaNode) CullResult::
+make_result_graph() {
+  PT(PandaNode) root_node = new PandaNode("cull_result");
+
+  // Ask the bin manager for the correct order to draw all the bins.
+  CullBinManager *bin_manager = CullBinManager::get_global_ptr();
+  int num_bins = bin_manager->get_num_bins();
+  for (int i = 0; i < num_bins; i++) {
+    int bin_index = bin_manager->get_bin(i);
+    nassertr(bin_index >= 0, NULL);
+
+    if (bin_index < (int)_bins.size() && _bins[bin_index] != (CullBin *)NULL) {
+      root_node->add_child(_bins[bin_index]->make_result_graph());
+    }
+  }
+
+  return root_node;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CullResult::bin_removed
 //     Function: CullResult::bin_removed
 //       Access: Public, Static
 //       Access: Public, Static

+ 2 - 0
panda/src/pgraph/cullResult.h

@@ -63,6 +63,8 @@ public:
   void finish_cull(SceneSetup *scene_setup, Thread *current_thread);
   void finish_cull(SceneSetup *scene_setup, Thread *current_thread);
   void draw(Thread *current_thread);
   void draw(Thread *current_thread);
 
 
+  PT(PandaNode) make_result_graph();
+
 public:
 public:
   static void bin_removed(int bin_index);
   static void bin_removed(int bin_index);