Browse Source

fixed a bug with multiple sibling portals in view at the same time

Asad M. Zaman 21 years ago
parent
commit
5a19e97534

+ 26 - 20
panda/src/pgraph/portalClipper.I

@@ -101,16 +101,26 @@ draw_camera_frustum() {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: PortalClipper::set_view_frustum
+//     Function: PortalClipper::set_reduced_frustum
 //       Access: Public
 //       Access: Public
-//  Description: set the current view frustum before traversing
+//  Description: Set the current view frustum that is being calculated
+//               by the portal clipper
 //           
 //           
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void PortalClipper::
 INLINE void PortalClipper::
-set_view_frustum(BoundingHexahedron *frustum) {
-  _view_frustum = frustum;
+set_reduced_frustum(BoundingHexahedron *frustum) {
+  _reduced_frustum = frustum;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: PortalClipper::get_reduced_frustum
+//       Access: Published
+//  Description: Return the reduced frustum
+////////////////////////////////////////////////////////////////////
+INLINE BoundingHexahedron *PortalClipper::
+get_reduced_frustum() const {
+  return _reduced_frustum;
+}
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PortalClipper::is_facing_view
 //     Function: PortalClipper::is_facing_view
 //       Access: Public
 //       Access: Public
@@ -118,9 +128,8 @@ set_view_frustum(BoundingHexahedron *frustum) {
 //               is facing the camera's near plane
 //               is facing the camera's near plane
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE bool PortalClipper::
 INLINE bool PortalClipper::
-is_facing_view(Planef portal_plane)
-{
-  Planef view_plane(_view_frustum->get_point(4), _view_frustum->get_point(5), _view_frustum->get_point(6));
+is_facing_view(Planef portal_plane) {
+  Planef view_plane(_reduced_frustum->get_point(4), _reduced_frustum->get_point(5), _reduced_frustum->get_point(6));
 
 
   // use the view_frustum's near plane to calculate direction
   // use the view_frustum's near plane to calculate direction
   pgraph_cat.spam() << portal_plane.get_normal() << "; " << -view_plane.get_normal() << endl;
   pgraph_cat.spam() << portal_plane.get_normal() << "; " << -view_plane.get_normal() << endl;
@@ -134,24 +143,21 @@ is_facing_view(Planef portal_plane)
 //       Access: Public
 //       Access: Public
 //  Description: checks if portal_node is within the view frustum.
 //  Description: checks if portal_node is within the view frustum.
 //               If so, then the portal is worth considering. This
 //               If so, then the portal is worth considering. This
-//               is a 1st level test to weed out most of the portals
+//               is a 2nd level test to weed out most of the portals
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE bool PortalClipper::
 INLINE bool PortalClipper::
-is_whole_portal_in_view(const NodePath &node_path) {
-
-  const BoundingVolume *bv = &_portal_node->get_bound();
-
+is_whole_portal_in_view(LMatrix4f cmat) {
   // I am about to xform this gbv, so lets make a copy
   // I am about to xform this gbv, so lets make a copy
+  const BoundingVolume *bv = &_portal_node->get_bound();
   BoundingVolume *cbv = bv->make_copy();
   BoundingVolume *cbv = bv->make_copy();
   GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, cbv);
   GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, cbv);
 
 
   // trasform it to camera space
   // trasform it to camera space
-  CPT(TransformState) ctransform = node_path.get_transform(_scene_setup->get_cull_center());
-  gbv->xform(ctransform->get_mat());
+  gbv->xform(cmat);
 
 
-  int result = _view_frustum->contains(gbv);
+  int result = _reduced_frustum->contains(gbv);
 
 
-  pgraph_cat.spam() << "1st level test if portal: " << *_view_frustum << " is in view " << result << endl;
+  pgraph_cat.spam() << "1st level test if portal: " << *_reduced_frustum << " is in view " << result << endl;
   return (result != 0);
   return (result != 0);
 }
 }
 
 
@@ -163,14 +169,14 @@ is_whole_portal_in_view(const NodePath &node_path) {
 //               test to make sure this portal is worth visiting
 //               test to make sure this portal is worth visiting
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE bool PortalClipper::
 INLINE bool PortalClipper::
-is_partial_portal_in_view(const NodePath &node_path) {
+is_partial_portal_in_view() {
   int result = 0;
   int result = 0;
-
+ 
   // check if any of the _coords in tested frustum
   // check if any of the _coords in tested frustum
   for (int j=0; j<_num_vert; ++j) {
   for (int j=0; j<_num_vert; ++j) {
-    result |= _view_frustum->contains(_coords[j]);
+    result |= _reduced_frustum->contains(_coords[j]);
   }
   }
-  pgraph_cat.spam() << "frustum: " << *_view_frustum << " contains(coord) result = " << result << endl;
+  pgraph_cat.spam() << "frustum: " << *_reduced_frustum << " contains(coord) result = " << result << endl;
 
 
   return (result != 0);
   return (result != 0);
 }
 }

+ 22 - 35
panda/src/pgraph/portalClipper.cxx

@@ -47,7 +47,7 @@ PortalClipper(GeometricBoundingVolume *frustum, SceneSetup *scene_setup) {
   _geom_point = new GeomPoint;
   _geom_point = new GeomPoint;
   _geom_linestrip = new GeomLinestrip;
   _geom_linestrip = new GeomLinestrip;
 
 
-  _view_frustum = DCAST(BoundingHexahedron, frustum);
+  _view_frustum = _reduced_frustum = DCAST(BoundingHexahedron, frustum);
 
 
   _scene_setup = scene_setup;
   _scene_setup = scene_setup;
 }
 }
@@ -306,7 +306,7 @@ prepare_portal(const NodePath &node_path)
   pgraph_cat.spam() << _coords[3] << endl;
   pgraph_cat.spam() << _coords[3] << endl;
 
 
   // check if portal is in view
   // check if portal is in view
-  if (is_whole_portal_in_view(node_path)) {
+  if (is_whole_portal_in_view(cmat)) {
     // ok, now lets add the original portal
     // ok, now lets add the original portal
     _color = Colorf(0,1,1,1);
     _color = Colorf(0,1,1,1);
     move_to(temp[0]);
     move_to(temp[0]);
@@ -339,23 +339,9 @@ prepare_portal(const NodePath &node_path)
 void PortalClipper::
 void PortalClipper::
 clip_portal(const NodePath &node_path)
 clip_portal(const NodePath &node_path)
 {
 {
-  int num_planes = _view_frustum->get_num_planes();
-
   if (!_num_vert)
   if (!_num_vert)
     return;
     return;
 
 
-  /*
-  pgraph_cat.debug() << "Number of planes " << num_planes << endl;
-
-  // print out the planes. plane 0 should be far and plane 5 should be near
-  // so we are only concerned with the 4 side planes.
-  for (int i=0; i<num_planes; ++i) {
-    Planef plane = _view_frustum->get_plane(i);
-    plane.output(pgraph_cat.debug());
-    pgraph_cat.debug() << endl;
-  }
-  */
-
   // ViewFrustum -> Logical Planes -> Portal Edge
   // ViewFrustum -> Logical Planes -> Portal Edge
   // Plane0      -> far plane      -> None
   // Plane0      -> far plane      -> None
   // plane5      -> near plane     -> None
   // plane5      -> near plane     -> None
@@ -374,7 +360,7 @@ clip_portal(const NodePath &node_path)
   LVector3f from_direction;
   LVector3f from_direction;
 
 
   // Look for intersection with the view frustum's bottom_plane and portal edges
   // Look for intersection with the view frustum's bottom_plane and portal edges
-  plane = _view_frustum->get_plane(1);
+  plane = _reduced_frustum->get_plane(1);
   for (j=0; j<_num_vert; ++j) {
   for (j=0; j<_num_vert; ++j) {
     from_origin = _coords[j];
     from_origin = _coords[j];
     from_direction = _coords[(j+1)%_num_vert] - _coords[j];
     from_direction = _coords[(j+1)%_num_vert] - _coords[j];
@@ -397,11 +383,11 @@ clip_portal(const NodePath &node_path)
         pgraph_cat.debug() << "ignored for now for simplicity \n";
         pgraph_cat.debug() << "ignored for now for simplicity \n";
     }
     }
     else
     else
-      pgraph_cat.debug() << "is_intersect: " << is_intersect << " at t = " << t << endl;
+      pgraph_cat.spam() << "is_intersect: " << is_intersect << " at t = " << t << endl;
   }
   }
 
 
   // Look for intersection with the view frustum's top_plane and portal edges
   // Look for intersection with the view frustum's top_plane and portal edges
-  plane = _view_frustum->get_plane(3);
+  plane = _reduced_frustum->get_plane(3);
   for (j=0; j<_num_vert; ++j) {
   for (j=0; j<_num_vert; ++j) {
     from_origin = _coords[j];
     from_origin = _coords[j];
     from_direction = _coords[(j+1)%_num_vert] - _coords[j];
     from_direction = _coords[(j+1)%_num_vert] - _coords[j];
@@ -424,11 +410,11 @@ clip_portal(const NodePath &node_path)
         pgraph_cat.debug() << "ignored for now for simplicity \n";
         pgraph_cat.debug() << "ignored for now for simplicity \n";
     }
     }
     else
     else
-      pgraph_cat.debug() << "is_intersect: " << is_intersect << " at t = " << t << endl;
+      pgraph_cat.spam() << "is_intersect: " << is_intersect << " at t = " << t << endl;
   }
   }
 
 
   // Look for intersection with the view frustum's right_plane and portal edges
   // Look for intersection with the view frustum's right_plane and portal edges
-  plane = _view_frustum->get_plane(2);
+  plane = _reduced_frustum->get_plane(2);
   for (j=0; j<_num_vert; ++j) {
   for (j=0; j<_num_vert; ++j) {
     from_origin = _coords[j];
     from_origin = _coords[j];
     from_direction = _coords[(j+1)%_num_vert] - _coords[j];
     from_direction = _coords[(j+1)%_num_vert] - _coords[j];
@@ -451,11 +437,11 @@ clip_portal(const NodePath &node_path)
         pgraph_cat.debug() << "ignored for now for simplicity \n";
         pgraph_cat.debug() << "ignored for now for simplicity \n";
     }
     }
     else
     else
-      pgraph_cat.debug() << "is_intersect: " << is_intersect << " at t = " << t << endl;
+      pgraph_cat.spam() << "is_intersect: " << is_intersect << " at t = " << t << endl;
   }
   }
 
 
   // Look for intersection with the view frustum's left_plane and portal edges
   // Look for intersection with the view frustum's left_plane and portal edges
-  plane = _view_frustum->get_plane(4);
+  plane = _reduced_frustum->get_plane(4);
   for (j=0; j<_num_vert; ++j) {
   for (j=0; j<_num_vert; ++j) {
     from_origin = _coords[j];
     from_origin = _coords[j];
     from_direction = _coords[(j+1)%_num_vert] - _coords[j];
     from_direction = _coords[(j+1)%_num_vert] - _coords[j];
@@ -478,7 +464,7 @@ clip_portal(const NodePath &node_path)
         pgraph_cat.debug() << "ignored for now for simplicity \n";
         pgraph_cat.debug() << "ignored for now for simplicity \n";
     }
     }
     else
     else
-      pgraph_cat.debug() << "is_intersect: " << is_intersect << " at t = " << t << endl;
+      pgraph_cat.spam() << "is_intersect: " << is_intersect << " at t = " << t << endl;
   }
   }
   // ok, now lets add the clipped portal
   // ok, now lets add the clipped portal
   _color = Colorf(1,0,0,1);
   _color = Colorf(1,0,0,1);
