Add box-into-plane collision test

This commit is contained in:
rdb 2015-12-04 00:03:11 +01:00
parent c644e7ae49
commit f7b61d4fa4
4 changed files with 58 additions and 0 deletions

View File

@ -130,6 +130,16 @@ get_center() const {
return _center;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionBox::get_dimensions
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE LVector3 CollisionBox::
get_dimensions() const {
return _max - _min;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionBox::get_radius
// Access: Published

View File

@ -68,6 +68,7 @@ PUBLISHED:
INLINE void set_center(const LPoint3 &center);
INLINE void set_center(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z);
INLINE const LPoint3 &get_center() const;
INLINE LVector3 get_dimensions() const;
INLINE PN_stdfloat get_radius() const;
protected:

View File

@ -390,6 +390,51 @@ test_intersection_from_parabola(const CollisionEntry &entry) const {
return new_entry;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionPlane::test_intersection_from_box
// Access: Public, Virtual
// Description: This is part of the double-dispatch implementation of
// test_intersection(). It is called when the "from"
// object is a box.
////////////////////////////////////////////////////////////////////
PT(CollisionEntry) CollisionPlane::
test_intersection_from_box(const CollisionEntry &entry) const {
const CollisionBox *box;
DCAST_INTO_R(box, entry.get_from(), 0);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
LPoint3 from_center = box->get_center() * wrt_mat;
LVector3 from_extents = box->get_dimensions() * wrt_mat * 0.5;
PN_stdfloat dist = _plane.dist_to_plane(from_center);
LVecBase3 box_x = entry.get_wrt_mat().get_row3(0);
LVecBase3 box_y = entry.get_wrt_mat().get_row3(1);
LVecBase3 box_z = entry.get_wrt_mat().get_row3(2);
if (abs(dist) >
abs(box_x.dot(_plane.get_normal()) * from_extents[0]) +
abs(box_y.dot(_plane.get_normal()) * from_extents[1]) +
abs(box_z.dot(_plane.get_normal()) * from_extents[2])) {
// No collision.
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);
LVector3 normal = (has_effective_normal() && box->get_respect_effective_normal()) ? get_effective_normal() : get_normal();
new_entry->set_surface_normal(normal);
new_entry->set_surface_point(from_center - get_normal() * dist);
return new_entry;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionPlane::fill_viz_geom
// Access: Protected, Virtual

View File

@ -71,6 +71,8 @@ protected:
test_intersection_from_segment(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
test_intersection_from_parabola(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
test_intersection_from_box(const CollisionEntry &entry) const;
virtual void fill_viz_geom();