diff --git a/panda/src/collide/collisionPolygon.cxx b/panda/src/collide/collisionPolygon.cxx index 10001bfe8d..8d94401188 100644 --- a/panda/src/collide/collisionPolygon.cxx +++ b/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; + } } } } diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index f705c17c89..0eb133279d 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/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"; } } diff --git a/panda/src/pgraph/planeNode.I b/panda/src/pgraph/planeNode.I index b401cd916a..c9e9b84f3d 100644 --- a/panda/src/pgraph/planeNode.I +++ b/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 diff --git a/panda/src/pgraph/planeNode.cxx b/panda/src/pgraph/planeNode.cxx index 5f870ff801..80e25321a6 100644 --- a/panda/src/pgraph/planeNode.cxx +++ b/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 ©) : 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(); + } } diff --git a/panda/src/pgraph/planeNode.h b/panda/src/pgraph/planeNode.h index 1f0e52caf9..771fc2025d 100644 --- a/panda/src/pgraph/planeNode.h +++ b/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. diff --git a/panda/src/putil/bam.h b/panda/src/putil/bam.h index e4dc3b4539..5eaa49a1b0 100644 --- a/panda/src/putil/bam.h +++ b/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