@@ -493,7 +479,7 @@ clip_portal(const NodePath &node_path)
   if (xect == 0xf) {  //if all four planes intersected the portal, it is visible
   if (xect == 0xf) {  //if all four planes intersected the portal, it is visible
     return;
     return;
   }
   }
-  if (!is_partial_portal_in_view(node_path)) {
+  if (!is_partial_portal_in_view()) {
     pgraph_cat.debug() << "portal failed 3rd level test \n";
     pgraph_cat.debug() << "portal failed 3rd level test \n";
     _num_vert = 0;
     _num_vert = 0;
   }
   }
@@ -522,10 +508,11 @@ get_reduced_frustum(const NodePath &node_path)
   
   
   float t;
   float t;
   bool visible = true;
   bool visible = true;
+
   // find intersection of 7->3 with far
   // find intersection of 7->3 with far
-  LPoint3f from_origin = _view_frustum->get_point(7);
+  LPoint3f from_origin = _reduced_frustum->get_point(7);
   LVector3f from_direction = _coords[3] - from_origin;
   LVector3f from_direction = _coords[3] - from_origin;
-  bool is_intersect = _view_frustum->get_plane(0).intersects_line(t, from_origin, from_direction);
+  bool is_intersect = _reduced_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.spam() << "far plane intersected 7->3 at t=" << t << endl;
     pgraph_cat.spam() << "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;
