浏览代码

add oobeCull mode

David Rose 24 年之前
父节点
当前提交
6be3c950da

+ 47 - 2
direct/src/showbase/ShowBase.py

@@ -450,6 +450,7 @@ class ShowBase:
             self.oobeButtonEventsType = TypeRegistry.ptr().findType('ButtonEvents_ButtonEventDataTransition')
 
             self.oobeVis = loader.loadModelOnce('models/misc/camera')
+            self.oobeCullFrustum = None
 
             # Make sure the MouseValve is monitoring the Control key.
             mods = ModifierButtons(self.mouseValve.node().getModifierButtons())
@@ -458,13 +459,18 @@ class ShowBase:
 
         if self.oobeMode:
             # Disable OOBE mode.
+
+            if self.oobeCullFrustum != None:
+                # First, disable OOBE cull mode.
+                self.oobeCull()
+            
             self.oobeControl.setOff()
             self.mouseControl.setOn()
             if self.oobeVis:
                 self.oobeVis.reparentTo(self.hidden)
             self.cam.reparentTo(self.camera)
             self.oobeCamera.reparentTo(self.hidden)
-            self.oobeMode = 0
+            self.oobeMode = 0            
         else:
             # Enable OOBE mode.
             mods = ModifierButtons(self.mouseValve.node().getModifierButtons())
@@ -488,7 +494,7 @@ class ShowBase:
             self.oobeCamera.clearMat()
 
             # Set our initial OOB position to be just behind the camera.
-            mat = Mat4.translateMat(0, -10, 3) * base.camera.getMat(cameraParent)
+            mat = Mat4.translateMat(0, -10, 3) * self.camera.getMat(cameraParent)
             mat.invertInPlace()
             self.oobeTrackball.node().setMat(mat)
 
@@ -497,6 +503,45 @@ class ShowBase:
                 self.oobeVis.reparentTo(self.camera)
             self.oobeMode = 1
 
+    def oobeCull(self):
+        """
+        While in OOBE mode (see above), cull the viewing frustum as if
+        it were still attached to our original camera.  This allows us
+        to visualize the effectiveness of our bounding volumes.
+        """
+
+        # First, make sure OOBE mode is enabled.
+        try:
+            if not self.oobeMode:
+                self.oobe()
+        except:
+            self.oobe()
+
+        if self.oobeCullFrustum == None:
+            # Enable OOBE culling.
+            pnode = ProjectionNode('oobeCull')
+            pnode.setProjection(self.camNode.getProjection())
+            self.oobeCullFrustum = self.camera.attachNewNode(pnode)
+
+            # Assign each DisplayRegion shared by the camera to use
+            # this cull frustum.
+            numDrs = self.camNode.getNumDrs()
+            for d in range(0, numDrs):
+                dr = self.camNode.getDr(d)
+                dr.setCullFrustum(pnode)
+        else:
+            # Disable OOBE culling.
+
+            # Assign each DisplayRegion shared by the camera to use
+            # the default cull frustum, the camera itself.
+            numDrs = self.camNode.getNumDrs()
+            for d in range(0, numDrs):
+                dr = self.camNode.getDr(d)
+                dr.setCullFrustum(self.camNode)
+
+            self.oobeCullFrustum.removeNode()
+            self.oobeCullFrustum = None
+
     def screenshot(self, namePrefix='screenshot'):
         # Get the current date and time to uniquify the image (down to the second)
         date = time.ctime(time.time())

+ 4 - 2
panda/src/cull/cullTraverser.cxx

@@ -41,6 +41,7 @@
 #endif
 
 #include <wrt.h>
+#include <displayRegion.h>
 #include <frustumCullTraverser.h>
 #include <pruneTransition.h>
 #include <decalTransition.h>
