瀏覽代碼

pstats frustum cull, add set_final to bounded object

David Rose 24 年之前
父節點
當前提交
fe70bd5e1d

+ 7 - 0
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::_texture_state_pcollector("State changes:Textures");
 PStatCollector GraphicsStateGuardian::_nodes_pcollector("Nodes");
 PStatCollector GraphicsStateGuardian::_nodes_pcollector("Nodes");
 PStatCollector GraphicsStateGuardian::_geom_nodes_pcollector("Nodes:GeomNodes");
 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
 #endif
 
 
 TypeHandle GraphicsStateGuardian::_type_handle;
 TypeHandle GraphicsStateGuardian::_type_handle;
@@ -759,6 +762,10 @@ init_frame_pstats() {
 
 
   _nodes_pcollector.clear_level();
   _nodes_pcollector.clear_level();
   _geom_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();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

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

@@ -232,6 +232,8 @@ public:
   static PStatCollector _texture_state_pcollector;
   static PStatCollector _texture_state_pcollector;
   static PStatCollector _nodes_pcollector;
   static PStatCollector _nodes_pcollector;
   static PStatCollector _geom_nodes_pcollector;
   static PStatCollector _geom_nodes_pcollector;
+  static PStatCollector _frustum_cull_volumes_pcollector;
+  static PStatCollector _frustum_cull_transforms_pcollector;
 
 
 private:
 private:
   // NOTE: on win32 another DLL (e.g. libpandadx.dll) cannot access
   // NOTE: on win32 another DLL (e.g. libpandadx.dll) cannot access

+ 65 - 21
panda/src/graph/boundedObject.I

@@ -18,20 +18,38 @@
 
 
 #include <notify.h>
 #include <notify.h>
 
 
+////////////////////////////////////////////////////////////////////
+//     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
 //     Function: BoundedObject::Constructor
-//       Access: Public
+//       Access: Published
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE_GRAPH BoundedObject::
 INLINE_GRAPH BoundedObject::
 BoundedObject() {
 BoundedObject() {
   _bound_type = BVT_dynamic_sphere;
   _bound_type = BVT_dynamic_sphere;
-  _bound_stale = true;
+  _flags = F_bound_stale;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: BoundedObject::set_bound
 //     Function: BoundedObject::set_bound
-//       Access: Public
+//       Access: Published
 //  Description: Sets the type of the bounding volume that will be
 //  Description: Sets the type of the bounding volume that will be
 //               dynamically computed for this particular node.
 //               dynamically computed for this particular node.
 //               Presently, this should only be BVT_dynamic_sphere.
 //               Presently, this should only be BVT_dynamic_sphere.
@@ -45,7 +63,7 @@ set_bound(BoundedObject::BoundingVolumeType type) {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: BoundedObject::set_bound
 //     Function: BoundedObject::set_bound
-//       Access: Public
+//       Access: Published
 //  Description: Explicitly sets a new bounding volume on this node.
 //  Description: Explicitly sets a new bounding volume on this node.
 //               This will be a static bounding volume that will no
 //               This will be a static bounding volume that will no
 //               longer be recomputed automatically.
 //               longer be recomputed automatically.
@@ -54,13 +72,13 @@ INLINE_GRAPH void BoundedObject::
 set_bound(const BoundingVolume &bound) {
 set_bound(const BoundingVolume &bound) {
   mark_bound_stale();
   mark_bound_stale();
   _bound_type = BVT_static;
   _bound_type = BVT_static;
-  _bound_stale = false;
+  _flags &= ~F_bound_stale;  
   _bound = bound.make_copy();
   _bound = bound.make_copy();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: BoundedObject::get_bound
 //     Function: BoundedObject::get_bound
-//       Access: Public
+//       Access: Published
 //  Description: Returns the current bounding volume on this node,
 //  Description: Returns the current bounding volume on this node,
 //               possibly forcing a recompute.  A node's bounding
 //               possibly forcing a recompute.  A node's bounding
 //               volume encloses only the node itself, irrespective of
 //               volume encloses only the node itself, irrespective of
@@ -71,8 +89,8 @@ set_bound(const BoundingVolume &bound) {
 INLINE_GRAPH const BoundingVolume &BoundedObject::
 INLINE_GRAPH const BoundingVolume &BoundedObject::
 get_bound() const {
 get_bound() const {
   if (_bound_type == BVT_static) {
   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();
     ((BoundedObject *)this)->recompute_bound();
   }
   }
   return *_bound;
   return *_bound;
@@ -80,7 +98,7 @@ get_bound() const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: BoundedObject::mark_bound_stale
 //     Function: BoundedObject::mark_bound_stale
-//       Access: Public
+//       Access: Published
 //  Description: Marks the current bounding volume as stale, so that
 //  Description: Marks the current bounding volume as stale, so that
 //               it will be recomputed later.  This may have a
 //               it will be recomputed later.  This may have a
 //               cascading effect up to the root of all graphs of
 //               cascading effect up to the root of all graphs of
@@ -90,10 +108,10 @@ get_bound() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE_GRAPH bool BoundedObject::
 INLINE_GRAPH bool BoundedObject::
 mark_bound_stale() {
 mark_bound_stale() {
-  if (_bound_stale) {
+  if (is_bound_stale()) {
     return false;
     return false;
   }
   }
-  _bound_stale = true;
+  _flags |= F_bound_stale;
   propagate_stale_bound();
   propagate_stale_bound();
 
 
   return true;
   return true;
@@ -101,26 +119,52 @@ mark_bound_stale() {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: BoundedObject::force_bound_stale
 //     Function: BoundedObject::force_bound_stale
-//       Access: Public
+//       Access: Published
 //  Description: Marks the current volume as stale and propagates the
 //  Description: Marks the current volume as stale and propagates the
 //               effect at least one level, even if it had already
 //               effect at least one level, even if it had already
 //               been marked stale.
 //               been marked stale.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE_GRAPH void BoundedObject::
 INLINE_GRAPH void BoundedObject::
 force_bound_stale() {
 force_bound_stale() {
-  _bound_stale = true;
+  _flags |= F_bound_stale;
   propagate_stale_bound();
   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;
+}

+ 1 - 1
panda/src/graph/boundedObject.cxx

@@ -65,6 +65,6 @@ recompute_bound() {
     _bound = NULL;
     _bound = NULL;
   }
   }
 
 
-  _bound_stale = false;
+  _flags &= ~F_bound_stale;
   // By default, the bound is empty.
   // By default, the bound is empty.
 }
 }

+ 8 - 1
panda/src/graph/boundedObject.h

@@ -53,12 +53,19 @@ PUBLISHED:
   INLINE_GRAPH void force_bound_stale();
   INLINE_GRAPH void force_bound_stale();
   INLINE_GRAPH bool is_bound_stale() const;
   INLINE_GRAPH bool is_bound_stale() const;
 
 
+  INLINE_GRAPH void set_final(bool flag);
+  INLINE_GRAPH bool is_final() const;
+
 protected:
 protected:
   virtual void propagate_stale_bound();
   virtual void propagate_stale_bound();
   virtual void recompute_bound();
   virtual void recompute_bound();
 
 
 private:
 private:
-  bool _bound_stale;
+  enum Flags {
+    F_bound_stale  = 0x0001,
+    F_final        = 0x0002,
+  };
+  int _flags;
   BoundingVolumeType _bound_type;
   BoundingVolumeType _bound_type;
 
 
 protected:
 protected:

+ 2 - 0
panda/src/pstatclient/pStatProperties.cxx

@@ -149,6 +149,8 @@ static LevelCollectorProperties level_properties[] = {
   { 1, "Vertices:Display lists",           { 0.8, 0.5, 1.0 } },
   { 1, "Vertices:Display lists",           { 0.8, 0.5, 1.0 } },
   { 1, "Nodes",                            { 0.4, 0.2, 0.8 },  "", 500.0 },
   { 1, "Nodes",                            { 0.4, 0.2, 0.8 },  "", 500.0 },
   { 1, "Nodes:GeomNodes",                  { 0.8, 0.2, 0.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",                    { 1.0, 0.5, 0.2 },  "", 500.0 },
   { 1, "State changes:Transforms",         { 0.2, 0.2, 0.8 } },
   { 1, "State changes:Transforms",         { 0.2, 0.2, 0.8 } },
   { 1, "State changes:Textures",           { 0.8, 0.2, 0.2 } },
   { 1, "State changes:Textures",           { 0.8, 0.2, 0.2 } },

+ 4 - 3
panda/src/sgraphutil/Sources.pp

@@ -4,8 +4,8 @@
 #begin lib_target
 #begin lib_target
   #define TARGET sgraphutil
   #define TARGET sgraphutil
   #define LOCAL_LIBS \
   #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 
   #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx 
 
 
@@ -18,7 +18,8 @@
 
 
   #define INCLUDED_SOURCES  \
   #define INCLUDED_SOURCES  \
      appTraverser.cxx config_sgraphutil.cxx directRenderTraverser.cxx  \
      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 \
   #define INSTALL_HEADERS \
     appTraverser.I appTraverser.h config_sgraphutil.h \
     appTraverser.I appTraverser.h config_sgraphutil.h \

+ 10 - 1
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 = DCAST(GeometricBoundingVolume, _view_frustum->make_copy());
     local_frustum->xform(rel_from_camera);
     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()) {
     if (sgraphutil_cat.is_spam()) {
       sgraphutil_cat.spam()
       sgraphutil_cat.spam()
@@ -130,6 +132,7 @@ traverse(NodeRelation *arc, AttributeWrapper render_state,
 
 
         nassertv(local_frustum != (GeometricBoundingVolume *)NULL);
         nassertv(local_frustum != (GeometricBoundingVolume *)NULL);
         int result = local_frustum->contains(arc_gbv);
         int result = local_frustum->contains(arc_gbv);
+        GraphicsStateGuardian::_frustum_cull_volumes_pcollector.add_level(1);
         if (result == BoundingVolume::IF_no_intersection) {
         if (result == BoundingVolume::IF_no_intersection) {
           // No intersection at all.  Cull.
           // No intersection at all.  Cull.
           if (sgraphutil_cat.is_spam()) {
           if (sgraphutil_cat.is_spam()) {
@@ -175,11 +178,16 @@ traverse(NodeRelation *arc, AttributeWrapper render_state,
       }
       }
 
 
       if (carry_on) {
       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
           // We can't reliably cull within a billboard, because the
           // geometry might get rotated out of its bounding volume.
           // geometry might get rotated out of its bounding volume.
           // So once we get within a billboard, we consider it all
           // So once we get within a billboard, we consider it all
           // visible.
           // 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;
           all_in = true;
         }
         }
 
 
@@ -205,6 +213,7 @@ traverse(NodeRelation *arc, AttributeWrapper render_state,
             // be.
             // be.
             nassertv(local_frustum != (GeometricBoundingVolume *)NULL);
             nassertv(local_frustum != (GeometricBoundingVolume *)NULL);
             local_frustum->xform(tt->get_matrix());
             local_frustum->xform(tt->get_matrix());
+            GraphicsStateGuardian::_frustum_cull_transforms_pcollector.add_level(1);
 
 
             if (sgraphutil_cat.is_spam()) {
             if (sgraphutil_cat.is_spam()) {
               sgraphutil_cat.spam()
               sgraphutil_cat.spam()

+ 19 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "frustumCullTraverser.h"

+ 1 - 1
panda/src/sgraphutil/frustumCullTraverser.h

@@ -33,11 +33,11 @@
 #include <transformTransition.h>
 #include <transformTransition.h>
 #include <billboardTransition.h>
 #include <billboardTransition.h>
 #include <wrt.h>
 #include <wrt.h>
+#include <pStatCollector.h>
 
 
 #include "config_sgraphutil.h"
 #include "config_sgraphutil.h"
 
 
 
 
-
 ///////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////
 //       Class : FrustumCullTraverser
 //       Class : FrustumCullTraverser
 // Description : A special kind of depth-first traverser that can
 // Description : A special kind of depth-first traverser that can

+ 1 - 0
panda/src/sgraphutil/sgraphutil_composite1.cxx

@@ -2,4 +2,5 @@
 #include "appTraverser.cxx"
 #include "appTraverser.cxx"
 #include "config_sgraphutil.cxx"
 #include "config_sgraphutil.cxx"
 #include "directRenderTraverser.cxx"
 #include "directRenderTraverser.cxx"
+#include "frustumCullTraverser.cxx"