@@ -535,9 +522,9 @@ get_reduced_frustum(const NodePath &node_path)
     visible = false;
     visible = false;
 
 
   // find intersection of 4->0 with far
   // find intersection of 4->0 with far
-  from_origin = _view_frustum->get_point(4);
+  from_origin = _reduced_frustum->get_point(4);
   from_direction = _coords[0] - from_origin;
   from_direction = _coords[0] - from_origin;
-  is_intersect = _view_frustum->get_plane(0).intersects_line(t, from_origin, from_direction);
+  is_intersect = _reduced_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.spam() << "far plane intersected 4->0 at t=" << t << endl;
     pgraph_cat.spam() << "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;
@@ -547,9 +534,9 @@ get_reduced_frustum(const NodePath &node_path)
     visible = false;
     visible = false;
 
 
   // find intersection of 5->1 with far
   // find intersection of 5->1 with far
-  from_origin = _view_frustum->get_point(5);
+  from_origin = _reduced_frustum->get_point(5);
   from_direction = _coords[1] - from_origin;
   from_direction = _coords[1] - from_origin;
-  is_intersect = _view_frustum->get_plane(0).intersects_line(t, from_origin, from_direction);
+  is_intersect = _reduced_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.spam() << "far plane intersected 5->1 at t=" << t << endl;
     pgraph_cat.spam() << "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;
