Browse Source

2nd pass portal clipping. This is integrated into scenegraph

Asad M. Zaman 21 years ago
parent
commit
d3d36911de

+ 21 - 0
panda/src/pgraph/cullTraverser.I

@@ -234,3 +234,24 @@ INLINE CullHandler *CullTraverser::
 get_cull_handler() const {
 get_cull_handler() const {
   return _cull_handler;
   return _cull_handler;
 }
 }
+////////////////////////////////////////////////////////////////////
+//     Function: CullTraverser::set_portal_clipper
+//       Access: Public
+//  Description: Specifies _portal_clipper object pointer that 
+//               subsequent traverse() or traverse_below may use.
+////////////////////////////////////////////////////////////////////
+INLINE void CullTraverser::
+set_portal_clipper(PortalClipper *portal_clipper) {
+  _portal_clipper = portal_clipper;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CullTraverser::get_portal_clipper
+//       Access: Public
+//  Description: Returns the _portal_clipper pointer
+////////////////////////////////////////////////////////////////////
+
+INLINE PortalClipper *CullTraverser::
+get_portal_clipper() const {
+  return _portal_clipper;
+}

+ 15 - 74
panda/src/pgraph/cullTraverser.cxx

@@ -48,6 +48,7 @@ CullTraverser() {
   _initial_state = RenderState::make_empty();
   _initial_state = RenderState::make_empty();
   _depth_offset_decals = false;
   _depth_offset_decals = false;
   _cull_handler = (CullHandler *)NULL;
   _cull_handler = (CullHandler *)NULL;
+  _portal_clipper = (PortalClipper *)NULL;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -63,7 +64,8 @@ CullTraverser(const CullTraverser &copy) :
   _depth_offset_decals(copy._depth_offset_decals),
   _depth_offset_decals(copy._depth_offset_decals),
   _view_frustum(copy._view_frustum),
   _view_frustum(copy._view_frustum),
   _guard_band(copy._guard_band),
   _guard_band(copy._guard_band),
-  _cull_handler(copy._cull_handler)
+  _cull_handler(copy._cull_handler),
+  _portal_clipper(copy._portal_clipper)
 {
 {
 }
 }
 
 
@@ -94,32 +96,16 @@ traverse(const NodePath &root, bool python_cull_control) {
     // This local_frustum is in camera space
     // This local_frustum is in camera space
     PortalClipper portal_viewer(local_frustum, _scene_setup);
     PortalClipper portal_viewer(local_frustum, _scene_setup);
     portal_viewer.draw_camera_frustum();
     portal_viewer.draw_camera_frustum();
-
-#if 0
-    PT(BoundingVolume) reduced_frustum;
-
-    // right now it is returning only one reduced frustum
-    portal_viewer.prepare_portal();
-    //portal_viewer.clip_portal(portal_idx);
-    if ((reduced_frustum = portal_viewer.get_reduced_frustum())) {
-      // This reduced frustum is in camera space
-      pgraph_cat.debug() << "got reduced frustum " << reduced_frustum << endl;
-      vf = DCAST(GeometricBoundingVolume, reduced_frustum);
-        
-      // trasform it to cull_center space
-      CPT(TransformState) cull_center_transform = 
-        _scene_setup->get_cull_center().get_transform(_scene_setup->get_scene_root());
-      vf->xform(cull_center_transform->get_mat());
-    }
-    pgraph_cat.debug() << "vf is " << *vf << "\n";
-#endif
     
     
+    // store this pointer in this
+    set_portal_clipper(&portal_viewer);
+
     CullTraverserData data(root, get_render_transform(),
     CullTraverserData data(root, get_render_transform(),
                            TransformState::make_identity(),
                            TransformState::make_identity(),
                            _initial_state, _view_frustum, 
                            _initial_state, _view_frustum, 
-                           vf, _guard_band);
+                           _guard_band);
     
     
-    traverse(data, &portal_viewer);
+    traverse(data);
     
     
     // finally add the lines to be drawn
     // finally add the lines to be drawn
     portal_viewer.draw_lines();
     portal_viewer.draw_lines();
@@ -131,14 +117,13 @@ traverse(const NodePath &root, bool python_cull_control) {
     CullTraverserData my_data(data, portal_viewer._previous);
     CullTraverserData my_data(data, portal_viewer._previous);
     my_data._render_transform = my_data._render_transform->compose(transform);
     my_data._render_transform = my_data._render_transform->compose(transform);
     traverse(my_data);
     traverse(my_data);
-    pgraph_cat.debug() << "finished portal culling\n";
-    pgraph_cat.debug() << "**********end*********\n";
+    pgraph_cat.debug() << "******finished portal culling*********\n";
 
 
   } else {
   } else {
     CullTraverserData data(root, get_render_transform(),
     CullTraverserData data(root, get_render_transform(),
                            TransformState::make_identity(),
                            TransformState::make_identity(),
                            _initial_state, _view_frustum, 
                            _initial_state, _view_frustum, 
-                           NULL, _guard_band);
+                           _guard_band);
     
     
     traverse(data);
     traverse(data);
   }
   }
@@ -152,7 +137,7 @@ traverse(const NodePath &root, bool python_cull_control) {
 //               has not yet been converted into the node's space.
 //               has not yet been converted into the node's space.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CullTraverser::
 void CullTraverser::
-traverse(CullTraverserData &data, PortalClipper *portal_viewer) {
+traverse(CullTraverserData &data) {
   // Most nodes will have no transform or state, and will not
   // Most nodes will have no transform or state, and will not
   // contain decals or require a special cull callback.  As an
   // contain decals or require a special cull callback.  As an
   // optimization, we should tag nodes with these properties as
   // optimization, we should tag nodes with these properties as
@@ -162,50 +147,6 @@ traverse(CullTraverserData &data, PortalClipper *portal_viewer) {
     PandaNode *node = data.node();
     PandaNode *node = data.node();
     pgraph_cat.spam() << "\n" << data._node_path << "\n";
     pgraph_cat.spam() << "\n" << data._node_path << "\n";
 
 
-#if 0
-    // let me see the names, curious
-    unsigned int loc = node->get_name().find("pTypeArchway");
-    if (loc != string::npos) {
-      node->output(pgraph_cat.spam());
-      pgraph_cat.spam() << endl;
-      if (data._reduced_frustum) {
-        pgraph_cat.debug() << "setting reduced frustum to this node\n";
-
-        if (data._view_frustum) {
-          pgraph_cat.spam() << *data._view_frustum << endl;
-        }
-        pgraph_cat.spam() << *data._reduced_frustum << endl;
-
-        data._view_frustum = data._reduced_frustum;
-        data._reduced_frustum = NULL;
-      }
-    }
-#else
-    if (node->is_of_type(PortalNode::get_class_type())) {
-      PortalNode *portal_node = DCAST(PortalNode, node);
-      if (portal_node->is_visible()) {
-        pgraph_cat.debug() << "portal node visible " << *portal_node << endl;
-        PT(GeometricBoundingVolume) vf = _view_frustum;
-        PT(BoundingVolume) reduced_frustum;
-        
-        // right now it is returning only one reduced frustum
-        portal_viewer->prepare_portal(data._node_path.get_node_path());
-        //portal_viewer->clip_portal(data._node_path.get_node_path());
-        if ((reduced_frustum = portal_viewer->get_reduced_frustum(data._node_path.get_node_path()))) {
-          // This reduced frustum is in camera space
-          pgraph_cat.debug() << "got reduced frustum " << reduced_frustum << endl;
-          vf = DCAST(GeometricBoundingVolume, reduced_frustum);
-          
-          // trasform it to cull_center space
-          CPT(TransformState) cull_center_transform = 
-            _scene_setup->get_cull_center().get_transform(_scene_setup->get_scene_root());
-          vf->xform(cull_center_transform->get_mat());
-        }
-        pgraph_cat.debug() << "vf is " << *vf << "\n";
-      }
-    }
-#endif
-  
     const RenderEffects *node_effects = node->get_effects();
     const RenderEffects *node_effects = node->get_effects();
     if (node_effects->has_show_bounds()) {
     if (node_effects->has_show_bounds()) {
       // If we should show the bounding volume for this node, make it
       // If we should show the bounding volume for this node, make it
@@ -231,7 +172,7 @@ traverse(CullTraverserData &data, PortalClipper *portal_viewer) {
       }
       }
     }
     }
 
 
-    traverse_below(data, portal_viewer);
+    traverse_below(data);
   }
   }
 }
 }
 
 
@@ -243,7 +184,7 @@ traverse(CullTraverserData &data, PortalClipper *portal_viewer) {
 //               node's space.
 //               node's space.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CullTraverser::
 void CullTraverser::
-traverse_below(CullTraverserData &data, PortalClipper *portal_viewer) {
+traverse_below(CullTraverserData &data) {
   _nodes_pcollector.add_level(1);
   _nodes_pcollector.add_level(1);
   PandaNode *node = data.node();
   PandaNode *node = data.node();
 
 
@@ -290,14 +231,14 @@ traverse_below(CullTraverserData &data, PortalClipper *portal_viewer) {
       int i = node->get_first_visible_child();
       int i = node->get_first_visible_child();
       while (i < num_children) {
       while (i < num_children) {
         CullTraverserData next_data(data, node->get_child(i));
         CullTraverserData next_data(data, node->get_child(i));
-        traverse(next_data, portal_viewer);
+        traverse(next_data);
         i = node->get_next_visible_child(i);
         i = node->get_next_visible_child(i);
       }
       }
       
       
     } else {
     } else {
       for (int i = 0; i < num_children; i++) {
       for (int i = 0; i < num_children; i++) {
         CullTraverserData next_data(data, node->get_child(i));
         CullTraverserData next_data(data, node->get_child(i));
-        traverse(next_data, portal_viewer);
+        traverse(next_data);
       }
       }
     }
     }
   }
   }

+ 6 - 2
panda/src/pgraph/cullTraverser.h

@@ -75,9 +75,12 @@ public:
   INLINE void set_cull_handler(CullHandler *cull_handler);
   INLINE void set_cull_handler(CullHandler *cull_handler);
   INLINE CullHandler *get_cull_handler() const;
   INLINE CullHandler *get_cull_handler() const;
 
 
+  INLINE void set_portal_clipper(PortalClipper *portal_clipper);
+  INLINE PortalClipper *get_portal_clipper() const;
+
   void traverse(const NodePath &root, bool python_cull_control=false);
   void traverse(const NodePath &root, bool python_cull_control=false);
-  void traverse(CullTraverserData &data, PortalClipper *portal_viewer=NULL);
-  void traverse_below(CullTraverserData &data, PortalClipper *portal_viewer=NULL);
+  void traverse(CullTraverserData &data);
+  void traverse_below(CullTraverserData &data);
 
 
 public:
 public:
   // Statistics
   // Statistics
@@ -101,6 +104,7 @@ private:
   PT(GeometricBoundingVolume) _view_frustum;
   PT(GeometricBoundingVolume) _view_frustum;
   PT(GeometricBoundingVolume) _guard_band;
   PT(GeometricBoundingVolume) _guard_band;
   CullHandler *_cull_handler;
   CullHandler *_cull_handler;
+  PortalClipper *_portal_clipper;
   
   
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {

+ 0 - 5
panda/src/pgraph/cullTraverserData.I

@@ -27,14 +27,12 @@ CullTraverserData(const NodePath &start,
                   const TransformState *net_transform,
                   const TransformState *net_transform,
                   const RenderState *state,
                   const RenderState *state,
                   GeometricBoundingVolume *view_frustum,
                   GeometricBoundingVolume *view_frustum,
-                  GeometricBoundingVolume *reduced_frustum,
                   GeometricBoundingVolume *guard_band) :
                   GeometricBoundingVolume *guard_band) :
   _node_path(start),
   _node_path(start),
   _render_transform(render_transform),
   _render_transform(render_transform),
   _net_transform(net_transform),
   _net_transform(net_transform),
   _state(state),
   _state(state),
   _view_frustum(view_frustum),
   _view_frustum(view_frustum),
-  _reduced_frustum(reduced_frustum),
   _guard_band(guard_band)
   _guard_band(guard_band)
 {
 {
 }
 }
@@ -51,7 +49,6 @@ CullTraverserData(const CullTraverserData &copy) :
   _net_transform(copy._net_transform),
   _net_transform(copy._net_transform),
   _state(copy._state),
   _state(copy._state),
   _view_frustum(copy._view_frustum),
   _view_frustum(copy._view_frustum),
-  _reduced_frustum(copy._reduced_frustum),
   _guard_band(copy._guard_band)
   _guard_band(copy._guard_band)
 {
 {
 }
 }
@@ -68,7 +65,6 @@ operator = (const CullTraverserData &copy) {
   _net_transform = copy._net_transform;
   _net_transform = copy._net_transform;
   _state = copy._state;
   _state = copy._state;
   _view_frustum = copy._view_frustum;
   _view_frustum = copy._view_frustum;
-  _reduced_frustum = copy._reduced_frustum;
   _guard_band = copy._guard_band;
   _guard_band = copy._guard_band;
 }
 }
 
 
