From 5a635059b6c2070e1b38829424ed10d2b043328f Mon Sep 17 00:00:00 2001 From: David Rose Date: Sat, 11 Sep 2010 08:39:05 +0000 Subject: [PATCH] add CollisionBox::test_intersection_from_segment() from forum user teedee --- panda/src/collide/collisionBox.cxx | 85 ++++++++++++++++++++++++++++++ panda/src/collide/collisionBox.h | 2 + 2 files changed, 87 insertions(+) diff --git a/panda/src/collide/collisionBox.cxx b/panda/src/collide/collisionBox.cxx index a9699329da..571d9ce52b 100644 --- a/panda/src/collide/collisionBox.cxx +++ b/panda/src/collide/collisionBox.cxx @@ -531,6 +531,91 @@ test_intersection_from_ray(const CollisionEntry &entry) const { return new_entry; } + +//////////////////////////////////////////////////////////////////// +// Function: CollisionBox::test_intersection_from_segment +// Access: Public, Virtual +// Description: Double dispatch point for segment as a FROM object +//////////////////////////////////////////////////////////////////// +PT(CollisionEntry) CollisionBox:: +test_intersection_from_segment(const CollisionEntry &entry) const { + const CollisionSegment *seg; + DCAST_INTO_R(seg, entry.get_from(), 0); + const LMatrix4f &wrt_mat = entry.get_wrt_mat(); + + LPoint3f from_origin = seg->get_point_a() * wrt_mat; + LPoint3f from_extent = seg->get_point_b() * wrt_mat; + LVector3f from_direction = from_extent - from_origin; + + int i, j; + float t, near_t; + bool intersect; + Planef plane; + Planef near_plane; + + //Returns the details about the first plane of the box that the + //segment intersects. + for(i = 0, intersect = false, t = 0, j = 0; i < 6 && j < 2; i++) { + plane = get_plane(i); + + if (!plane.intersects_line(t, from_origin, from_direction)) { + // No intersection. The segment is parallel to the plane. + continue; + } + + if (t < 0.0f || t > 1.0f) { + // The intersection point is before the start of the segment, + // or after the end of the segment, so the segment is either + // entirely in front of or behind the plane. + continue; + } + LPoint3f plane_point = from_origin + t * from_direction; + LPoint2f p = to_2d(plane_point, i); + + if (!point_is_inside(p, _points[i])){ + continue; + } + intersect = true; + if(j) { + if(t < near_t) { + near_plane = plane; + near_t = t; + } + } + else { + near_plane = plane; + near_t = t; + } + ++j; + } + + + if(!intersect) { + //No intersection with ANY of the box's planes has been detected + return NULL; + } + + if (collide_cat.is_debug()) { + collide_cat.debug() + << "intersection detected from " << entry.get_from_node_path() + << " into " << entry.get_into_node_path() << "\n"; + } + + PT(CollisionEntry) new_entry = new CollisionEntry(entry); + + LPoint3f into_intersection_point = from_origin + near_t * from_direction; + + LVector3f normal = + (has_effective_normal() && seg->get_respect_effective_normal()) + ? get_effective_normal() : near_plane.get_normal(); + + new_entry->set_surface_normal(normal); + new_entry->set_surface_point(into_intersection_point); + + return new_entry; +} + + //////////////////////////////////////////////////////////////////// // Function: CollisionBox::test_intersection_from_box // Access: Public, Virtual diff --git a/panda/src/collide/collisionBox.h b/panda/src/collide/collisionBox.h index 328c5ec712..3f58a1d10f 100644 --- a/panda/src/collide/collisionBox.h +++ b/panda/src/collide/collisionBox.h @@ -78,6 +78,8 @@ protected: virtual PT(CollisionEntry) test_intersection_from_ray(const CollisionEntry &entry) const; virtual PT(CollisionEntry) + test_intersection_from_segment(const CollisionEntry &entry) const; + virtual PT(CollisionEntry) test_intersection_from_box(const CollisionEntry &entry) const; virtual void fill_viz_geom();