43PStatCollector CollisionBox::_volume_pcollector(
"Collision Volumes:CollisionBox");
44PStatCollector CollisionBox::_test_pcollector(
"Collision Tests:CollisionBox");
47const int CollisionBox::plane_def[6][4] = {
69 for(
int plane = 0; plane < 6; plane++) {
83setup_points(
const LPoint3 *begin,
const LPoint3 *end,
int plane) {
84 int num_points = end - begin;
85 nassertv(num_points >= 3);
87 _points[plane].clear();
95 _to_2d_mat[plane].invert_from(to_3d_mat);
100 for (pi = begin; pi != end; ++pi) {
101 LPoint3 point = (*pi) * _to_2d_mat[plane];
102 _points[plane].push_back(
PointDef(point[0], point[2]));
105 nassertv(_points[plane].size() >= 3);
131 return entry.
get_into()->test_intersection_from_box(entry);
138xform(
const LMatrix4 &mat) {
141 _center = _center * mat;
142 for(
int v = 0; v < 8; v++) {
143 _vertex[v] = _vertex[v] * mat;
145 for(
int p = 0; p < 6 ; p++) {
148 _x = _vertex[0].get_x() - _center.get_x();
149 _y = _vertex[0].get_y() - _center.get_y();
150 _z = _vertex[0].get_z() - _center.get_z();
151 _radius = sqrt(_x * _x + _y * _y + _z * _z);
154 mark_internal_bounds_stale();
173 return _volume_pcollector;
182 return _test_pcollector;
189output(std::ostream &out)
const {
190 out <<
"box, (" << get_min() <<
") to (" << get_max() <<
")";
197compute_internal_bounds()
const {
198 return new BoundingSphere(_center, _radius);
207 const CollisionSphere *sphere;
208 DCAST_INTO_R(sphere, entry.
get_from(),
nullptr);
213 const LMatrix4 &wrt_mat = wrt_space->get_mat();
215 LPoint3 orig_center = sphere->get_center() * wrt_mat;
216 LPoint3 from_center = orig_center;
217 bool moved_from_center =
false;
218 PN_stdfloat t = 1.0f;
219 LPoint3 contact_point(from_center);
220 PN_stdfloat actual_t = 1.0f;
222 LVector3 from_radius_v =
223 LVector3(sphere->get_radius(), 0.0f, 0.0f) * wrt_mat;
224 PN_stdfloat from_radius_2 = from_radius_v.length_squared();
225 PN_stdfloat from_radius = csqrt(from_radius_2);
228 PN_stdfloat max_dist = 0.0;
229 PN_stdfloat dist = 0.0;
233 bool fully_inside =
true;
235 for(ip = 0, intersect =
false; ip < 6 && !intersect; ip++) {
237 if (_points[ip].size() < 3) {
238 fully_inside =
false;
241 if (wrt_prev_space != wrt_space) {
245 LPoint3 b = from_center;
246 LPoint3 a = sphere->get_center() * wrt_prev_space->get_mat();
247 LVector3 delta = b - a;
251 PN_stdfloat dot = delta.dot(plane.get_normal());
253 fully_inside =
false;
257 if (IS_NEARLY_ZERO(dot)) {
270 PN_stdfloat dist_to_p = plane.dist_to_plane(a);
271 t = (dist_to_p / -dot);
275 actual_t = ((dist_to_p - from_radius) / -dot);
276 actual_t = min((PN_stdfloat)1.0, max((PN_stdfloat)0.0, actual_t));
277 contact_point = a + (actual_t * delta);
282 }
else if (t < 0.0f) {
284 moved_from_center =
true;
286 from_center = a + t * delta;
287 moved_from_center =
true;
307 if (!plane.intersects_line(dist, from_center, -(plane.get_normal()))) {
310 fully_inside =
false;
314 if (dist > from_radius) {
318 if (dist < -from_radius) {
322 fully_inside =
false;
324 LPoint2 p =
to_2d(from_center - dist * plane.get_normal(), ip);
325 PN_stdfloat edge_dist = 0.0f;
327 const ClipPlaneAttrib *cpa = entry.get_into_clip_planes();
328 if (cpa !=
nullptr) {
334 }
else if (new_points.empty()) {
346 max_dist = from_radius;
356 if((edge_dist > 0) &&
357 ((edge_dist * edge_dist + dist * dist) > from_radius_2)) {
367 if (edge_dist >= 0.0f) {
368 PN_stdfloat max_dist_2 = max(from_radius_2 - edge_dist * edge_dist, (PN_stdfloat)0.0);
369 max_dist = csqrt(max_dist_2);
372 if (dist > max_dist) {
378 if (!fully_inside && !intersect) {
382 if (collide_cat.is_debug()) {
388 PT(CollisionEntry) new_entry =
new CollisionEntry(entry);
390 PN_stdfloat into_depth = max_dist - dist;
391 if (moved_from_center) {
394 PN_stdfloat orig_dist;
395 plane.intersects_line(orig_dist, orig_center, -normal);
396 into_depth = max_dist - orig_dist;
400 LPoint3 surface = from_center - normal * dist;
401 surface = surface.fmax(_min);
402 surface = surface.fmin(_max);
404 new_entry->set_surface_normal(normal);
405 new_entry->set_surface_point(surface);
406 new_entry->set_interior_point(surface - normal * into_depth);
407 new_entry->set_contact_pos(contact_point);
408 new_entry->set_contact_normal(plane.get_normal());
409 new_entry->set_t(actual_t);
419 const CollisionLine *line;
420 DCAST_INTO_R(line, entry.
get_from(),
nullptr);
423 const LMatrix4 &wrt_mat = wrt_space->get_mat();
425 LPoint3 from_origin = line->get_origin() * wrt_mat;
426 LVector3 from_direction = line->get_direction() * wrt_mat;
429 if (!intersects_line(t1, t2, from_origin, from_direction)) {
434 if (collide_cat.is_debug()) {
439 PT(CollisionEntry) new_entry =
new CollisionEntry(entry);
441 LPoint3 point = from_origin + t1 * from_direction;
442 new_entry->set_surface_point(point);
448 IS_NEARLY_EQUAL(point[0], _max[0]) - IS_NEARLY_EQUAL(point[0], _min[0]),
449 IS_NEARLY_EQUAL(point[1], _max[1]) - IS_NEARLY_EQUAL(point[1], _min[1]),
450 IS_NEARLY_EQUAL(point[2], _max[2]) - IS_NEARLY_EQUAL(point[2], _min[2])
453 new_entry->set_surface_normal(normal);
464 const CollisionRay *ray;
465 DCAST_INTO_R(ray, entry.
get_from(),
nullptr);
467 const LMatrix4 &wrt_mat = wrt_space->get_mat();
469 LPoint3 from_origin = ray->get_origin() * wrt_mat;
470 LVector3 from_direction = ray->get_direction() * wrt_mat;
473 if (!intersects_line(t1, t2, from_origin, from_direction) || (t1 < 0.0 && t2 < 0.0)) {
478 if (collide_cat.is_debug()) {
483 PT(CollisionEntry) new_entry =
new CollisionEntry(entry);
487 new_entry->set_interior_point(from_origin);
491 LPoint3 point = from_origin + t1 * from_direction;
492 new_entry->set_surface_point(point);
498 IS_NEARLY_EQUAL(point[0], _max[0]) - IS_NEARLY_EQUAL(point[0], _min[0]),
499 IS_NEARLY_EQUAL(point[1], _max[1]) - IS_NEARLY_EQUAL(point[1], _min[1]),
500 IS_NEARLY_EQUAL(point[2], _max[2]) - IS_NEARLY_EQUAL(point[2], _min[2])
503 new_entry->set_surface_normal(normal);
513test_intersection_from_segment(
const CollisionEntry &entry)
const {
514 const CollisionSegment *seg;
515 DCAST_INTO_R(seg, entry.
get_from(),
nullptr);
517 const LMatrix4 &wrt_mat = wrt_space->get_mat();
519 LPoint3 from_origin = seg->get_point_a() * wrt_mat;
520 LPoint3 from_extent = seg->get_point_b() * wrt_mat;
521 LVector3 from_direction = from_extent - from_origin;
524 if (!intersects_line(t1, t2, from_origin, from_direction) ||
525 (t1 < 0.0 && t2 < 0.0) || (t1 > 1.0 && t2 > 1.0)) {
530 if (collide_cat.is_debug()) {
535 PT(CollisionEntry) new_entry =
new CollisionEntry(entry);
539 if (t1 < (1.0 - t2)) {
544 new_entry->set_interior_point(from_origin + std::min(std::max(t2, 0.0), 1.0) * from_direction);
546 LPoint3 point = from_origin + t1 * from_direction;
547 new_entry->set_surface_point(point);
553 IS_NEARLY_EQUAL(point[0], _max[0]) - IS_NEARLY_EQUAL(point[0], _min[0]),
554 IS_NEARLY_EQUAL(point[1], _max[1]) - IS_NEARLY_EQUAL(point[1], _min[1]),
555 IS_NEARLY_EQUAL(point[2], _max[2]) - IS_NEARLY_EQUAL(point[2], _min[2])
558 new_entry->set_surface_normal(normal);
568test_intersection_from_capsule(
const CollisionEntry &entry)
const {
569 const CollisionCapsule *capsule;
570 DCAST_INTO_R(capsule, entry.
get_from(),
nullptr);
573 const LMatrix4 &wrt_mat = wrt_space->get_mat();
575 LPoint3 from_a = capsule->get_point_a() * wrt_mat;
576 LPoint3 from_b = capsule->get_point_b() * wrt_mat;
577 LVector3 from_direction = from_b - from_a;
578 PN_stdfloat radius_sq = wrt_mat.xform_vec(LVector3(0, 0, capsule->get_radius())).length_squared();
579 PN_stdfloat radius = csqrt(radius_sq);
581 LPoint3 box_min = get_min();
582 LPoint3 box_max = get_max();
583 LVector3 dimensions = box_max - box_min;
592 if (!intersects_line(t1, t2, from_a, from_direction, radius)) {
596 if (t2 < 0.0 || t1 > 1.0) {
600 t1 = std::min(1.0, std::max(0.0, (t1 + t2) * 0.5));
601 LPoint3 point = from_a + from_direction * t1;
608 if ((point[0] < box_min[0] || point[0] > box_max[0]) +
609 (point[1] < box_min[1] || point[1] > box_max[1]) +
610 (point[2] < box_min[2] || point[2] > box_max[2]) > 1) {
612 static const struct {
630 PN_stdfloat best_dist_sq = FLT_MAX;
632 for (
int i = 0; i < 12; ++i) {
633 LPoint3 vertex = edges[i].point;
634 vertex.componentwise_mult(dimensions);
637 delta[edges[i].axis] = dimensions[edges[i].axis];
639 CollisionCapsule::calc_closest_segment_points(u1, u2, from_a, from_direction, vertex, delta);
640 PN_stdfloat dist_sq = ((from_a + from_direction * u1) - (vertex + delta * u2)).length_squared();
641 if (dist_sq < best_dist_sq) {
642 best_dist_sq = dist_sq;
646 if (best_dist_sq > radius_sq) {
652 if (collide_cat.is_debug()) {
657 PT(CollisionEntry) new_entry =
new CollisionEntry(entry);
660 LVector3 diff = point - _center;
661 diff[0] /= dimensions[0];
662 diff[1] /= dimensions[1];
663 diff[2] /= dimensions[2];
665 if (cabs(diff[0]) > cabs(diff[1])) {
666 if (cabs(diff[0]) > cabs(diff[2])) {
672 if (cabs(diff[1]) > cabs(diff[2])) {
679 normal[axis] = std::copysign(1, diff[axis]);
681 LPoint3 clamped = point.fmax(box_min).fmin(box_max);
682 LPoint3 surface_point = clamped;
683 surface_point[axis] = (diff[axis] >= 0.0f) ? box_max[axis] : box_min[axis];
686 LVector3 interior_vec;
687 if (clamped != point) {
690 interior_vec = point - surface_point;
691 if (!interior_vec.normalize()) {
692 interior_vec = normal;
696 interior_vec = normal;
698 new_entry->set_interior_point(point - interior_vec * radius);
699 new_entry->set_surface_point(surface_point);
704 new_entry->set_surface_normal(normal);
716 DCAST_INTO_R(box, entry.
get_from(),
nullptr);
719 const LMatrix4 &wrt_mat = wrt_space->get_mat();
721 LPoint3 diff = wrt_mat.xform_point_general(box->get_center()) - _center;
722 LVector3 from_extents = box->get_dimensions() * 0.5f;
723 LVector3 into_extents = get_dimensions() * 0.5f;
725 LVecBase3 box_x = wrt_mat.get_row3(0);
726 LVecBase3 box_y = wrt_mat.get_row3(1);
727 LVecBase3 box_z = wrt_mat.get_row3(2);
735 from_extents[0] *= l;
738 from_extents[1] *= l;
741 from_extents[2] *= l;
745 PN_stdfloat min_pen = 0;
750 r1 = into_extents[0];
751 r2 = cabs(box_x[0] * from_extents[0]) +
752 cabs(box_y[0] * from_extents[1]) +
753 cabs(box_z[0] * from_extents[2]);
754 pen = r1 + r2 - cabs(diff[0]);
760 r1 = into_extents[1];
761 r2 = cabs(box_x[1] * from_extents[0]) +
762 cabs(box_y[1] * from_extents[1]) +
763 cabs(box_z[1] * from_extents[2]);
764 pen = r1 + r2 - cabs(diff[1]);
773 r1 = into_extents[2];
774 r2 = cabs(box_x[2] * from_extents[0]) +
775 cabs(box_y[2] * from_extents[1]) +
776 cabs(box_z[2] * from_extents[2]);
777 pen = r1 + r2 - cabs(diff[2]);
787 r1 = cabs(box_x[0] * into_extents[0]) +
788 cabs(box_x[1] * into_extents[1]) +
789 cabs(box_x[2] * into_extents[2]);
790 r2 = from_extents[0];
791 pen = r1 + r2 - cabs(diff.dot(box_x));
799 r1 = cabs(box_y[0] * into_extents[0]) +
800 cabs(box_y[1] * into_extents[1]) +
801 cabs(box_y[2] * into_extents[2]);
802 r2 = from_extents[1];
803 pen = r1 + r2 - cabs(diff.dot(box_y));
811 r1 = cabs(box_z[0] * into_extents[0]) +
812 cabs(box_z[1] * into_extents[1]) +
813 cabs(box_z[2] * into_extents[2]);
814 r2 = from_extents[2];
815 pen = r1 + r2 - cabs(diff.dot(box_z));
824 r1 = into_extents[1] * cabs(box_x[2]) + into_extents[2] * cabs(box_x[1]);
825 r2 = from_extents[1] * cabs(box_z[0]) + from_extents[2] * cabs(box_y[0]);
826 if (cabs(diff[2] * box_x[1] - diff[1] * box_x[2]) > r1 + r2) {
830 r1 = into_extents[1] * cabs(box_y[2]) + into_extents[2] * cabs(box_y[1]);
831 r2 = from_extents[0] * cabs(box_z[0]) + from_extents[2] * cabs(box_x[0]);
832 if (cabs(diff[2] * box_y[1] - diff[1] * box_y[2]) > r1 + r2) {
836 r1 = into_extents[1] * cabs(box_z[2]) + into_extents[2] * cabs(box_z[1]);
837 r2 = from_extents[0] * cabs(box_y[0]) + from_extents[1] * cabs(box_x[0]);
838 if (cabs(diff[2] * box_z[1] - diff[1] * box_z[2]) > r1 + r2) {
842 r1 = into_extents[0] * cabs(box_x[2]) + into_extents[2] * cabs(box_x[0]);
843 r2 = from_extents[1] * cabs(box_z[1]) + from_extents[2] * cabs(box_y[1]);
844 if (cabs(diff[0] * box_x[2] - diff[2] * box_x[0]) > r1 + r2) {
848 r1 = into_extents[0] * cabs(box_y[2]) + into_extents[2] * cabs(box_y[0]);
849 r2 = from_extents[0] * cabs(box_z[1]) + from_extents[2] * cabs(box_x[1]);
850 if (cabs(diff[0] * box_y[2] - diff[2] * box_y[0]) > r1 + r2) {
854 r1 = into_extents[0] * cabs(box_z[2]) + into_extents[2] * cabs(box_z[0]);
855 r2 = from_extents[0] * cabs(box_y[1]) + from_extents[1] * cabs(box_x[1]);
856 if (cabs(diff[0] * box_z[2] - diff[2] * box_z[0]) > r1 + r2) {
860 r1 = into_extents[0] * cabs(box_x[1]) + into_extents[1] * cabs(box_x[0]);
861 r2 = from_extents[1] * cabs(box_z[2]) + from_extents[2] * cabs(box_y[2]);
862 if (cabs(diff[1] * box_x[0] - diff[0] * box_x[1]) > r1 + r2) {
866 r1 = into_extents[0] * cabs(box_y[1]) + into_extents[1] * cabs(box_y[0]);
867 r2 = from_extents[0] * cabs(box_z[2]) + from_extents[2] * cabs(box_x[2]);
868 if (cabs(diff[1] * box_y[0] - diff[0] * box_y[1]) > r1 + r2) {
872 r1 = into_extents[0] * cabs(box_z[1]) + into_extents[1] * cabs(box_z[0]);
873 r2 = from_extents[0] * cabs(box_y[2]) + from_extents[1] * cabs(box_x[2]);
874 if (cabs(diff[1] * box_z[0] - diff[0] * box_z[1]) > r1 + r2) {
878 if (collide_cat.is_debug()) {
883 PT(CollisionEntry) new_entry =
new CollisionEntry(entry);
888 min(max(diff[0], -into_extents[0]), into_extents[0]),
889 min(max(diff[1], -into_extents[1]), into_extents[1]),
890 min(max(diff[2], -into_extents[2]), into_extents[2]));
894 PN_stdfloat diff_axis = diff[axis];
895 int sign = (diff_axis >= 0) ? 1 : -1;
897 surface[axis] = into_extents[axis] * sign;
899 new_entry->set_surface_point(surface + _center);
902 new_entry->set_interior_point(surface + _center + normal * -min_pen);
907 new_entry->set_surface_normal(normal);
919 if (collide_cat.is_debug()) {
921 <<
"Recomputing viz for " << *
this <<
"\n";
924 PT(GeomVertexData) vdata =
new GeomVertexData
928 vdata->unclean_set_num_rows(8);
931 GeomVertexWriter vertex(vdata, InternalName::get_vertex());
932 vertex.set_data3(_min[0], _min[1], _min[2]);
933 vertex.set_data3(_min[0], _max[1], _min[2]);
934 vertex.set_data3(_max[0], _max[1], _min[2]);
935 vertex.set_data3(_max[0], _min[1], _min[2]);
937 vertex.set_data3(_min[0], _min[1], _max[2]);
938 vertex.set_data3(_min[0], _max[1], _max[2]);
939 vertex.set_data3(_max[0], _max[1], _max[2]);
940 vertex.set_data3(_max[0], _min[1], _max[2]);
943 PT(GeomTriangles) tris =
new GeomTriangles(Geom::UH_static);
946 tris->add_vertices(0, 1, 2);
947 tris->add_vertices(2, 3, 0);
950 tris->add_vertices(4, 7, 6);
951 tris->add_vertices(6, 5, 4);
954 tris->add_vertices(0, 4, 1);
955 tris->add_vertices(1, 4, 5);
957 tris->add_vertices(1, 5, 2);
958 tris->add_vertices(2, 5, 6);
960 tris->add_vertices(2, 6, 3);
961 tris->add_vertices(3, 6, 7);
963 tris->add_vertices(3, 7, 0);
964 tris->add_vertices(0, 7, 4);
966 PT(GeomLines) lines =
new GeomLines(Geom::UH_static);
969 lines->add_vertices(0, 1);
970 lines->add_vertices(1, 2);
971 lines->add_vertices(0, 3);
972 lines->add_vertices(2, 3);
975 lines->add_vertices(4, 5);
976 lines->add_vertices(5, 6);
977 lines->add_vertices(4, 7);
978 lines->add_vertices(6, 7);
981 lines->add_vertices(0, 4);
982 lines->add_vertices(1, 5);
983 lines->add_vertices(2, 6);
984 lines->add_vertices(3, 7);
986 PT(Geom) geom1 =
new Geom(vdata);
987 geom1->add_primitive(tris);
989 PT(Geom) geom2 =
new Geom(vdata);
990 geom2->add_primitive(lines);
992 _viz_geom->add_geom(geom1, get_solid_viz_state());
993 _viz_geom->add_geom(geom2, get_wireframe_viz_state());
995 _bounds_viz_geom->add_geom(geom1, get_solid_bounds_viz_state());
996 _bounds_viz_geom->add_geom(geom2, get_wireframe_viz_state());
1008intersects_line(
double &t1,
double &t2,
1009 const LPoint3 &from,
const LVector3 &delta,
1010 PN_stdfloat inflate_size)
const {
1012 LPoint3 bmin = _min - LVector3(inflate_size);
1013 LPoint3 bmax = _max + LVector3(inflate_size);
1015 double tmin = -DBL_MAX;
1016 double tmax = DBL_MAX;
1018 for (
int i = 0; i < 3; ++i) {
1019 PN_stdfloat d = delta[i];
1020 if (!IS_NEARLY_ZERO(d)) {
1021 double tmin2 = (bmin[i] - from[i]) / d;
1022 double tmax2 = (bmax[i] - from[i]) / d;
1023 if (tmin2 > tmax2) {
1024 std::swap(tmin2, tmax2);
1026 tmin = std::max(tmin, tmin2);
1027 tmax = std::min(tmax, tmax2);
1033 }
else if (from[i] < bmin[i] || from[i] > bmax[i]) {
1058 bool first_plane =
true;
1060 for (
int i = 0; i < num_planes; i++) {
1065 net_transform->invert_compose(plane_path.get_net_transform());
1067 LPlane plane = plane_node->
get_plane() * new_transform->get_mat();
1069 first_plane =
false;
1070 if (!
clip_polygon(new_points, _points[plane_no], plane, plane_no)) {
1075 last_points.swap(new_points);
1076 if (!
clip_polygon(new_points, last_points, plane, plane_no)) {
1099 const CollisionBox::Points &source_points,
1100 const LPlane &plane,
int plane_no)
const {
1102 if (source_points.empty()) {
1108 if (!plane.intersects_plane(from3d, delta3d,
get_plane(plane_no))) {
1114 new_points = source_points;
1122 LPoint2 from2d =
to_2d(from3d,plane_no);
1123 LVector2 delta2d =
to_2d(delta3d,plane_no);
1125 PN_stdfloat a = -delta2d[1];
1126 PN_stdfloat b = delta2d[0];
1127 PN_stdfloat c = from2d[0] * delta2d[1] - from2d[1] * delta2d[0];
1135 new_points.reserve(source_points.size() + 1);
1137 LPoint2 last_point = source_points.back()._p;
1138 bool last_is_in = !is_right(last_point - from2d, delta2d);
1139 bool all_in = last_is_in;
1140 Points::const_iterator pi;
1141 for (pi = source_points.begin(); pi != source_points.end(); ++pi) {
1142 const LPoint2 &this_point = (*pi)._p;
1143 bool this_is_in = !is_right(this_point - from2d, delta2d);
1147 bool crossed_over = (this_is_in != last_is_in);
1151 LVector2 d = this_point - last_point;
1152 PN_stdfloat denom = (a * d[0] + b * d[1]);
1154 PN_stdfloat t = -(a * last_point[0] + b * last_point[1] + c) / denom;
1155 LPoint2 p = last_point + t * d;
1157 new_points.push_back(
PointDef(p[0], p[1]));
1158 last_is_in = this_is_in;
1164 new_points.push_back(
PointDef(this_point[0], this_point[1]));
1169 last_point = this_point;
1182dist_to_polygon(
const LPoint2 &p,
const CollisionBox::Points &points)
const {
1192 bool got_dist =
false;
1193 PN_stdfloat best_dist = -1.0f;
1195 size_t num_points = points.size();
1196 for (
size_t i = 0; i < num_points - 1; ++i) {
1197 PN_stdfloat d = dist_to_line_segment(p, points[i]._p, points[i + 1]._p,
1200 if (!got_dist || d < best_dist) {
1207 PN_stdfloat d = dist_to_line_segment(p, points[num_points - 1]._p, points[0]._p,
1208 points[num_points - 1]._v);
1210 if (!got_dist || d < best_dist) {
1227PN_stdfloat CollisionBox::
1228dist_to_line_segment(
const LPoint2 &p,
1229 const LPoint2 &f,
const LPoint2 &t,
1230 const LVector2 &v) {
1231 LVector2 v1 = (p - f);
1232 PN_stdfloat d = (v1[0] * v[1] - v1[1] * v[0]);
1238 LPoint2 q = p + LVector2(-v[1], v[0]) * d;
1248 return (p - f).length();
1249 }
if (q[0] > t[0]) {
1250 return (p - t).length();
1257 return (p - f).length();
1258 }
if (q[1] > t[1]) {
1259 return (p - t).length();
1269 return (p - f).length();
1270 }
if (q[0] > t[0]) {
1271 return (p - t).length();
1278 return (p - f).length();
1279 }
if (q[1] < t[1]) {
1280 return (p - t).length();
1293 return (p - f).length();
1294 }
if (q[0] < t[0]) {
1295 return (p - t).length();
1302 return (p - f).length();
1303 }
if (q[1] > t[1]) {
1304 return (p - t).length();
1311 if (-v[0] > -v[1]) {
1314 return (p - f).length();
1315 }
if (q[0] < t[0]) {
1316 return (p - t).length();
1323 return (p - f).length();
1324 }
if (q[1] < t[1]) {
1325 return (p - t).length();
1339point_is_inside(
const LPoint2 &p,
const CollisionBox::Points &points)
const {
1344 for (
int i = 0; i < (int)points.size() - 1; i++) {
1345 if (is_right(p - points[i]._p, points[i+1]._p - points[i]._p)) {
1349 if (is_right(p - points[points.size() - 1]._p,
1350 points[0]._p - points[points.size() - 1]._p)) {
1363 size_t num_points = points.size();
1364 for (
size_t i = 0; i < num_points; i++) {
1365 points[i]._v = points[(i + 1) % num_points]._p - points[i]._p;
1366 points[i]._v.normalize();
1385 _center.write_datagram(me);
1386 _min.write_datagram(me);
1387 _max.write_datagram(me);
1388 for(
int i=0; i < 8; i++) {
1389 _vertex[i].write_datagram(me);
1395 for(
int i=0; i < 6; i++) {
1396 _planes[i].write_datagram(me);
1398 for(
int i=0; i < 6; i++) {
1399 _to_2d_mat[i].write_datagram(me);
1401 for(
int i=0; i < 6; i++) {
1403 for (
size_t j = 0; j < _points[i].size(); j++) {
1404 _points[i][j]._p.write_datagram(me);
1405 _points[i][j]._v.write_datagram(me);
1420 me->fillin(scan, manager);
1431 CollisionSolid::fillin(scan, manager);
1432 _center.read_datagram(scan);
1433 _min.read_datagram(scan);
1434 _max.read_datagram(scan);
1435 for(
int i=0; i < 8; i++) {
1436 _vertex[i].read_datagram(scan);
1442 for(
int i=0; i < 6; i++) {
1443 _planes[i].read_datagram(scan);
1445 for(
int i=0; i < 6; i++) {
1446 _to_2d_mat[i].read_datagram(scan);
1448 for(
int i=0; i < 6; i++) {
1450 for (
size_t j = 0; j < size; j++) {
1453 p.read_datagram(scan);
1454 v.read_datagram(scan);
1455 _points[i].push_back(
PointDef(p, v));
1459 array[0] = _vertex[plane_def[i][0]];
1460 array[1] = _vertex[plane_def[i][1]];
1461 array[2] = _vertex[plane_def[i][2]];
1462 array[3] = _vertex[plane_def[i][3]];
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void parse_params(const FactoryParams ¶ms, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
This functions similarly to a LightAttrib.
get_on_plane
Returns the nth plane enabled by the attribute, sorted in render order.
get_num_on_planes
Returns the number of planes that are enabled by the attribute.
A cuboid collision volume or object.
static void register_with_read_factory()
Factory method to generate a CollisionBox object.
PN_stdfloat dist_to_polygon(const LPoint2 &p, const Points &points) const
Returns the linear distance from the 2-d point to the nearest part of the polygon defined by the poin...
void setup_points(const LPoint3 *begin, const LPoint3 *end, int plane)
Computes the plane and 2d projection of points that make up this side.
bool apply_clip_plane(Points &new_points, const ClipPlaneAttrib *cpa, const TransformState *net_transform, int plane_no) const
Clips the polygon by all of the clip planes named in the clip plane attribute and fills new_points up...
CollisionBox(const LPoint3 ¢er, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Create the Box by giving a Center and distances of each of the sides of box from the Center.
bool clip_polygon(Points &new_points, const Points &source_points, const LPlane &plane, int plane_no) const
Clips the source_points of the polygon by the indicated clipping plane, and modifies new_points to re...
virtual void write_datagram(BamWriter *manager, Datagram &me)
Function to write the important information in the particular object to a Datagram.
virtual PointerTo< CollisionEntry > test_intersection(const CollisionEntry &entry) const
First Dispatch point for box as a FROM object.
void calc_to_3d_mat(LMatrix4 &to_3d_mat, int plane) const
Fills the indicated matrix with the appropriate rotation transform to move points from the 2-d plane ...
static void compute_vectors(Points &points)
Now that the _p members of the given points array have been computed, go back and compute all of the ...
void setup_box()
Compute parameters for each of the box's sides.
LPlane get_plane(int n) const
Returns the nth face of the rectangular solid.
virtual void xform(const LMatrix4 &mat)
Transforms the solid by the indicated matrix.
bool point_is_inside(const LPoint2 &p, const Points &points) const
Returns true if the indicated point is within the polygon's 2-d space, false otherwise.
virtual PStatCollector & get_volume_pcollector()
Returns a PStatCollector that is used to count the number of bounding volume tests made against a sol...
LPoint2 to_2d(const LVecBase3 &point3d, int plane) const
Assuming the indicated point in 3-d space lies within the polygon's plane, returns the corresponding ...
LPoint3 get_point(int n) const
Returns the nth vertex of the OBB.
virtual LPoint3 get_collision_origin() const
Returns the point in space deemed to be the "origin" of the solid for collision purposes.
virtual PStatCollector & get_test_pcollector()
Returns a PStatCollector that is used to count the number of intersection tests made against a solid ...
LPlane set_plane(int n) const
Creates the nth face of the rectangular solid.
Defines a single collision event.
get_into
Returns the CollisionSolid pointer for the particular solid was collided into.
get_from_node_path
Returns the NodePath that represents the CollisionNode that contains the CollisionSolid that triggere...
get_into_node_path
Returns the NodePath that represents the specific CollisionNode or GeomNode instance that was collide...
get_from
Returns the CollisionSolid pointer for the particular solid that triggered this collision.
The abstract base class for all things that can collide with other things in the world,...
virtual void write_datagram(BamWriter *manager, Datagram &me)
Function to write the important information in the particular object to a Datagram.
bool has_effective_normal() const
Returns true if a special normal was set by set_effective_normal(), false otherwise.
const LVector3 & get_effective_normal() const
Returns the normal that was set by set_effective_normal().
get_respect_effective_normal
See set_respect_effective_normal().
A class to retrieve the individual data elements previously stored in a Datagram.
PN_stdfloat get_stdfloat()
Extracts either a 32-bit or a 64-bit floating-point number, according to Datagram::set_stdfloat_doubl...
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
void add_stdfloat(PN_stdfloat value)
Adds either a 32-bit or a 64-bit floating-point number, according to set_stdfloat_double().
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
PandaNode * node() const
Returns the referenced node of the path.
A lightweight class that represents a single element that may be timed and/or counted via stats.
A node that contains a plane.
get_clip_effect
Returns the clip_effect bits for this clip plane.
get_plane
Returns the plane represented by the PlaneNode.
TypeHandle is the identifier used to differentiate C++ class types.
Base class for objects that can be written to and read from Bam files.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.