@@ -559,9 +546,9 @@ get_reduced_frustum(const NodePath &node_path)
     visible = false;
     visible = false;
 
 
   // find intersection of 6->2 with far
   // find intersection of 6->2 with far
-  from_origin = _view_frustum->get_point(6);
+  from_origin = _reduced_frustum->get_point(6);
   from_direction = _coords[2] - from_origin;
   from_direction = _coords[2] - from_origin;
-  is_intersect = _view_frustum->get_plane(0).intersects_line(t, from_origin, from_direction);
+  is_intersect = _reduced_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.spam() << "far plane intersected 6->2 at t=" << t << endl;
     pgraph_cat.spam() << "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;
@@ -579,8 +566,8 @@ get_reduced_frustum(const NodePath &node_path)
   PT(BoundingVolume) reduced_frustum = new
   PT(BoundingVolume) reduced_frustum = new
     BoundingHexahedron(intersect_points[1], intersect_points[2],
     BoundingHexahedron(intersect_points[1], intersect_points[2],
                        intersect_points[3], intersect_points[0],
                        intersect_points[3], intersect_points[0],
-                       _view_frustum->get_point(4), _view_frustum->get_point(5),
-                       _view_frustum->get_point(6), _view_frustum->get_point(7));
+                       _reduced_frustum->get_point(4), _reduced_frustum->get_point(5),
+                       _reduced_frustum->get_point(6), _reduced_frustum->get_point(7));
 
 
   pgraph_cat.debug() << *reduced_frustum << endl;
   pgraph_cat.debug() << *reduced_frustum << endl;
 
 

+ 5 - 3
panda/src/pgraph/portalClipper.h

@@ -63,9 +63,9 @@ public:
   PortalClipper(GeometricBoundingVolume *frustum, SceneSetup *scene_setup);
   PortalClipper(GeometricBoundingVolume *frustum, SceneSetup *scene_setup);
   ~PortalClipper();
   ~PortalClipper();
 
 
-  INLINE bool is_whole_portal_in_view(const NodePath &node_path);
-  INLINE bool is_partial_portal_in_view(const NodePath &node_path);
+  INLINE bool is_partial_portal_in_view();
   INLINE bool is_facing_view(Planef portal_plane);
   INLINE bool is_facing_view(Planef portal_plane);