@@ -85,7 +81,6 @@ CullTraverserData(const CullTraverserData &parent, PandaNode *child) :
   _net_transform(parent._net_transform),
   _net_transform(parent._net_transform),
   _state(parent._state),
   _state(parent._state),
   _view_frustum(parent._view_frustum),
   _view_frustum(parent._view_frustum),
-  _reduced_frustum(parent._reduced_frustum),
   _guard_band(parent._guard_band)
   _guard_band(parent._guard_band)
 {
 {
 }
 }

+ 0 - 7
panda/src/pgraph/cullTraverserData.cxx

@@ -62,7 +62,6 @@ apply_transform_and_state(CullTraverser *trav,
     _render_transform = _render_transform->compose(node_transform);
     _render_transform = _render_transform->compose(node_transform);
 
 
     if ((_view_frustum != (GeometricBoundingVolume *)NULL) ||
     if ((_view_frustum != (GeometricBoundingVolume *)NULL) ||
-        (_reduced_frustum != (GeometricBoundingVolume *)NULL) ||
         (_guard_band != (GeometricBoundingVolume *)NULL)) {
         (_guard_band != (GeometricBoundingVolume *)NULL)) {
       // We need to move the viewing frustums into the node's
       // We need to move the viewing frustums into the node's
       // coordinate space by applying the node's inverse transform.
       // coordinate space by applying the node's inverse transform.
@@ -71,7 +70,6 @@ apply_transform_and_state(CullTraverser *trav,
         // trying, we'll just give up on frustum culling from this
         // trying, we'll just give up on frustum culling from this
         // point down.
         // point down.
         _view_frustum = (GeometricBoundingVolume *)NULL;
         _view_frustum = (GeometricBoundingVolume *)NULL;
-        _reduced_frustum = (GeometricBoundingVolume *)NULL;
         _guard_band = (GeometricBoundingVolume *)NULL;
         _guard_band = (GeometricBoundingVolume *)NULL;
 
 
       } else {
       } else {
@@ -85,11 +83,6 @@ apply_transform_and_state(CullTraverser *trav,
           _view_frustum->xform(inv_transform->get_mat());
           _view_frustum->xform(inv_transform->get_mat());
         }
         }
 
 
-        if (_reduced_frustum != (GeometricBoundingVolume *)NULL) {
-          _reduced_frustum = DCAST(GeometricBoundingVolume, _reduced_frustum->make_copy());
-          _reduced_frustum->xform(inv_transform->get_mat());
-        }
-        
         if (_guard_band != (GeometricBoundingVolume *)NULL) {
         if (_guard_band != (GeometricBoundingVolume *)NULL) {
           _guard_band = DCAST(GeometricBoundingVolume, _guard_band->make_copy());
           _guard_band = DCAST(GeometricBoundingVolume, _guard_band->make_copy());
           _guard_band->xform(inv_transform->get_mat());
           _guard_band->xform(inv_transform->get_mat());

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

@@ -52,7 +52,6 @@ public:
                            const TransformState *net_transform,
                            const TransformState *net_transform,
                            const RenderState *state,
                            const RenderState *state,
                            GeometricBoundingVolume *view_frustum,
                            GeometricBoundingVolume *view_frustum,
-                           GeometricBoundingVolume *reduced_frustum,
                            GeometricBoundingVolume *guard_band);
                            GeometricBoundingVolume *guard_band);
   INLINE CullTraverserData(const CullTraverserData &copy);
   INLINE CullTraverserData(const CullTraverserData &copy);
   INLINE void operator = (const CullTraverserData &copy); 
   INLINE void operator = (const CullTraverserData &copy); 
@@ -74,7 +73,6 @@ public:
   CPT(TransformState) _net_transform;
   CPT(TransformState) _net_transform;
   CPT(RenderState) _state;
   CPT(RenderState) _state;
   PT(GeometricBoundingVolume) _view_frustum;
   PT(GeometricBoundingVolume) _view_frustum;
-  PT(GeometricBoundingVolume) _reduced_frustum;
   PT(GeometricBoundingVolume) _guard_band;
   PT(GeometricBoundingVolume) _guard_band;
 
 
 private:
 private:

+ 21 - 0
panda/src/pgraph/portalClipper.I

@@ -133,3 +133,24 @@ is_facing_camera()
   pgraph_cat.debug() << "Found direction of " << direction << endl;
   pgraph_cat.debug() << "Found direction of " << direction << endl;
   return (direction < _FACING_THRESHOLD);
   return (direction < _FACING_THRESHOLD);
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: PortalClipper::get_plane_depth
+//       Access: Public
+//  Description: Given the x and z, solve for y: from the plane
+////////////////////////////////////////////////////////////////////
+INLINE float PortalClipper::
+get_plane_depth(float x, float z, Planef *portal_plane) {
+  float y = 0.0;
+  // Plane equation: Ax + By + Cz + D = 0
+  // y = (Ax + Cz + D) / -B
+  pgraph_cat.debug() << *portal_plane << endl;
+  pgraph_cat.debug() << portal_plane->_v.v._0 << " " << portal_plane->_v.v._1 << " "
+                     << portal_plane->_v.v._2 << " " << portal_plane->_v.v._3 << endl;
+
+  if (portal_plane->_v.v._1 != 0.0) {
+    y = (((portal_plane->_v.v._0*x)+(portal_plane->_v.v._2*z)+portal_plane->_v.v._3)
+         / -(portal_plane->_v.v._1));
+  }
+  return y;    
+}

+ 75 - 47
panda/src/pgraph/portalClipper.cxx

@@ -112,19 +112,6 @@ draw_to(const LVecBase3f &v) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void PortalClipper::
 void PortalClipper::
 draw_hexahedron(BoundingHexahedron *frustum) {
 draw_hexahedron(BoundingHexahedron *frustum) {
-  /*
-  pgraph_cat.debug() << "frustum points " << frustum->get_num_points() << endl;
-
-  pgraph_cat.debug() << frustum->get_point(0) << endl;
-  pgraph_cat.debug() << frustum->get_point(1) << endl;
-  pgraph_cat.debug() << frustum->get_point(2) << endl;
-  pgraph_cat.debug() << frustum->get_point(3) << endl;
-  pgraph_cat.debug() << frustum->get_point(4) << endl;
-  pgraph_cat.debug() << frustum->get_point(5) << endl;
-  pgraph_cat.debug() << frustum->get_point(6) << endl;
-  pgraph_cat.debug() << frustum->get_point(7) << endl;
-  */
-
   // walk the view frustum as it should be drawn
   // walk the view frustum as it should be drawn
   move_to(frustum->get_point(0));
   move_to(frustum->get_point(0));
   draw_to(frustum->get_point(1));
   draw_to(frustum->get_point(1));
@@ -255,22 +242,78 @@ prepare_portal(const NodePath &node_path)
   //CPT(TransformState) ctransform = node_path.get_transform(_scene_setup->get_camera_path());
   //CPT(TransformState) ctransform = node_path.get_transform(_scene_setup->get_camera_path());
   LMatrix4f cmat = ctransform->get_mat();
   LMatrix4f cmat = ctransform->get_mat();
   pgraph_cat.debug() << cmat << endl;
   pgraph_cat.debug() << cmat << endl;
+ 
+  Vertexf temp[4];
+  temp[0] = portal_node->get_vertex(0);
+  temp[1] = portal_node->get_vertex(1);
+  temp[2] = portal_node->get_vertex(2);
+  temp[3] = portal_node->get_vertex(3);
+
+  pgraph_cat.debug() << "before transformation to camera space" << endl;
+  pgraph_cat.debug() << temp[0] << endl;
+  pgraph_cat.debug() << temp[1] << endl;
+  pgraph_cat.debug() << temp[2] << endl;
+  pgraph_cat.debug() << temp[3] << endl;
   
   
-  _coords[0] = portal_node->get_vertex(0)*cmat;
-  _coords[1] = portal_node->get_vertex(1)*cmat;
-  _coords[2] = portal_node->get_vertex(2)*cmat;
-  _coords[3] = portal_node->get_vertex(3)*cmat;
-  
+  temp[0] = temp[0]*cmat;
+  temp[1] = temp[1]*cmat;
+  temp[2] = temp[2]*cmat;
+  temp[3] = temp[3]*cmat;
+
   pgraph_cat.debug() << "after transformation to camera space" << endl;
   pgraph_cat.debug() << "after transformation to camera space" << endl;
+  pgraph_cat.debug() << temp[0] << endl;
+  pgraph_cat.debug() << temp[1] << endl;
+  pgraph_cat.debug() << temp[2] << endl;
+  pgraph_cat.debug() << temp[3] << endl;
+  
+  float min_x, max_x, min_z, max_z;
+
+  min_x = min(min(min(temp[0][0], temp[1][0]), temp[2][0]), temp[3][0]);
+  max_x = max(max(max(temp[0][0], temp[1][0]), temp[2][0]), temp[3][0]);
+  min_z = min(min(min(temp[0][2], temp[1][2]), temp[2][2]), temp[3][2]);
+  max_z = max(max(max(temp[0][2], temp[1][2]), temp[2][2]), temp[3][2]);
+
+  pgraph_cat.debug() << "min_x " << min_x << ";max_x " << max_x << ";min_z " << min_z << ";max_z " << max_z << endl;
+
+
+  Planef portal_plane(temp[0], temp[1], temp[2]);
+
+  float y;
+
+  y = get_plane_depth(min_x, min_z, &portal_plane);
+  pgraph_cat.debug() << "plane's depth is " << y << endl;
+  _coords[0].set(min_x, y, min_z);
+
+  y = get_plane_depth(max_x, min_z, &portal_plane);
+  pgraph_cat.debug() << "plane's depth is " << y << endl;
+  _coords[1].set(max_x, y, min_z);
+
+  y = get_plane_depth(max_x, max_z, &portal_plane);
+  pgraph_cat.debug() << "plane's depth is " << y << endl;
+  _coords[2].set(max_x, y, max_z);
+
+  y = get_plane_depth(min_x, max_z, &portal_plane);
+  pgraph_cat.debug() << "plane's depth is " << y << endl;
+  _coords[3].set(min_x, y, max_z);
+    
+  pgraph_cat.debug() << "after min max calculation" << endl;
   pgraph_cat.debug() << _coords[0] << endl;
   pgraph_cat.debug() << _coords[0] << endl;
   pgraph_cat.debug() << _coords[1] << endl;
   pgraph_cat.debug() << _coords[1] << endl;
   pgraph_cat.debug() << _coords[2] << endl;
   pgraph_cat.debug() << _coords[2] << endl;
   pgraph_cat.debug() << _coords[3] << endl;
   pgraph_cat.debug() << _coords[3] << endl;
-  
+
   // check if facing camera
   // check if facing camera
   if (is_facing_camera()) {
   if (is_facing_camera()) {
     
     
-    // ok, now lets add the near plane to this portal
+    // ok, now lets add the original portal
+    _color = Colorf(0,1,1,1);
+    move_to(temp[0]);
+    draw_to(temp[1]);
+    draw_to(temp[2]);
+    draw_to(temp[3]);
+    draw_to(temp[0]);
+
+    // ok, now lets add the min_max portal
     _color = Colorf(1,0,0,1);
     _color = Colorf(1,0,0,1);
     move_to(_coords[0]);
     move_to(_coords[0]);
     draw_to(_coords[1]);
     draw_to(_coords[1]);
@@ -336,20 +379,6 @@ get_reduced_frustum(const NodePath &node_path)
   int num_planes = 6;
   int num_planes = 6;
   LPoint3f intersect_points[4];
   LPoint3f intersect_points[4];
   
   
-#if 0
-  // calculate the new side planes
-  for (int i=0; i<_num_vert; ++i) {
-    // get the vectors, Vi+1 and Vi
-    LVector3f front(_coords[(i+1)%_num_vert]);
-    LVector3f back(_coords[i]);
-    // get the cross product of these two vectors
-    LVector3f normal = front.cross(back);
-    normal.normalize();
-    frustum_planes[i+1] = Planef(normal, LPoint3f(0,0,0));
-    frustum_planes[i+1].output(pgraph_cat.debug());
-    pgraph_cat.debug() << endl;
-  }
-#else
   // another approach to actually finding the points, so that 
   // another approach to actually finding the points, so that 
   // I can reuse the current BoundingHexahedron object. Apparently,
   // I can reuse the current BoundingHexahedron object. Apparently,
   // it is better to construct this BH with bounding points, rather
   // it is better to construct this BH with bounding points, rather
@@ -360,48 +389,48 @@ get_reduced_frustum(const NodePath &node_path)
   
   
   float t;
   float t;
   bool visible = true;
   bool visible = true;
-  // find intersection of 7->0 with far
+  // find intersection of 7->3 with far
   LPoint3f from_origin = _hex_frustum->get_point(7);
   LPoint3f from_origin = _hex_frustum->get_point(7);
-  LVector3f from_direction = _coords[0] - from_origin;
+  LVector3f from_direction = _coords[3] - from_origin;
   bool is_intersect = _hex_frustum->get_plane(0).intersects_line(t, from_origin, from_direction);
   bool is_intersect = _hex_frustum->get_plane(0).intersects_line(t, from_origin, from_direction);
   if (is_intersect && t >= 0.0) { // has to be positive, else camera is not looking at the portal
   if (is_intersect && t >= 0.0) { // has to be positive, else camera is not looking at the portal
-    pgraph_cat.debug() << "far plane intersected 7->0 at t=" << t << endl;
+    pgraph_cat.debug() << "far plane intersected 7->3 at t=" << t << endl;
     intersect_points[0] = from_origin + t*from_direction;
     intersect_points[0] = from_origin + t*from_direction;
     pgraph_cat.debug() << intersect_points[0] << endl;
     pgraph_cat.debug() << intersect_points[0] << endl;
   }
   }
   else
   else
     visible = false;
     visible = false;
 
 
-  // find intersection of 4->1 with far
+  // find intersection of 4->0 with far
   from_origin = _hex_frustum->get_point(4);
   from_origin = _hex_frustum->get_point(4);
-  from_direction = _coords[1] - from_origin;
+  from_direction = _coords[0] - from_origin;
   is_intersect = _hex_frustum->get_plane(0).intersects_line(t, from_origin, from_direction);
   is_intersect = _hex_frustum->get_plane(0).intersects_line(t, from_origin, from_direction);
   if (is_intersect && t >= 0.0) { // has to be positive, else camera is not looking at the portal
   if (is_intersect && t >= 0.0) { // has to be positive, else camera is not looking at the portal
-    pgraph_cat.debug() << "far plane intersected 4->1 at t=" << t << endl;
+    pgraph_cat.debug() << "far plane intersected 4->0 at t=" << t << endl;
     intersect_points[1] = from_origin + t*from_direction;
     intersect_points[1] = from_origin + t*from_direction;
     pgraph_cat.debug() << intersect_points[1] << endl;
     pgraph_cat.debug() << intersect_points[1] << endl;
   }
   }
   else
   else
     visible = false;
     visible = false;
 
 
-  // find intersection of 5->2 with far
+  // find intersection of 5->1 with far
   from_origin = _hex_frustum->get_point(5);
   from_origin = _hex_frustum->get_point(5);
-  from_direction = _coords[2] - from_origin;
+  from_direction = _coords[1] - from_origin;
   is_intersect = _hex_frustum->get_plane(0).intersects_line(t, from_origin, from_direction);
   is_intersect = _hex_frustum->get_plane(0).intersects_line(t, from_origin, from_direction);
   if (is_intersect && t >= 0.0) { // has to be positive, else camera is not looking at the portal
   if (is_intersect && t >= 0.0) { // has to be positive, else camera is not looking at the portal
-    pgraph_cat.debug() << "far plane intersected 5->2 at t=" << t << endl;
+    pgraph_cat.debug() << "far plane intersected 5->1 at t=" << t << endl;
     intersect_points[2] = from_origin + t*from_direction;
     intersect_points[2] = from_origin + t*from_direction;
     pgraph_cat.debug() << intersect_points[2] << endl;
     pgraph_cat.debug() << intersect_points[2] << endl;
   }
   }
   else
   else
     visible = false;
     visible = false;
 
 
-  // find intersection of 6->3 with far
+  // find intersection of 6->2 with far
   from_origin = _hex_frustum->get_point(6);
   from_origin = _hex_frustum->get_point(6);
-  from_direction = _coords[3] - from_origin;
+  from_direction = _coords[2] - from_origin;
   is_intersect = _hex_frustum->get_plane(0).intersects_line(t, from_origin, from_direction);
   is_intersect = _hex_frustum->get_plane(0).intersects_line(t, from_origin, from_direction);
   if (is_intersect && t >= 0.0) { // has to be positive, else camera is not looking at the portal
   if (is_intersect && t >= 0.0) { // has to be positive, else camera is not looking at the portal
-    pgraph_cat.debug() << "far plane intersected 6->3 at t=" << t << endl;
+    pgraph_cat.debug() << "far plane intersected 6->2 at t=" << t << endl;
     intersect_points[3] = from_origin + t*from_direction;
     intersect_points[3] = from_origin + t*from_direction;
     pgraph_cat.debug() << intersect_points[3] << endl;
     pgraph_cat.debug() << intersect_points[3] << endl;
   }
   }
@@ -426,6 +455,5 @@ get_reduced_frustum(const NodePath &node_path)
   _color = Colorf(0,0,1,1);
   _color = Colorf(0,0,1,1);
   draw_hexahedron(DCAST(BoundingHexahedron, reduced_frustum));
   draw_hexahedron(DCAST(BoundingHexahedron, reduced_frustum));
 
 
-#endif
   return reduced_frustum;
   return reduced_frustum;
 }
 }

+ 2 - 1
panda/src/pgraph/portalClipper.h

@@ -78,6 +78,7 @@ public:
   INLINE void draw_to(float x, float y, float z);
   INLINE void draw_to(float x, float y, float z);
   void draw_to(const LVecBase3f &v);
   void draw_to(const LVecBase3f &v);
 
 
+  INLINE float get_plane_depth(float x, float z, Planef *portal_plane);
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
@@ -123,13 +124,13 @@ private:
   PT(GeomLinestrip) _geom_linestrip;
   PT(GeomLinestrip) _geom_linestrip;
 
 
   BoundingHexahedron *_hex_frustum;
   BoundingHexahedron *_hex_frustum;
-  SceneSetup *_scene_setup;
 
 
   int _num_vert;
   int _num_vert;
   Vertexf _coords[4];
   Vertexf _coords[4];
 
 
 public:
 public:
   PT(GeomNode) _previous;
   PT(GeomNode) _previous;
+  SceneSetup *_scene_setup;
 };
 };
 
 
 #include "portalClipper.I"
 #include "portalClipper.I"

+ 4 - 4
panda/src/pgraph/portalNode.I

@@ -173,7 +173,7 @@ get_vertex(int n) const {
 //       Access: Published
 //       Access: Published
 //  Description: Sets the zone that this portal belongs to
 //  Description: Sets the zone that this portal belongs to
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE void PortalNode::set_zone_in(PandaNode *zone) {
+INLINE void PortalNode::set_zone_in(const NodePath &zone) {
   _zone_in = zone;
   _zone_in = zone;
 }
 }
 
 
@@ -182,7 +182,7 @@ INLINE void PortalNode::set_zone_in(PandaNode *zone) {
 //       Access: Published
 //       Access: Published
 //  Description: Sets the zone that this portal belongs to
 //  Description: Sets the zone that this portal belongs to
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE PandaNode *PortalNode::get_zone_in() const {
+INLINE NodePath PortalNode::get_zone_in() const {
   return _zone_in;
   return _zone_in;
 }
 }
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -190,7 +190,7 @@ INLINE PandaNode *PortalNode::get_zone_in() const {
 //       Access: Published
 //       Access: Published
 //  Description: Sets the zone that this portal leads out to
 //  Description: Sets the zone that this portal leads out to
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE void PortalNode::set_zone_out(PandaNode *zone) {
+INLINE void PortalNode::set_zone_out(const NodePath &zone) {
   _zone_out = zone;
   _zone_out = zone;
 }
 }
 
 
@@ -199,7 +199,7 @@ INLINE void PortalNode::set_zone_out(PandaNode *zone) {
 //       Access: Published
 //       Access: Published
 //  Description: Sets the zone that this portal leads out to
 //  Description: Sets the zone that this portal leads out to
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE PandaNode *PortalNode::get_zone_out() const {
+INLINE NodePath PortalNode::get_zone_out() const {
   return _zone_out;
   return _zone_out;
 }
 }
 
 

+ 39 - 11
panda/src/pgraph/portalNode.cxx

@@ -22,6 +22,7 @@
 #include "cullTraverserData.h"
 #include "cullTraverserData.h"
 #include "cullTraverser.h"
 #include "cullTraverser.h"
 #include "renderState.h"
 #include "renderState.h"
+#include "portalClipper.h"
 #include "transformState.h"
 #include "transformState.h"
 #include "colorScaleAttrib.h"
 #include "colorScaleAttrib.h"
 #include "transparencyAttrib.h"
 #include "transparencyAttrib.h"
@@ -158,7 +159,7 @@ combine_with(PandaNode *other) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool PortalNode::
 bool PortalNode::
 has_cull_callback() const {
 has_cull_callback() const {
-  return false;
+  return true;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -176,16 +177,43 @@ has_cull_callback() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool PortalNode::
 bool PortalNode::
 cull_callback(CullTraverser *trav, CullTraverserData &data) {
 cull_callback(CullTraverser *trav, CullTraverserData &data) {
-  
-  // Calculate the reduced frustum for this portal
-
-  CullTraverserData next_data(data, _zone_out);
-
-  // We don't want to inherit the render state from above for these
-  // guys.
-  next_data._state = RenderState::make_empty();
-  trav->traverse(next_data);
-
+  PortalClipper *portal_viewer = trav->get_portal_clipper();
+  if (!_zone_out.is_empty() && portal_viewer) {
+    //CullTraverserData next_data(data, _zone_out);
+    if (is_visible()) {
+      pgraph_cat.debug() << "portal node visible " << *this << endl;
+      PT(GeometricBoundingVolume) vf = trav->get_view_frustum();
+      PT(BoundingVolume) reduced_frustum;
+      
+      portal_viewer->prepare_portal(data._node_path.get_node_path());
+      //portal_viewer->clip_portal(data._node_path.get_node_path());
+      if ((reduced_frustum = portal_viewer->get_reduced_frustum(data._node_path.get_node_path()))) {
+        // This reduced frustum is in camera space
+        pgraph_cat.debug() << "got reduced frustum " << reduced_frustum << endl;
+        vf = DCAST(GeometricBoundingVolume, reduced_frustum);
+        
+        // trasform it to cull_center space
+        CPT(TransformState) cull_center_transform = 
+          portal_viewer->_scene_setup->get_cull_center().get_transform(_zone_out);
+        vf->xform(cull_center_transform->get_mat());
+      }
+      pgraph_cat.debug() << "vf is " << *vf << "\n";
+
+      // Get the net trasform of the _zone_out
+      CPT(TransformState) zone_transform = _zone_out.get_net_transform();
+
+      CullTraverserData next_data(_zone_out, trav->get_render_transform()->compose(zone_transform),
+                                  zone_transform,
+                                  trav->get_initial_state(), vf, 
+                                  trav->get_guard_band());
+      pgraph_cat.debug() << "cull_callback: traversing " << _zone_out.get_name() << endl;
+      // Make this zone show with the reduced frustum
+      _zone_out.show();
+      trav->traverse(next_data);
+      // make sure traverser is not drawing this node again
+      _zone_out.hide();
+    }
+  }
   // Now carry on to render our child nodes.
   // Now carry on to render our child nodes.
   return true;
   return true;
 }
 }

+ 6 - 6
panda/src/pgraph/portalNode.h

@@ -68,11 +68,11 @@ PUBLISHED:
   INLINE int get_num_vertices() const;
   INLINE int get_num_vertices() const;
   INLINE const LPoint3f &get_vertex(int n) const;
   INLINE const LPoint3f &get_vertex(int n) const;
 
 
-  INLINE void set_zone_in(PandaNode *zone);
-  INLINE PandaNode *get_zone_in() const;
+  INLINE void set_zone_in(const NodePath &zone);
+  INLINE NodePath get_zone_in() const;
 
 
-  INLINE void set_zone_out(PandaNode *zone);
-  INLINE PandaNode *get_zone_out() const;
+  INLINE void set_zone_out(const NodePath &zone);
+  INLINE NodePath get_zone_out() const;
 
 
   INLINE void set_visible(bool value);
   INLINE void set_visible(bool value);
   INLINE bool is_visible();
   INLINE bool is_visible();
@@ -99,8 +99,8 @@ private:
   typedef pvector<LPoint3f> Vertices;
   typedef pvector<LPoint3f> Vertices;
   Vertices _vertices;
   Vertices _vertices;
 
 
-  PT(PandaNode) _zone_in;  // This is the zone it resides in
-  PT(PandaNode) _zone_out;  // This is the zone it leads out to
+  NodePath _zone_in;  // This is the zone it resides in
+  NodePath _zone_out;  // This is the zone it leads out to
 
 
   bool _visible;
   bool _visible;
 
 

+ 26 - 26
panda/src/pgraph/sceneGraphReducer.cxx

@@ -91,22 +91,22 @@ flatten(PandaNode *root, bool combine_siblings) {
 void SceneGraphReducer::
 void SceneGraphReducer::
 r_apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs,
 r_apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs,
                 int attrib_types, GeomTransformer &transformer) {
                 int attrib_types, GeomTransformer &transformer) {
-  if (pgraph_cat.is_debug()) {
-    pgraph_cat.debug()
+  if (pgraph_cat.is_spam()) {
+    pgraph_cat.spam()
       << "r_apply_attribs(" << *node << "), node's attribs are:\n";
       << "r_apply_attribs(" << *node << "), node's attribs are:\n";
-    node->get_transform()->write(pgraph_cat.debug(false), 2);
-    node->get_state()->write(pgraph_cat.debug(false), 2);
-    node->get_effects()->write(pgraph_cat.debug(false), 2);
+    node->get_transform()->write(pgraph_cat.spam(false), 2);
+    node->get_state()->write(pgraph_cat.spam(false), 2);
+    node->get_effects()->write(pgraph_cat.spam(false), 2);
   }
   }
 
 
   AccumulatedAttribs next_attribs(attribs);
   AccumulatedAttribs next_attribs(attribs);
   next_attribs.collect(node, attrib_types);
   next_attribs.collect(node, attrib_types);
 
 
-  if (pgraph_cat.is_debug()) {
-    pgraph_cat.debug()
+  if (pgraph_cat.is_spam()) {
+    pgraph_cat.spam()
       << "Got attribs from " << *node << "\n"
       << "Got attribs from " << *node << "\n"
       << "Accumulated attribs are:\n";
       << "Accumulated attribs are:\n";
-    next_attribs.write(pgraph_cat.debug(false), attrib_types, 2);
+    next_attribs.write(pgraph_cat.spam(false), attrib_types, 2);
   }
   }
 
 
   // Check to see if we can't propagate any of these attribs past
   // Check to see if we can't propagate any of these attribs past
@@ -115,16 +115,16 @@ r_apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs,
 
 
   const RenderEffects *effects = node->get_effects();
   const RenderEffects *effects = node->get_effects();
   if (!effects->safe_to_transform()) {
   if (!effects->safe_to_transform()) {
-    if (pgraph_cat.is_debug()) {
-      pgraph_cat.debug()
+    if (pgraph_cat.is_spam()) {
+      pgraph_cat.spam()
         << "Node " << *node
         << "Node " << *node
         << " contains a non-transformable effect; leaving transform here.\n";
         << " contains a non-transformable effect; leaving transform here.\n";
     }
     }
     apply_types |= TT_transform;
     apply_types |= TT_transform;
   }
   }
   if (!node->safe_to_transform()) {
   if (!node->safe_to_transform()) {
-    if (pgraph_cat.is_debug()) {
-      pgraph_cat.debug()
+    if (pgraph_cat.is_spam()) {
+      pgraph_cat.spam()
         << "Cannot safely transform nodes of type " << node->get_type()
         << "Cannot safely transform nodes of type " << node->get_type()
         << "; leaving a transform here but carrying on otherwise.\n";
         << "; leaving a transform here but carrying on otherwise.\n";
     }
     }
@@ -145,8 +145,8 @@ r_apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs,
     }
     }
 
 
     if (!children_transform_friendly) {
     if (!children_transform_friendly) {
-      if (pgraph_cat.is_debug()) {
-        pgraph_cat.debug()
+      if (pgraph_cat.is_spam()) {
+        pgraph_cat.spam()
           << "Node " << *node
           << "Node " << *node
           << " has a child that cannot modify its transform; leaving transform here.\n";
           << " has a child that cannot modify its transform; leaving transform here.\n";
       }
       }
@@ -167,8 +167,8 @@ r_apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs,
 
 
     if (child_node->get_num_parents() > 1) {
     if (child_node->get_num_parents() > 1) {
       if (!child_node->safe_to_flatten()) {
       if (!child_node->safe_to_flatten()) {
-        if (pgraph_cat.is_debug()) {
-          pgraph_cat.debug()
+        if (pgraph_cat.is_spam()) {
+          pgraph_cat.spam()
             << "Cannot duplicate nodes of type " << child_node->get_type()
             << "Cannot duplicate nodes of type " << child_node->get_type()
             << ".\n";
             << ".\n";
           resist_copy = true;
           resist_copy = true;
@@ -183,8 +183,8 @@ r_apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs,
           resist_copy = true;
           resist_copy = true;
 
 
         } else {
         } else {
-          if (pgraph_cat.is_debug()) {
-            pgraph_cat.debug()
+          if (pgraph_cat.is_spam()) {
+            pgraph_cat.spam()
               << "Duplicated " << *child_node << "\n";
               << "Duplicated " << *child_node << "\n";
           }
           }
           
           
@@ -421,15 +421,15 @@ consider_siblings(PandaNode *parent_node, PandaNode *child1,
 bool SceneGraphReducer::
 bool SceneGraphReducer::
 do_flatten_child(PandaNode *grandparent_node, PandaNode *parent_node, 
 do_flatten_child(PandaNode *grandparent_node, PandaNode *parent_node, 
                  PandaNode *child_node) {
                  PandaNode *child_node) {
-  if (pgraph_cat.is_debug()) {
-    pgraph_cat.debug()
+  if (pgraph_cat.is_spam()) {
+    pgraph_cat.spam()
       << "Collapsing " << *parent_node << " and " << *child_node << "\n";
       << "Collapsing " << *parent_node << " and " << *child_node << "\n";
   }
   }
 
 
   PT(PandaNode) new_parent = collapse_nodes(parent_node, child_node, false);
   PT(PandaNode) new_parent = collapse_nodes(parent_node, child_node, false);
   if (new_parent == (PandaNode *)NULL) {
   if (new_parent == (PandaNode *)NULL) {
-    if (pgraph_cat.is_debug()) {
-      pgraph_cat.debug()
+    if (pgraph_cat.is_spam()) {
+      pgraph_cat.spam()
         << "Decided not to collapse " << *parent_node 
         << "Decided not to collapse " << *parent_node 
         << " and " << *child_node << "\n";
         << " and " << *child_node << "\n";
     }
     }
@@ -466,15 +466,15 @@ do_flatten_child(PandaNode *grandparent_node, PandaNode *parent_node,
 PandaNode *SceneGraphReducer::
 PandaNode *SceneGraphReducer::
 do_flatten_siblings(PandaNode *parent_node, PandaNode *child1,
 do_flatten_siblings(PandaNode *parent_node, PandaNode *child1,
                     PandaNode *child2) {
                     PandaNode *child2) {
-  if (pgraph_cat.is_debug()) {
-    pgraph_cat.debug()
+  if (pgraph_cat.is_spam()) {
+    pgraph_cat.spam()
       << "Collapsing " << *child1 << " and " << *child2 << "\n";
       << "Collapsing " << *child1 << " and " << *child2 << "\n";
   }
   }
 
 
   PT(PandaNode) new_child = collapse_nodes(child2, child1, true);
   PT(PandaNode) new_child = collapse_nodes(child2, child1, true);
   if (new_child == (PandaNode *)NULL) {
   if (new_child == (PandaNode *)NULL) {
-    if (pgraph_cat.is_debug()) {
-      pgraph_cat.debug()
+    if (pgraph_cat.is_spam()) {
+      pgraph_cat.spam()
         << "Decided not to collapse " << *child1 << " and " << *child2 << "\n";
         << "Decided not to collapse " << *child1 << " and " << *child2 << "\n";
     }
     }
     return NULL;
     return NULL;