mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -04:00
parent
1302b215ea
commit
47f39809ee
@ -16,6 +16,7 @@
|
||||
#include "collisionRay.h"
|
||||
#include "collisionSphere.h"
|
||||
#include "collisionSegment.h"
|
||||
#include "collisionParabola.h"
|
||||
#include "collisionCapsule.h"
|
||||
#include "collisionHandler.h"
|
||||
#include "collisionEntry.h"
|
||||
@ -493,6 +494,82 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
|
||||
return new_entry;
|
||||
}
|
||||
|
||||
PT(CollisionEntry) CollisionBox::
|
||||
test_intersection_from_parabola(const CollisionEntry &entry) const {
|
||||
const CollisionParabola *parabola;
|
||||
DCAST_INTO_R(parabola, entry.get_from(), nullptr);
|
||||
|
||||
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
|
||||
|
||||
// Convert the parabola into local coordinate space.
|
||||
LParabola local_p(parabola->get_parabola());
|
||||
local_p.xform(wrt_mat);
|
||||
|
||||
PN_stdfloat t = INT_MAX;
|
||||
PN_stdfloat t1, t2;
|
||||
int intersecting_face = -1;
|
||||
for (int i = 0; i < get_num_planes(); i++) {
|
||||
LPlane face = get_plane(i);
|
||||
if (!face.intersects_parabola(t1, t2, local_p)) {
|
||||
// the parabola does not intersect this face, skip to the next one
|
||||
continue;
|
||||
}
|
||||
PN_stdfloat ts[2] = {t1, t2};
|
||||
// iterate through the t values to see if each of them are within our
|
||||
// parabola and the intersection point is behind all other faces
|
||||
for (int j = 0; j < 2; j++) {
|
||||
PN_stdfloat cur_t = ts[j];
|
||||
if (cur_t > t) {
|
||||
// we are looking for the earliest t value
|
||||
// if this t value is greater, don't bother checking it
|
||||
continue;
|
||||
}
|
||||
if (cur_t >= parabola->get_t1() && cur_t <= parabola->get_t2()) {
|
||||
// the parabola does intersect this plane, now we check
|
||||
// if the intersection point is behind all other planes
|
||||
bool behind = true;
|
||||
for (int k = 0; k < get_num_planes(); k++) {
|
||||
if (k == i) {
|
||||
// no need to check the intersecting face
|
||||
continue;
|
||||
}
|
||||
if (get_plane(k).dist_to_plane(local_p.calc_point(cur_t)) > 0.0f) {
|
||||
// our point is in front of this face, turns out the parabola
|
||||
// does not collide with the box at this point
|
||||
behind = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (behind) {
|
||||
// the parabola does indeed collide with the box at this point
|
||||
t = cur_t;
|
||||
intersecting_face = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (intersecting_face != -1) {
|
||||
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);
|
||||
|
||||
LPlane face = get_plane(intersecting_face);
|
||||
|
||||
LPoint3 into_intersection_point = local_p.calc_point(t);
|
||||
LVector3 normal = (has_effective_normal() && parabola->get_respect_effective_normal()) ? get_effective_normal() : face.get_normal();
|
||||
|
||||
new_entry->set_surface_point(into_intersection_point);
|
||||
new_entry->set_surface_normal(normal);
|
||||
return new_entry;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Double dispatch point for segment as a FROM object
|
||||
*/
|
||||
|
@ -81,6 +81,8 @@ protected:
|
||||
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_parabola(const CollisionEntry &entry) const;
|
||||
virtual PT(CollisionEntry)
|
||||
test_intersection_from_capsule(const CollisionEntry &entry) const;
|
||||
virtual PT(CollisionEntry)
|
||||
|
@ -43,3 +43,74 @@ def test_ray_into_box():
|
||||
# No collision
|
||||
entry = make_collision(CollisionRay(0, 0, 100, 1, 0, 0), box)[0]
|
||||
assert entry is None
|
||||
|
||||
|
||||
def test_parabola_into_box():
|
||||
# Set up Parabola and Box
|
||||
parabola = CollisionParabola()
|
||||
parabola.set_t1(0)
|
||||
parabola.set_t2(2)
|
||||
box = CollisionBox((0,0,0), 3, 3, 3)
|
||||
|
||||
# Parabola is inside the Box and not colliding
|
||||
parabola.set_parabola(
|
||||
LParabola((-1, 0, -1), (1, 0, 1), (1, 1, 1)))
|
||||
entry = make_collision(parabola, box)[0]
|
||||
assert entry is None
|
||||
|
||||
# Parabola is inside the Box and colliding on its projectile
|
||||
parabola.set_parabola(
|
||||
LParabola((0, 0, 1), (0, 0, 1), (1, 1, 1)))
|
||||
# Parabola collides with Box when t == 1 at point (1, 1, 3)
|
||||
assert parabola.get_parabola().calc_point(1) == (1, 1, 3)
|
||||
entry, np_from, into = make_collision(parabola, box)
|
||||
assert entry.get_surface_point(np_from) == (1, 1, 3)
|
||||
assert entry.get_from() == parabola
|
||||
assert entry.get_into() == box
|
||||
|
||||
# Parabola is inside the Box and colliding on one of the endpoints
|
||||
parabola.set_parabola(
|
||||
LParabola((0, 0, 0), (0, 0, 1), (-3, 0, -3)))
|
||||
entry, np_from, np_into = make_collision(parabola, box)
|
||||
assert entry.get_surface_point(np_from) == (-3, 0, -3)
|
||||
|
||||
# Parabola is outside the Box and not colliding
|
||||
parabola.set_parabola(
|
||||
LParabola((0, 0, 0), (0, 0, 1), (-5, 0, 0)))
|
||||
entry = make_collision(parabola, box)[0]
|
||||
assert entry is None
|
||||
|
||||
# Parabola is outside the Box and colliding on its projecticle
|
||||
parabola.set_parabola(
|
||||
LParabola((-2, -2, -2), (1, 1, 1), (4, 4, 4)))
|
||||
# Parabola collides with Box when t == 1 at point (3, 3, 3)
|
||||
assert parabola.get_parabola().calc_point(1) == (3, 3, 3)
|
||||
entry, np_from, into = make_collision(parabola, box)
|
||||
assert entry.get_surface_point(np_from) == (3, 3, 3)
|
||||
|
||||
# Parabola is outside the Box and colliding on the first endpoint
|
||||
parabola.set_parabola(
|
||||
LParabola((1, 1, 1), (1, 1, 1), (3, 3, 3)))
|
||||
entry, np_from, np_into = make_collision(parabola, box)
|
||||
assert entry.get_surface_point(np_from) == (3, 3, 3)
|
||||
|
||||
# Parabola is outside the Box and colliding on the second endpoint
|
||||
parabola.set_parabola(
|
||||
LParabola((1, 0, 1), (-1, 0, -1), (-5, -3, -5)))
|
||||
assert parabola.get_parabola().calc_point(2) == (-3, -3, -3)
|
||||
entry, np_from, np_into = make_collision(parabola, box)
|
||||
assert entry.get_surface_point(np_from) == (-3, -3, -3)
|
||||
|
||||
# Parabola intersects the Box at two points,
|
||||
# t == 0 and t == 2 the earliest one should be chosen.
|
||||
parabola.set_parabola(
|
||||
LParabola((-1, -1, -1), (-1, -1, -1), (3, 3, 3)))
|
||||
entry, np_from, np_into = make_collision(parabola, box)
|
||||
assert entry.get_surface_point(np_from) == parabola.get_parabola().calc_point(0)
|
||||
|
||||
# First point no longer intersecting
|
||||
parabola.set_t1(1)
|
||||
entry, np_from, np_into = make_collision(parabola, box)
|
||||
assert parabola.get_parabola().calc_point(2) == (-3, -3, -3)
|
||||
assert entry.get_surface_point(np_from) == parabola.get_parabola().calc_point(2)
|
||||
assert entry.get_surface_normal(np_from) is not None
|
||||
|
Loading…
x
Reference in New Issue
Block a user