+  INLINE bool is_whole_portal_in_view(LMatrix4f cmat);
 
 
   void prepare_portal(const NodePath &node_path);
   void prepare_portal(const NodePath &node_path);
   void clip_portal(const NodePath &node_path);
   void clip_portal(const NodePath &node_path);
@@ -83,7 +83,8 @@ public:
 
 
   INLINE float get_plane_depth(float x, float z, Planef *portal_plane);
   INLINE float get_plane_depth(float x, float z, Planef *portal_plane);
 
 
-  INLINE void  set_view_frustum(BoundingHexahedron *frustum);
+  INLINE BoundingHexahedron *get_reduced_frustum() const;
+  INLINE void set_reduced_frustum(BoundingHexahedron *bh);
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
@@ -129,6 +130,7 @@ private:
   PT(GeomLinestrip) _geom_linestrip;
   PT(GeomLinestrip) _geom_linestrip;
 
 
   BoundingHexahedron *_view_frustum;
   BoundingHexahedron *_view_frustum;
+  BoundingHexahedron *_reduced_frustum;
 
 
   PortalNode *_portal_node;  // current working portal for dereference ease
   PortalNode *_portal_node;  // current working portal for dereference ease
 
 

+ 15 - 4
panda/src/pgraph/portalNode.cxx

@@ -63,9 +63,9 @@ PortalNode(const PortalNode &copy) :
   _into_portal_mask(copy._into_portal_mask),
   _into_portal_mask(copy._into_portal_mask),
   _flags(copy._flags)
   _flags(copy._flags)
 {
 {
-  _zone_in = NULL;
-  _zone_out = NULL;
-  _visible = true;
+  _zone_in = copy._zone_in;
+  _zone_out = copy._zone_in;
+  _visible = copy._visible;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -192,7 +192,8 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
       pgraph_cat.debug() << "got reduced frustum " << reduced_frustum << endl;
       pgraph_cat.debug() << "got reduced frustum " << reduced_frustum << endl;
       vf = DCAST(GeometricBoundingVolume, reduced_frustum);
       vf = DCAST(GeometricBoundingVolume, reduced_frustum);
       
       
-      portal_viewer->set_view_frustum(DCAST(BoundingHexahedron,vf->make_copy()));
+      // keep a copy of this reduced frustum
+      BoundingHexahedron *new_bh = DCAST(BoundingHexahedron, vf->make_copy());
       
       
       // trasform it to cull_center space
       // trasform it to cull_center space
       CPT(TransformState) cull_center_transform = 
       CPT(TransformState) cull_center_transform = 
@@ -208,12 +209,22 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
                                   zone_transform,
                                   zone_transform,
                                   trav->get_initial_state(), vf, 
                                   trav->get_initial_state(), vf, 
                                   trav->get_guard_band());
                                   trav->get_guard_band());
+
       pgraph_cat.spam() << "cull_callback: traversing " << _zone_out.get_name() << endl;
       pgraph_cat.spam() << "cull_callback: traversing " << _zone_out.get_name() << endl;
+
       // Make this zone show with the reduced frustum
       // Make this zone show with the reduced frustum
       _zone_out.show();
       _zone_out.show();
+
+      // all nodes visible through this portal, should have this node's frustum
+      BoundingHexahedron *old_bh = portal_viewer->get_reduced_frustum();
+      portal_viewer->set_reduced_frustum(new_bh);
       trav->traverse(next_data);
       trav->traverse(next_data);
+
       // make sure traverser is not drawing this node again
       // make sure traverser is not drawing this node again
       _zone_out.hide();
       _zone_out.hide();
+
+      // reset portal viewer frustum for the siblings;
+      portal_viewer->set_reduced_frustum(old_bh);
     }
     }
   }
   }
   // Now carry on to render our child nodes.
   // Now carry on to render our child nodes.

+ 1 - 0
panda/src/pgraph/portalNode.h

@@ -77,6 +77,7 @@ PUBLISHED:
   INLINE void set_visible(bool value);
   INLINE void set_visible(bool value);
   INLINE bool is_visible();
   INLINE bool is_visible();
 
 
+
 protected:
 protected:
   virtual BoundingVolume *recompute_bound();
   virtual BoundingVolume *recompute_bound();
   virtual BoundingVolume *recompute_internal_bound();
   virtual BoundingVolume *recompute_internal_bound();