From 3b528350bbca4013ba1b418d444f413ba10d33f0 Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 15 Jun 2007 16:54:30 +0000 Subject: [PATCH] DisplayRegion::make_cull_result_graph() --- panda/src/cull/cullBinBackToFront.cxx | 14 +++ panda/src/cull/cullBinBackToFront.h | 3 + panda/src/cull/cullBinFixed.cxx | 14 +++ panda/src/cull/cullBinFixed.h | 3 + panda/src/cull/cullBinFrontToBack.cxx | 14 +++ panda/src/cull/cullBinFrontToBack.h | 3 + panda/src/cull/cullBinStateSorted.cxx | 14 +++ panda/src/cull/cullBinStateSorted.h | 3 + panda/src/cull/cullBinUnsorted.cxx | 14 +++ panda/src/cull/cullBinUnsorted.h | 3 + panda/src/display/displayRegion.cxx | 30 ++++++ panda/src/display/displayRegion.h | 2 + panda/src/framework/pandaFramework.cxx | 19 ++++ panda/src/framework/pandaFramework.h | 1 + panda/src/pgraph/cullBin.cxx | 123 +++++++++++++++++++++++++ panda/src/pgraph/cullBin.h | 27 ++++++ panda/src/pgraph/cullResult.cxx | 35 +++++++ panda/src/pgraph/cullResult.h | 2 + 18 files changed, 324 insertions(+) diff --git a/panda/src/cull/cullBinBackToFront.cxx b/panda/src/cull/cullBinBackToFront.cxx index 0992571840..87cc954171 100644 --- a/panda/src/cull/cullBinBackToFront.cxx +++ b/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); + } +} diff --git a/panda/src/cull/cullBinBackToFront.h b/panda/src/cull/cullBinBackToFront.h index 2b22a755cf..cff60ef518 100644 --- a/panda/src/cull/cullBinBackToFront.h +++ b/panda/src/cull/cullBinBackToFront.h @@ -51,6 +51,9 @@ public: virtual void finish_cull(SceneSetup *scene_setup, Thread *current_thread); virtual void draw(bool force, Thread *current_thread); +protected: + virtual void fill_result_graph(ResultGraphBuilder &builder); + private: class ObjectData { public: diff --git a/panda/src/cull/cullBinFixed.cxx b/panda/src/cull/cullBinFixed.cxx index 7c1f260c21..36fb85d007 100644 --- a/panda/src/cull/cullBinFixed.cxx +++ b/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); + } +} diff --git a/panda/src/cull/cullBinFixed.h b/panda/src/cull/cullBinFixed.h index 4b0e2f6828..71395f94cf 100644 --- a/panda/src/cull/cullBinFixed.h +++ b/panda/src/cull/cullBinFixed.h @@ -53,6 +53,9 @@ public: virtual void finish_cull(SceneSetup *scene_setup, Thread *current_thread); virtual void draw(bool force, Thread *current_thread); +protected: + virtual void fill_result_graph(ResultGraphBuilder &builder); + private: class ObjectData { public: diff --git a/panda/src/cull/cullBinFrontToBack.cxx b/panda/src/cull/cullBinFrontToBack.cxx index a4313ede52..b580c99f06 100644 --- a/panda/src/cull/cullBinFrontToBack.cxx +++ b/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); + } +} diff --git a/panda/src/cull/cullBinFrontToBack.h b/panda/src/cull/cullBinFrontToBack.h index 68d8cf2728..ebf1d9e1f3 100644 --- a/panda/src/cull/cullBinFrontToBack.h +++ b/panda/src/cull/cullBinFrontToBack.h @@ -51,6 +51,9 @@ public: virtual void finish_cull(SceneSetup *scene_setup, Thread *current_thread); virtual void draw(bool force, Thread *current_thread); +protected: + virtual void fill_result_graph(ResultGraphBuilder &builder); + private: class ObjectData { public: diff --git a/panda/src/cull/cullBinStateSorted.cxx b/panda/src/cull/cullBinStateSorted.cxx index c19ea2cac6..929ab0f9d6 100644 --- a/panda/src/cull/cullBinStateSorted.cxx +++ b/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); + } +} diff --git a/panda/src/cull/cullBinStateSorted.h b/panda/src/cull/cullBinStateSorted.h index a353fefbea..5c6e13974b 100644 --- a/panda/src/cull/cullBinStateSorted.h +++ b/panda/src/cull/cullBinStateSorted.h @@ -55,6 +55,9 @@ public: virtual void finish_cull(SceneSetup *scene_setup, Thread *current_thread); virtual void draw(bool force, Thread *current_thread); +protected: + virtual void fill_result_graph(ResultGraphBuilder &builder); + private: class ObjectData { public: diff --git a/panda/src/cull/cullBinUnsorted.cxx b/panda/src/cull/cullBinUnsorted.cxx index 6f1ed73e8a..f76cf5fbf6 100644 --- a/panda/src/cull/cullBinUnsorted.cxx +++ b/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); + } +} diff --git a/panda/src/cull/cullBinUnsorted.h b/panda/src/cull/cullBinUnsorted.h index 5e67a62c02..78ff7900f2 100644 --- a/panda/src/cull/cullBinUnsorted.h +++ b/panda/src/cull/cullBinUnsorted.h @@ -45,6 +45,9 @@ public: virtual void add_object(CullableObject *object, Thread *current_thread); virtual void draw(bool force, Thread *current_thread); +protected: + virtual void fill_result_graph(ResultGraphBuilder &builder); + private: typedef pvector Objects; Objects _objects; diff --git a/panda/src/display/displayRegion.cxx b/panda/src/display/displayRegion.cxx index e7e765024e..7ef8ac23fa 100644 --- a/panda/src/display/displayRegion.cxx +++ b/panda/src/display/displayRegion.cxx @@ -524,6 +524,36 @@ get_screenshot(PNMImage &image) { 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 // Access: Private diff --git a/panda/src/display/displayRegion.h b/panda/src/display/displayRegion.h index f33e67e563..3ff489c7d5 100644 --- a/panda/src/display/displayRegion.h +++ b/panda/src/display/displayRegion.h @@ -125,6 +125,8 @@ PUBLISHED: const Filename &filename, const string &image_comment = ""); bool get_screenshot(PNMImage &image); + PT(PandaNode) make_cull_result_graph(); + public: INLINE void set_cull_result(CullResult *cull_result, SceneSetup *scene_setup, Thread *current_thread); diff --git a/panda/src/framework/pandaFramework.cxx b/panda/src/framework/pandaFramework.cxx index 41b8780d77..e4bad7b6be 100644 --- a/panda/src/framework/pandaFramework.cxx +++ b/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-b", "report bounding volume", event_B, 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("arrow_up", "move highlight to parent", event_arrow_up, 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(); } +//////////////////////////////////////////////////////////////////// +// 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 // Access: Public, Static diff --git a/panda/src/framework/pandaFramework.h b/panda/src/framework/pandaFramework.h index e7bb83ed8a..4a5363d384 100644 --- a/panda/src/framework/pandaFramework.h +++ b/panda/src/framework/pandaFramework.h @@ -136,6 +136,7 @@ public: static void event_C(const Event *, void *data); static void event_B(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_arrow_up(const Event *, void *data); static void event_arrow_down(const Event *, void *data); diff --git a/panda/src/pgraph/cullBin.cxx b/panda/src/pgraph/cullBin.cxx index 587154394e..b081b05a11 100644 --- a/panda/src/pgraph/cullBin.cxx +++ b/panda/src/pgraph/cullBin.cxx @@ -18,6 +18,11 @@ #include "cullBin.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"); @@ -63,6 +68,29 @@ void CullBin:: 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 // Access: Private @@ -96,3 +124,98 @@ check_flash_color() { } #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); +} diff --git a/panda/src/pgraph/cullBin.h b/panda/src/pgraph/cullBin.h index 3d98b81be7..52c6bd3f9a 100644 --- a/panda/src/pgraph/cullBin.h +++ b/panda/src/pgraph/cullBin.h @@ -29,6 +29,10 @@ class CullableObject; class GraphicsStateGuardianBase; class SceneSetup; +class TransformState; +class RenderState; +class PandaNode; +class GeomNode; //////////////////////////////////////////////////////////////////// // Class : CullBin @@ -60,9 +64,15 @@ public: virtual void draw(bool force, Thread *current_thread)=0; + PT(PandaNode) make_result_graph(); + INLINE bool has_flash_color() const; INLINE const Colorf &get_flash_color() const; +protected: + class ResultGraphBuilder; + virtual void fill_result_graph(ResultGraphBuilder &builder)=0; + private: void check_flash_color(); @@ -74,6 +84,23 @@ protected: bool _has_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; PStatCollector _cull_this_pcollector; PStatCollector _draw_this_pcollector; diff --git a/panda/src/pgraph/cullResult.cxx b/panda/src/pgraph/cullResult.cxx index f29e550b68..c4a0e4f6c7 100644 --- a/panda/src/pgraph/cullResult.cxx +++ b/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 // Access: Public, Static diff --git a/panda/src/pgraph/cullResult.h b/panda/src/pgraph/cullResult.h index 9b9112d201..b98648921e 100644 --- a/panda/src/pgraph/cullResult.h +++ b/panda/src/pgraph/cullResult.h @@ -63,6 +63,8 @@ public: void finish_cull(SceneSetup *scene_setup, Thread *current_thread); void draw(Thread *current_thread); + PT(PandaNode) make_result_graph(); + public: static void bin_removed(int bin_index);