From fe70bd5e1de4c345f3c6bbcee98651f142f4dc05 Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 15 Jun 2001 02:02:31 +0000 Subject: [PATCH] pstats frustum cull, add set_final to bounded object --- panda/src/display/graphicsStateGuardian.cxx | 7 ++ panda/src/display/graphicsStateGuardian.h | 2 + panda/src/graph/boundedObject.I | 86 ++++++++++++++----- panda/src/graph/boundedObject.cxx | 2 +- panda/src/graph/boundedObject.h | 9 +- panda/src/pstatclient/pStatProperties.cxx | 2 + panda/src/sgraphutil/Sources.pp | 7 +- panda/src/sgraphutil/frustumCullTraverser.I | 11 ++- panda/src/sgraphutil/frustumCullTraverser.cxx | 19 ++++ panda/src/sgraphutil/frustumCullTraverser.h | 2 +- .../src/sgraphutil/sgraphutil_composite1.cxx | 1 + 11 files changed, 120 insertions(+), 28 deletions(-) create mode 100644 panda/src/sgraphutil/frustumCullTraverser.cxx diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index c3c31bf155..d453292124 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -47,6 +47,9 @@ PStatCollector GraphicsStateGuardian::_transform_state_pcollector("State changes PStatCollector GraphicsStateGuardian::_texture_state_pcollector("State changes:Textures"); PStatCollector GraphicsStateGuardian::_nodes_pcollector("Nodes"); PStatCollector GraphicsStateGuardian::_geom_nodes_pcollector("Nodes:GeomNodes"); +PStatCollector GraphicsStateGuardian::_frustum_cull_volumes_pcollector("Cull volumes"); +PStatCollector GraphicsStateGuardian::_frustum_cull_transforms_pcollector("Cull volumes:Transforms"); + #endif TypeHandle GraphicsStateGuardian::_type_handle; @@ -759,6 +762,10 @@ init_frame_pstats() { _nodes_pcollector.clear_level(); _geom_nodes_pcollector.clear_level(); + + // Not to mention the view-frustum-cull counters. + _frustum_cull_volumes_pcollector.clear_level(); + _frustum_cull_transforms_pcollector.clear_level(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index cc48688d10..83905c0bf0 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -232,6 +232,8 @@ public: static PStatCollector _texture_state_pcollector; static PStatCollector _nodes_pcollector; static PStatCollector _geom_nodes_pcollector; + static PStatCollector _frustum_cull_volumes_pcollector; + static PStatCollector _frustum_cull_transforms_pcollector; private: // NOTE: on win32 another DLL (e.g. libpandadx.dll) cannot access diff --git a/panda/src/graph/boundedObject.I b/panda/src/graph/boundedObject.I index 35bfc47eb0..827c8966ab 100644 --- a/panda/src/graph/boundedObject.I +++ b/panda/src/graph/boundedObject.I @@ -18,20 +18,38 @@ #include +//////////////////////////////////////////////////////////////////// +// Function: BoundedObject::is_bound_stale +// Access: Published +// Description: Returns true if the bound is currently marked stale +// and will be recomputed the next time get_bound() is +// called. +// +// This function is defined up at the top of this file, +// because several of the inline functions below +// reference it. +//////////////////////////////////////////////////////////////////// +INLINE_GRAPH bool BoundedObject:: +is_bound_stale() const { + return (_flags & F_bound_stale) != 0; +} + + + //////////////////////////////////////////////////////////////////// // Function: BoundedObject::Constructor -// Access: Public +// Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE_GRAPH BoundedObject:: BoundedObject() { _bound_type = BVT_dynamic_sphere; - _bound_stale = true; + _flags = F_bound_stale; } //////////////////////////////////////////////////////////////////// // Function: BoundedObject::set_bound -// Access: Public +// Access: Published // Description: Sets the type of the bounding volume that will be // dynamically computed for this particular node. // Presently, this should only be BVT_dynamic_sphere. @@ -45,7 +63,7 @@ set_bound(BoundedObject::BoundingVolumeType type) { //////////////////////////////////////////////////////////////////// // Function: BoundedObject::set_bound -// Access: Public +// Access: Published // Description: Explicitly sets a new bounding volume on this node. // This will be a static bounding volume that will no // longer be recomputed automatically. @@ -54,13 +72,13 @@ INLINE_GRAPH void BoundedObject:: set_bound(const BoundingVolume &bound) { mark_bound_stale(); _bound_type = BVT_static; - _bound_stale = false; + _flags &= ~F_bound_stale; _bound = bound.make_copy(); } //////////////////////////////////////////////////////////////////// // Function: BoundedObject::get_bound -// Access: Public +// Access: Published // Description: Returns the current bounding volume on this node, // possibly forcing a recompute. A node's bounding // volume encloses only the node itself, irrespective of @@ -71,8 +89,8 @@ set_bound(const BoundingVolume &bound) { INLINE_GRAPH const BoundingVolume &BoundedObject:: get_bound() const { if (_bound_type == BVT_static) { - ((BoundedObject *)this)->_bound_stale = false; - } else if (_bound_stale || _bound == (BoundingVolume *)NULL) { + ((BoundedObject *)this)->_flags &= ~F_bound_stale; + } else if (is_bound_stale() || _bound == (BoundingVolume *)NULL) { ((BoundedObject *)this)->recompute_bound(); } return *_bound; @@ -80,7 +98,7 @@ get_bound() const { //////////////////////////////////////////////////////////////////// // Function: BoundedObject::mark_bound_stale -// Access: Public +// Access: Published // Description: Marks the current bounding volume as stale, so that // it will be recomputed later. This may have a // cascading effect up to the root of all graphs of @@ -90,10 +108,10 @@ get_bound() const { //////////////////////////////////////////////////////////////////// INLINE_GRAPH bool BoundedObject:: mark_bound_stale() { - if (_bound_stale) { + if (is_bound_stale()) { return false; } - _bound_stale = true; + _flags |= F_bound_stale; propagate_stale_bound(); return true; @@ -101,26 +119,52 @@ mark_bound_stale() { //////////////////////////////////////////////////////////////////// // Function: BoundedObject::force_bound_stale -// Access: Public +// Access: Published // Description: Marks the current volume as stale and propagates the // effect at least one level, even if it had already // been marked stale. //////////////////////////////////////////////////////////////////// INLINE_GRAPH void BoundedObject:: force_bound_stale() { - _bound_stale = true; + _flags |= F_bound_stale; propagate_stale_bound(); } //////////////////////////////////////////////////////////////////// -// Function: BoundedObject::is_bound_stale -// Access: Public -// Description: Returns true if the bound is currently marked stale -// and will be recomputed the next time get_bound() is -// called. +// Function: BoundedObject::set_final +// Access: Published +// Description: Sets the "final" flag on this BoundedObject. If +// this is true, than no bounding volume need be tested +// below it; a positive intersection with this bounding +// volume is deemed to be a positive intersection with +// all geometry inside. +// +// This is useful to quickly force a larger bounding +// volume around a node when the GeomNodes themselves +// are inaccurate for some reason, without forcing a +// recompute of every nested bounding volume. It's also +// helpful when the bounding volume is tricked by some +// special properties, like billboards, that may move +// geometry out of its bounding volume otherwise. //////////////////////////////////////////////////////////////////// -INLINE_GRAPH bool BoundedObject:: -is_bound_stale() const { - return _bound_stale; +INLINE_GRAPH void BoundedObject:: +set_final(bool flag) { + if (flag) { + _flags |= F_final; + } else { + _flags &= ~F_final; + } } +//////////////////////////////////////////////////////////////////// +// Function: BoundedObject::is_final +// Access: Published +// Description: Returns the current state of the "final" flag. +// Initially, this flag is off (false), but it may be +// changed by an explicit call to set_final(). See +// set_final(). +//////////////////////////////////////////////////////////////////// +INLINE_GRAPH bool BoundedObject:: +is_final() const { + return (_flags & F_final) != 0; +} diff --git a/panda/src/graph/boundedObject.cxx b/panda/src/graph/boundedObject.cxx index 93bd969b1b..b14a570374 100644 --- a/panda/src/graph/boundedObject.cxx +++ b/panda/src/graph/boundedObject.cxx @@ -65,6 +65,6 @@ recompute_bound() { _bound = NULL; } - _bound_stale = false; + _flags &= ~F_bound_stale; // By default, the bound is empty. } diff --git a/panda/src/graph/boundedObject.h b/panda/src/graph/boundedObject.h index 3e86099b50..f4eb097975 100644 --- a/panda/src/graph/boundedObject.h +++ b/panda/src/graph/boundedObject.h @@ -53,12 +53,19 @@ PUBLISHED: INLINE_GRAPH void force_bound_stale(); INLINE_GRAPH bool is_bound_stale() const; + INLINE_GRAPH void set_final(bool flag); + INLINE_GRAPH bool is_final() const; + protected: virtual void propagate_stale_bound(); virtual void recompute_bound(); private: - bool _bound_stale; + enum Flags { + F_bound_stale = 0x0001, + F_final = 0x0002, + }; + int _flags; BoundingVolumeType _bound_type; protected: diff --git a/panda/src/pstatclient/pStatProperties.cxx b/panda/src/pstatclient/pStatProperties.cxx index b812410751..9a4c73bbe1 100644 --- a/panda/src/pstatclient/pStatProperties.cxx +++ b/panda/src/pstatclient/pStatProperties.cxx @@ -149,6 +149,8 @@ static LevelCollectorProperties level_properties[] = { { 1, "Vertices:Display lists", { 0.8, 0.5, 1.0 } }, { 1, "Nodes", { 0.4, 0.2, 0.8 }, "", 500.0 }, { 1, "Nodes:GeomNodes", { 0.8, 0.2, 0.0 } }, + { 1, "Cull volumes", { 0.7, 0.6, 0.9 }, "", 500.0 }, + { 1, "Cull volumes:Transforms", { 0.9, 0.6, 0.0 } }, { 1, "State changes", { 1.0, 0.5, 0.2 }, "", 500.0 }, { 1, "State changes:Transforms", { 0.2, 0.2, 0.8 } }, { 1, "State changes:Textures", { 0.8, 0.2, 0.2 } }, diff --git a/panda/src/sgraphutil/Sources.pp b/panda/src/sgraphutil/Sources.pp index fdb85f652e..7a8c22ee43 100644 --- a/panda/src/sgraphutil/Sources.pp +++ b/panda/src/sgraphutil/Sources.pp @@ -4,8 +4,8 @@ #begin lib_target #define TARGET sgraphutil #define LOCAL_LIBS \ - graph sgraph sgattrib linmath putil gobj mathutil gsgbase display \ - pnmimage + pstatclient graph sgraph sgattrib linmath putil gobj mathutil \ + gsgbase display pnmimage #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx @@ -18,7 +18,8 @@ #define INCLUDED_SOURCES \ appTraverser.cxx config_sgraphutil.cxx directRenderTraverser.cxx \ - get_rel_pos.cxx sceneGraphAnalyzer.cxx sceneGraphReducer.cxx + frustumCullTraverser.cxx get_rel_pos.cxx sceneGraphAnalyzer.cxx \ + sceneGraphReducer.cxx #define INSTALL_HEADERS \ appTraverser.I appTraverser.h config_sgraphutil.h \ diff --git a/panda/src/sgraphutil/frustumCullTraverser.I b/panda/src/sgraphutil/frustumCullTraverser.I index 36f8b2759d..769f1f23a4 100644 --- a/panda/src/sgraphutil/frustumCullTraverser.I +++ b/panda/src/sgraphutil/frustumCullTraverser.I @@ -63,6 +63,8 @@ FrustumCullTraverser(ArcChain &arc_chain, Node *root, local_frustum = DCAST(GeometricBoundingVolume, _view_frustum->make_copy()); local_frustum->xform(rel_from_camera); + GraphicsStateGuardian::_frustum_cull_volumes_pcollector.add_level(1); + GraphicsStateGuardian::_frustum_cull_transforms_pcollector.add_level(1); if (sgraphutil_cat.is_spam()) { sgraphutil_cat.spam() @@ -130,6 +132,7 @@ traverse(NodeRelation *arc, AttributeWrapper render_state, nassertv(local_frustum != (GeometricBoundingVolume *)NULL); int result = local_frustum->contains(arc_gbv); + GraphicsStateGuardian::_frustum_cull_volumes_pcollector.add_level(1); if (result == BoundingVolume::IF_no_intersection) { // No intersection at all. Cull. if (sgraphutil_cat.is_spam()) { @@ -175,11 +178,16 @@ traverse(NodeRelation *arc, AttributeWrapper render_state, } if (carry_on) { - if (arc->has_transition(BillboardTransition::get_class_type())) { + if (arc->is_final() || + arc->has_transition(BillboardTransition::get_class_type())) { // We can't reliably cull within a billboard, because the // geometry might get rotated out of its bounding volume. // So once we get within a billboard, we consider it all // visible. + + // Also, if the arc has the "final" flag, the user is + // claiming that there is some other reason we should + // consider everything visible at this point. So be it. all_in = true; } @@ -205,6 +213,7 @@ traverse(NodeRelation *arc, AttributeWrapper render_state, // be. nassertv(local_frustum != (GeometricBoundingVolume *)NULL); local_frustum->xform(tt->get_matrix()); + GraphicsStateGuardian::_frustum_cull_transforms_pcollector.add_level(1); if (sgraphutil_cat.is_spam()) { sgraphutil_cat.spam() diff --git a/panda/src/sgraphutil/frustumCullTraverser.cxx b/panda/src/sgraphutil/frustumCullTraverser.cxx new file mode 100644 index 0000000000..f43665d99b --- /dev/null +++ b/panda/src/sgraphutil/frustumCullTraverser.cxx @@ -0,0 +1,19 @@ +// Filename: frustumCullTraverser.cxx +// Created by: drose (14Jun01) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "frustumCullTraverser.h" diff --git a/panda/src/sgraphutil/frustumCullTraverser.h b/panda/src/sgraphutil/frustumCullTraverser.h index 26ddf3dbbb..af3ce186e5 100644 --- a/panda/src/sgraphutil/frustumCullTraverser.h +++ b/panda/src/sgraphutil/frustumCullTraverser.h @@ -33,11 +33,11 @@ #include #include #include +#include #include "config_sgraphutil.h" - /////////////////////////////////////////////////////////////////// // Class : FrustumCullTraverser // Description : A special kind of depth-first traverser that can diff --git a/panda/src/sgraphutil/sgraphutil_composite1.cxx b/panda/src/sgraphutil/sgraphutil_composite1.cxx index 824699f69c..08ae1ce9ae 100644 --- a/panda/src/sgraphutil/sgraphutil_composite1.cxx +++ b/panda/src/sgraphutil/sgraphutil_composite1.cxx @@ -2,4 +2,5 @@ #include "appTraverser.cxx" #include "config_sgraphutil.cxx" #include "directRenderTraverser.cxx" +#include "frustumCullTraverser.cxx"