Browse Source

add PlaneNode::set_clip_effect

David Rose 18 years ago
parent
commit
7e08d7b759

+ 54 - 34
panda/src/collide/collisionPolygon.cxx

@@ -613,12 +613,19 @@ test_intersection_from_line(const CollisionEntry &entry) const {
   if (cpa != (ClipPlaneAttrib *)NULL) {
     // We have a clip plane; apply it.
     Points new_points;
-    apply_clip_plane(new_points, cpa, entry.get_into_node_path().get_net_transform());
-    if (new_points.size() < 3) {
-      return NULL;
-    }
-    if (!point_is_inside(p, new_points)) {
-      return NULL;
+    if (apply_clip_plane(new_points, cpa, entry.get_into_node_path().get_net_transform())) {
+      // All points are behind the clip plane.
+      if (!point_is_inside(p, _points)) {
+        return NULL;
+      }
+
+    } else {
+      if (new_points.size() < 3) {
+        return NULL;
+      }
+      if (!point_is_inside(p, new_points)) {
+        return NULL;
+      }
     }
 
   } else {
@@ -682,12 +689,19 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
   if (cpa != (ClipPlaneAttrib *)NULL) {
     // We have a clip plane; apply it.
     Points new_points;
-    apply_clip_plane(new_points, cpa, entry.get_into_node_path().get_net_transform());
-    if (new_points.size() < 3) {
-      return NULL;
-    }
-    if (!point_is_inside(p, new_points)) {
-      return NULL;
+    if (apply_clip_plane(new_points, cpa, entry.get_into_node_path().get_net_transform())) {
+      // All points are behind the clip plane.
+      if (!point_is_inside(p, _points)) {
+        return NULL;
+      }
+
+    } else {
+      if (new_points.size() < 3) {
+        return NULL;
+      }
+      if (!point_is_inside(p, new_points)) {
+        return NULL;
+      }
     }
 
   } else {
@@ -753,12 +767,19 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
   if (cpa != (ClipPlaneAttrib *)NULL) {
     // We have a clip plane; apply it.
     Points new_points;
-    apply_clip_plane(new_points, cpa, entry.get_into_node_path().get_net_transform());
-    if (new_points.size() < 3) {
-      return NULL;
-    }
-    if (!point_is_inside(p, new_points)) {
-      return NULL;
+    if (apply_clip_plane(new_points, cpa, entry.get_into_node_path().get_net_transform())) {
+      // All points are behind the clip plane.
+      if (!point_is_inside(p, _points)) {
+        return NULL;
+      }
+
+    } else {
+      if (new_points.size() < 3) {
+        return NULL;
+      }
+      if (!point_is_inside(p, new_points)) {
+        return NULL;
+      }
     }
 
   } else {
@@ -1165,28 +1186,27 @@ apply_clip_plane(CollisionPolygon::Points &new_points,
   bool all_in = true;
 
   int num_planes = cpa->get_num_on_planes();
-  if (num_planes > 0) {
+  bool first_plane = true;
+
+  for (int i = 0; i < num_planes; i++) {
     NodePath plane_path = cpa->get_on_plane(0);
     PlaneNode *plane_node = DCAST(PlaneNode, plane_path.node());
-    CPT(TransformState) new_transform = 
-      net_transform->invert_compose(plane_path.get_net_transform());
-    
-    Planef plane = plane_node->get_plane() * new_transform->get_mat();
-    if (!clip_polygon(new_points, _points, plane)) {
-      all_in = false;
-    }
-
-    for (int i = 1; i < num_planes; i++) {
-      NodePath plane_path = cpa->get_on_plane(0);
-      PlaneNode *plane_node = DCAST(PlaneNode, plane_path.node());
+    if ((plane_node->get_clip_effect() & PlaneNode::CE_collision) != 0) {
       CPT(TransformState) new_transform = 
         net_transform->invert_compose(plane_path.get_net_transform());
       
       Planef plane = plane_node->get_plane() * new_transform->get_mat();
-      Points last_points;
-      last_points.swap(new_points);
-      if (!clip_polygon(new_points, last_points, plane)) {
-        all_in = false;
+      if (first_plane) {
+        first_plane = false;
+        if (!clip_polygon(new_points, _points, plane)) {
+          all_in = false;
+        }
+      } else {
+        Points last_points;
+        last_points.swap(new_points);
+        if (!clip_polygon(new_points, last_points, plane)) {
+          all_in = false;
+        }
       }
     }
   }

+ 65 - 63
panda/src/display/graphicsStateGuardian.cxx

@@ -1431,78 +1431,80 @@ do_issue_clip_plane() {
   for (int li = 0; li < num_on_planes; li++) {
     NodePath plane = new_attrib->get_on_plane(li);
     nassertv(!plane.is_empty() && plane.node()->is_of_type(PlaneNode::get_class_type()));
+    PlaneNode *plane_node = (PlaneNode *)plane.node();
+    if ((plane_node->get_clip_effect() & PlaneNode::CE_visible) != 0) {
+      num_enabled++;
 
-    num_enabled++;
-
-    // Clipping should be enabled before we apply any planes.
-    enable_clip_planes(true);
-    _clip_planes_enabled = true;
-    _clip_planes_enabled_this_frame = true;
-
-    // Check to see if this plane has already been bound to an id
-    int cur_plane_id = -1;
-    for (i = 0; i < cur_max_planes; i++) {
-      if (_clip_plane_info[i]._plane == plane) {
-        // Plane has already been bound to an id, we only need to
-        // enable the plane, not reapply it.
-        cur_plane_id = -2;
-        enable_clip_plane(i, true);
-        _clip_plane_info[i]._enabled = true;
-        _clip_plane_info[i]._next_enabled = true;
-        break;
-      }
-    }
-
-    // See if there are any unbound plane ids
-    if (cur_plane_id == -1) {
+      // Clipping should be enabled before we apply any planes.
+      enable_clip_planes(true);
+      _clip_planes_enabled = true;
+      _clip_planes_enabled_this_frame = true;
+      
+      // Check to see if this plane has already been bound to an id
+      int cur_plane_id = -1;
       for (i = 0; i < cur_max_planes; i++) {
-        if (_clip_plane_info[i]._plane.is_empty()) {
-          _clip_plane_info[i]._plane = plane;
-          cur_plane_id = i;
+        if (_clip_plane_info[i]._plane == plane) {
+          // Plane has already been bound to an id, we only need to
+          // enable the plane, not reapply it.
+          cur_plane_id = -2;
+          enable_clip_plane(i, true);
+          _clip_plane_info[i]._enabled = true;
+          _clip_plane_info[i]._next_enabled = true;
           break;
         }
       }
-    }
-
-    // If there were no unbound plane ids, see if we can replace
-    // a currently unused but previously bound id
-    if (cur_plane_id == -1) {
-      for (i = 0; i < cur_max_planes; i++) {
-        if (!new_attrib->has_on_plane(_clip_plane_info[i]._plane)) {
-          _clip_plane_info[i]._plane = plane;
-          cur_plane_id = i;
-          break;
+      
+      // See if there are any unbound plane ids
+      if (cur_plane_id == -1) {
+        for (i = 0; i < cur_max_planes; i++) {
+          if (_clip_plane_info[i]._plane.is_empty()) {
+            _clip_plane_info[i]._plane = plane;
+            cur_plane_id = i;
+            break;
+          }
         }
       }
-    }
-
-    // If we *still* don't have a plane id, slot a new one.
-    if (cur_plane_id == -1) {
-      if (_max_clip_planes < 0 || cur_max_planes < _max_clip_planes) {
-        cur_plane_id = cur_max_planes;
-        _clip_plane_info.push_back(ClipPlaneInfo());
-        cur_max_planes++;
-        nassertv(cur_max_planes == (int)_clip_plane_info.size());
+      
+      // If there were no unbound plane ids, see if we can replace
+      // a currently unused but previously bound id
+      if (cur_plane_id == -1) {
+        for (i = 0; i < cur_max_planes; i++) {
+          if (!new_attrib->has_on_plane(_clip_plane_info[i]._plane)) {
+            _clip_plane_info[i]._plane = plane;
+            cur_plane_id = i;
+            break;
+          }
+        }
       }
-    }
-
-    if (cur_plane_id >= 0) {
-      enable_clip_plane(cur_plane_id, true);
-      _clip_plane_info[cur_plane_id]._enabled = true;
-      _clip_plane_info[cur_plane_id]._next_enabled = true;
-
-      if (!any_bound) {
-        begin_bind_clip_planes();
-        any_bound = true;
+      
+      // If we *still* don't have a plane id, slot a new one.
+      if (cur_plane_id == -1) {
+        if (_max_clip_planes < 0 || cur_max_planes < _max_clip_planes) {
+          cur_plane_id = cur_max_planes;
+          _clip_plane_info.push_back(ClipPlaneInfo());
+          cur_max_planes++;
+          nassertv(cur_max_planes == (int)_clip_plane_info.size());
+        }
+      }
+      
+      if (cur_plane_id >= 0) {
+        enable_clip_plane(cur_plane_id, true);
+        _clip_plane_info[cur_plane_id]._enabled = true;
+        _clip_plane_info[cur_plane_id]._next_enabled = true;
+        
+        if (!any_bound) {
+          begin_bind_clip_planes();
+          any_bound = true;
+        }
+        
+        // This is the first time this frame that this plane has been
+        // bound to this particular id.
+        bind_clip_plane(plane, cur_plane_id);
+        
+      } else if (cur_plane_id == -1) {
+        gsg_cat.warning()
+          << "Failed to bind " << plane << " to id.\n";
       }
-
-      // This is the first time this frame that this plane has been
-      // bound to this particular id.
-      bind_clip_plane(plane, cur_plane_id);
-
-    } else if (cur_plane_id == -1) {
-      gsg_cat.warning()
-        << "Failed to bind " << plane << " to id.\n";
     }
   }
 

+ 28 - 0
panda/src/pgraph/planeNode.I

@@ -133,6 +133,34 @@ INLINE int PlaneNode::
 get_priority() const {
   return _priority;
 }
+ 
+////////////////////////////////////////////////////////////////////
+//     Function: PlaneNode::set_clip_effect
+//       Access: Published
+//  Description: Specifies the sort of things this plane will actually
+//               clip (when it is used as a clip plane).  This is a
+//               bitmask union of ClipEffect values.  If it includes
+//               CE_visible, then it will clip visible geometry; if it
+//               includes CE_collision, then it will clip collision
+//               polygons.  If it includes neither bit, it will still
+//               affect culling, but objects will either be wholly
+//               behind the clipping plane, or wholly present.
+////////////////////////////////////////////////////////////////////
+INLINE void PlaneNode::
+set_clip_effect(int clip_effect) {
+  _clip_effect = clip_effect;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PlaneNode::get_clip_effect
+//       Access: Published
+//  Description: Returns the clip_effect bits for this clip plane.
+//               See set_clip_effect().
+////////////////////////////////////////////////////////////////////
+INLINE int PlaneNode::
+get_clip_effect() const {
+  return _clip_effect;
+}
 
 ////////////////////////////////////////////////////////////////////
 //     Function: PlaneNode::get_sort_seq

+ 10 - 1
panda/src/pgraph/planeNode.cxx

@@ -75,7 +75,8 @@ fillin(DatagramIterator &scan, BamReader *) {
 PlaneNode::
 PlaneNode(const string &name, const Planef &plane) :
   PandaNode(name),
-  _priority(0)
+  _priority(0),
+  _clip_effect(~0)
 {
   set_cull_callback();
 
@@ -94,6 +95,7 @@ PlaneNode::
 PlaneNode(const PlaneNode &copy) :
   PandaNode(copy),
   _priority(copy._priority),
+  _clip_effect(copy._clip_effect),
   _cycler(copy._cycler)
 {
 }
@@ -316,6 +318,7 @@ write_datagram(BamWriter *manager, Datagram &dg) {
   PandaNode::write_datagram(manager, dg);
   manager->write_cdata(dg, _cycler);
   dg.add_int32(_priority);
+  dg.add_uint8(_clip_effect);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -350,4 +353,10 @@ fillin(DatagramIterator &scan, BamReader *manager) {
   PandaNode::fillin(scan, manager);
   manager->read_cdata(scan, _cycler);
   _priority = scan.get_int32();
+
+  if (manager->get_file_minor_ver() < 9) {
+    _clip_effect = ~0;
+  } else {
+    _clip_effect = scan.get_uint8();
+  }
 }

+ 8 - 0
panda/src/pgraph/planeNode.h

@@ -65,6 +65,13 @@ PUBLISHED:
   INLINE void set_priority(int priority);
   INLINE int get_priority() const;
 
+  enum ClipEffect {
+    CE_visible    = 0x0001,
+    CE_collision  = 0x0002,
+  };
+  INLINE void set_clip_effect(int clip_effect);
+  INLINE int get_clip_effect() const;
+
 public:
   INLINE static UpdateSeq get_sort_seq();
 
@@ -77,6 +84,7 @@ private:
   // so, and cycling it makes it difficult to synchronize with the
   // ClipPlaneAttribs.
   int _priority;
+  int _clip_effect;
   static UpdateSeq _sort_seq;
 
   // This is the data that must be cycled between pipeline stages.

+ 2 - 1
panda/src/putil/bam.h

@@ -36,7 +36,7 @@ static const unsigned short _bam_major_ver = 6;
 // Bumped to major version 5 on 5/6/05 for new Geom implementation.
 // Bumped to major version 6 on 2/11/06 to factor out PandaNode::CData.
 
-static const unsigned short _bam_minor_ver = 8;
+static const unsigned short _bam_minor_ver = 9;
 // Bumped to minor version 1 on 3/12/06 to add Texture::_compression.
 // Bumped to minor version 2 on 3/17/06 to add PandaNode::_draw_control_mask.
 // Bumped to minor version 3 on 3/21/06 to add Texture::_ram_images.
@@ -45,6 +45,7 @@ static const unsigned short _bam_minor_ver = 8;
 // Bumped to minor version 6 on 2/5/07 to change GeomPrimitive::_num_vertices.
 // Bumped to minor version 7 on 2/15/07 to change SliderTable.
 // Bumped to minor version 8 on 5/12/07 to change GeomVertexArrayData::_data.
+// Bumped to minor version 9 on 5/15/07 to add PlaneNode::_clip_effect.
 
 
 #endif