@@ -270,8 +271,9 @@ traverse(Node *root,
   // culling.
   LMatrix4f rel_from_camera;
   NodeTransitionWrapper ntw(TransformTransition::get_class_type());
-  wrt(_gsg->get_current_projection_node(), root, begin(), end(),
-      ntw, get_graph_type());
+  const DisplayRegion *dr = _gsg->get_current_display_region();
+  ProjectionNode *camera = dr->get_cull_frustum();
+  wrt(camera, root, begin(), end(), ntw, get_graph_type());
   const TransformTransition *tt;
   if (get_transition_into(tt, ntw)) {
     rel_from_camera = tt->get_matrix();

+ 30 - 1
panda/src/display/displayRegion.I

@@ -49,11 +49,40 @@ get_layer() const {
 //  Description: Returns the camera associated with this
 //               DisplayRegion, or NULL if no camera is associated.
 ////////////////////////////////////////////////////////////////////
-INLINE PT(Camera) DisplayRegion::
+INLINE Camera *DisplayRegion::
 get_camera() const {
   return _camera;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::set_cull_frustum
+//       Access: Public
+//  Description: Sets the ProjectionNode that will be used to perform
+//               view-frustum culling for this particular
+//               DisplayRegion.  Normally, this is the same as the
+//               camera (and is implicitly set when set_camera() is
+//               called).  However, it may be useful to occasionally
+//               set it to a different node, particularly to enable a
+//               debugging mode where the culling effectiveness can be
+//               observed from a third-person perspective.
+////////////////////////////////////////////////////////////////////
+void DisplayRegion::
+set_cull_frustum(ProjectionNode *cull_frustum) {
+  _cull_frustum = cull_frustum;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_cull_frustum
+//       Access: Public
+//  Description: Returns the ProjectionNode that will be used to
+//               perform view-frustum culling for this particular
+//               DisplayRegion.  See set_cull_frustum().
+////////////////////////////////////////////////////////////////////
+INLINE ProjectionNode *DisplayRegion::
+get_cull_frustum() const {
+  return _cull_frustum;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DisplayRegion::set_active
 //       Access: Public

+ 2 - 1
panda/src/display/displayRegion.cxx

@@ -174,7 +174,7 @@ get_pipe() const {
 //               between multiple DisplayRegions.
 ////////////////////////////////////////////////////////////////////
 void DisplayRegion::
-set_camera(const PT(Camera) &camera) {
+set_camera(Camera *camera) {
   if (camera != _camera) {
     if (_camera != (Camera *)NULL) {
       // We need to tell the old camera we're not using him anymore.
@@ -186,6 +186,7 @@ set_camera(const PT(Camera) &camera) {
       _camera->add_display_region(this);
     }
   }
+  set_cull_frustum(camera);
 }
 
 ////////////////////////////////////////////////////////////////////

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

@@ -58,8 +58,11 @@ PUBLISHED:
   GraphicsWindow *get_window() const;
   GraphicsPipe *get_pipe() const;
 
-  void set_camera(const PT(Camera) &camera);
-  INLINE PT(Camera) get_camera() const;
+  void set_camera(Camera *camera);
+  INLINE Camera *get_camera() const;
+
+  INLINE void set_cull_frustum(ProjectionNode *cull_frustum);
+  INLINE ProjectionNode *get_cull_frustum() const;
 
   INLINE void set_active(bool active);
   INLINE bool is_active() const;
@@ -87,6 +90,7 @@ protected:
 
   GraphicsLayer *_layer;
   PT(Camera) _camera;
+  PT(ProjectionNode) _cull_frustum;
 
   bool _active;
 

+ 3 - 3
panda/src/display/graphicsStateGuardian.I

@@ -88,7 +88,7 @@ get_current_root_node(void) const {
 //               region will be made active (if it is not already) by
 //               a call to prepare_display_region().
 ////////////////////////////////////////////////////////////////////
-INLINE CPT(DisplayRegion) GraphicsStateGuardian::
+INLINE const DisplayRegion *GraphicsStateGuardian::
 get_current_display_region(void) const {
   return _current_display_region;
 }
@@ -107,7 +107,7 @@ get_current_display_region(void) const {
 //               optimization.
 ////////////////////////////////////////////////////////////////////
 INLINE DisplayRegionStack GraphicsStateGuardian::
-push_display_region(CPT(DisplayRegion) dr) {
+push_display_region(const DisplayRegion *dr) {
   DisplayRegionStack old;
   old._display_region = _current_display_region;
   old._stack_level = _display_region_stack_level;
@@ -147,7 +147,7 @@ pop_display_region(DisplayRegionStack &node) {
 ////////////////////////////////////////////////////////////////////
 INLINE FrameBufferStack GraphicsStateGuardian::
 push_frame_buffer(const RenderBuffer &buffer,
-                  CPT(DisplayRegion) dr) {
+                  const DisplayRegion *dr) {
   FrameBufferStack old;
   old._frame_buffer = save_frame_buffer(buffer, dr);
   old._stack_level = _frame_buffer_stack_level;

+ 3 - 3
panda/src/display/graphicsStateGuardian.h

@@ -123,12 +123,12 @@ public:
   INLINE ProjectionNode *get_current_projection_node(void) const ;
   INLINE const Node* get_current_root_node(void) const;
 
-  INLINE CPT(DisplayRegion) get_current_display_region(void) const;
+  INLINE const DisplayRegion *get_current_display_region(void) const;
 
-  INLINE DisplayRegionStack push_display_region(CPT(DisplayRegion) dr);
+  INLINE DisplayRegionStack push_display_region(const DisplayRegion *dr);
   INLINE void pop_display_region(DisplayRegionStack &node);
   INLINE FrameBufferStack push_frame_buffer(const RenderBuffer &buffer,
-                                            CPT(DisplayRegion) dr);
+                                            const DisplayRegion *dr);
   INLINE void pop_frame_buffer(FrameBufferStack &node);
 
   INLINE void set_coordinate_system(CoordinateSystem cs);

+ 7 - 2
panda/src/sgattrib/billboardTransition.cxx

@@ -22,6 +22,7 @@
 #include "renderRelation.h"
 
 #include <graphicsStateGuardian.h>
+#include <displayRegion.h>
 #include <renderTraverser.h>
 #include <projectionNode.h>
 #include <look_at.h>
@@ -57,8 +58,12 @@ sub_render(NodeRelation *arc, const AllAttributesWrapper &,
   Node *node = arc->get_child();
   GraphicsStateGuardian *gsg = trav->get_gsg();
 
-  // Get the current camera from the gsg
-  const ProjectionNode *camera = gsg->get_current_projection_node();
+  // First, we have to get the current viewing frustum.  This is
+  // normally the same thing as the current camera, but the
+  // DisplayRegion may have some override in effect, so we ask the
+  // DisplayRegion instead of the GSG.
+  const DisplayRegion *dr = gsg->get_current_display_region();
+  ProjectionNode *camera = dr->get_cull_frustum();
   nassertr(camera != (ProjectionNode *)NULL, true);
 
   // And the relative coordinate space.

+ 2 - 2
panda/src/sgraph/projectionNode.cxx

@@ -69,8 +69,8 @@ share_projection(Projection *projection) {
 ////////////////////////////////////////////////////////////////////
 //     Function: get_projection
 //       Access: Public
-//  Description: Returns a pointer to particular Projection associated
-//               with this ProjectionNode.
+//  Description: Returns a pointer to the particular Projection
+//               associated with this ProjectionNode.
 ////////////////////////////////////////////////////////////////////
 Projection *ProjectionNode::
 get_projection() {

+ 4 - 2
panda/src/sgraphutil/directRenderTraverser.cxx

@@ -23,6 +23,7 @@
 #include <wrt.h>
 #include <geomNode.h>
 #include <graphicsStateGuardian.h>
+#include <displayRegion.h>
 #include <geometricBoundingVolume.h>
 #include <projectionNode.h>
 #include <projection.h>
@@ -103,8 +104,9 @@ traverse(Node *root,
   // culling.
   LMatrix4f rel_from_camera;
   NodeTransitionWrapper ntw(TransformTransition::get_class_type());
-  wrt(_gsg->get_current_projection_node(), root, begin(), end(),
-      ntw, get_graph_type());
+  const DisplayRegion *dr = _gsg->get_current_display_region();
+  ProjectionNode *camera = dr->get_cull_frustum();
+  wrt(camera, root, begin(), end(), ntw, get_graph_type());
   const TransformTransition *tt;
   if (get_transition_into(tt, ntw)) {
     rel_from_camera = tt->get_matrix();

+ 9 - 2
panda/src/sgraphutil/frustumCullTraverser.I

@@ -43,7 +43,12 @@ FrustumCullTraverser(ArcChain &arc_chain, Node *root,
     // If we're to be performing view-frustum culling, determine the
     // bounding volume associated with the current viewing frustum.
 
-    ProjectionNode *camera = _gsg->get_current_projection_node();
+    // First, we have to get the current viewing frustum.  This is
+    // normally the same thing as the current camera, but the
+    // DisplayRegion may have some override in effect, so we ask the
+    // DisplayRegion instead of the GSG.
+    const DisplayRegion *dr = _gsg->get_current_display_region();
+    ProjectionNode *camera = dr->get_cull_frustum();
     if (camera != (const ProjectionNode *)NULL) {
       const Projection *proj = camera->get_projection();
       nassertv(proj != (const Projection *)NULL);
@@ -188,7 +193,9 @@ traverse(NodeRelation *arc, AttributeWrapper render_state,
             DCAST(GeometricBoundingVolume, _view_frustum->make_copy());
 
           NodeTransitionWrapper ntw(TransformTransition::get_class_type());
-          wrt(_gsg->get_current_projection_node(),
+          const DisplayRegion *dr = _gsg->get_current_display_region();
+          ProjectionNode *camera = dr->get_cull_frustum();
+          wrt(camera,
               arc->get_child(), _arc_chain.begin(), _arc_chain.end(),
               ntw, _graph_type);
 

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

@@ -27,6 +27,7 @@
 #include <typedObject.h>
 #include <geometricBoundingVolume.h>
 #include <graphicsStateGuardian.h>
+#include <displayRegion.h>
 #include <arcChain.h>
 #include <nodeTransitionWrapper.h>
 #include <transformTransition.h>

+ 26 - 19
panda/src/switchnode/LODNode.cxx

@@ -20,6 +20,7 @@
 #include "config_switchnode.h"
 
 #include <graphicsStateGuardian.h>
+#include <displayRegion.h>
 #include <get_rel_pos.h>
 #include <luse.h>
 #include <renderRelation.h>
@@ -85,26 +86,32 @@ void LODNode::
 compute_switch(RenderTraverser *trav) {
   GraphicsStateGuardian *gsg = trav->get_gsg();
 
-  // Get the current camera position from the gsg
-  const ProjectionNode* camera = gsg->get_current_projection_node();
-  LPoint3f camera_pos(0, 0, 0);
-
-  // Get the LOD center in camera space
-  LPoint3f LOD_pos;
-
-  NodeTransitionWrapper ntw(TransformTransition::get_class_type());
-  wrt(this, trav->begin(), trav->end(),
-      camera, ntw, RenderRelation::get_class_type());
-  const TransformTransition *tt;
-  if (get_transition_into(tt, ntw)) {
-    LOD_pos = _lod._center * tt->get_matrix();
-  } else {
-    LOD_pos = _lod._center;
+  // First, we have to get the current viewing frustum.  This is
+  // normally the same thing as the current camera, but the
+  // DisplayRegion may have some override in effect, so we ask the
+  // DisplayRegion instead of the GSG.
+  const DisplayRegion *dr = gsg->get_current_display_region();
+  ProjectionNode *camera = dr->get_cull_frustum();
+  if (camera != (ProjectionNode *)NULL) {
+    LPoint3f camera_pos(0, 0, 0);
+
+    // Get the LOD center in camera space
+    LPoint3f LOD_pos;
+
+    NodeTransitionWrapper ntw(TransformTransition::get_class_type());
+    wrt(this, trav->begin(), trav->end(),
+        camera, ntw, RenderRelation::get_class_type());
+    const TransformTransition *tt;
+    if (get_transition_into(tt, ntw)) {
+      LOD_pos = _lod._center * tt->get_matrix();
+    } else {
+      LOD_pos = _lod._center;
+    }
+    
+    // Determine which child to traverse
+    int index = _lod.compute_child(camera_pos, LOD_pos);
+    select_child(index);
   }
-
-  // Determine which child to traverse
-  int index = _lod.compute_child(camera_pos, LOD_pos);
-  select_child(index);
 }
 
 ////////////////////////////////////////////////////////////////////