47 PStatCollector CollisionPolygon::_volume_pcollector(
"Collision Volumes:CollisionPolygon");
48 PStatCollector CollisionPolygon::_test_pcollector(
"Collision Tests:CollisionPolygon");
57 _points(copy._points),
58 _to_2d_mat(copy._to_2d_mat)
81 int num_points = end - begin;
90 for (pi = begin; pi != end && all_ok; ++pi) {
96 for (pj = begin; pj != pi && all_ok; ++pj) {
108 bool got_normal =
false;
109 for (
int i = 2; i < num_points && !got_normal; i++) {
110 LPlane plane(begin[0], begin[1], begin[i]);
111 LVector3 normal = plane.get_normal();
112 PN_stdfloat normal_length = normal.length();
113 got_normal = IS_THRESHOLD_EQUAL(normal_length, 1.0f, 0.001f);
130 return (_points.size() >= 3);
139 if (_points.size() < 3) {
144 LPoint2 p0 = _points[0]._p;
145 LPoint2 p1 = _points[1]._p;
146 PN_stdfloat dx1 = p1[0] - p0[0];
147 PN_stdfloat dy1 = p1[1] - p0[1];
151 PN_stdfloat dx2 = p1[0] - p0[0];
152 PN_stdfloat dy2 = p1[1] - p0[1];
153 int asum = ((dx1 * dy2 - dx2 * dy1 >= 0.0f) ? 1 : 0);
155 for (
size_t i = 0; i < _points.size() - 1; i++) {
157 p1 = _points[(i+3) % _points.size()]._p;
163 int csum = ((dx1 * dy2 - dx2 * dy1 >= 0.0f) ? 1 : 0);
179 xform(
const LMatrix4 &mat) {
184 if (collide_cat.is_spam()) {
186 <<
"CollisionPolygon transformed by:\n";
187 mat.write(collide_cat.spam(
false), 2);
188 if (_points.empty()) {
189 collide_cat.spam(
false)
194 if (!_points.empty()) {
196 rederive_to_3d_mat(to_3d_mat);
198 epvector<LPoint3> verts;
199 verts.reserve(_points.size());
200 Points::const_iterator pi;
201 for (pi = _points.begin(); pi != _points.end(); ++pi) {
202 verts.push_back(to_3d((*pi)._p, to_3d_mat) * mat);
205 const LPoint3 *verts_begin = &verts[0];
206 const LPoint3 *verts_end = verts_begin + verts.size();
207 setup_points(verts_begin, verts_end);
210 CollisionSolid::xform(mat);
221 rederive_to_3d_mat(to_3d_mat);
223 LPoint2 median = _points[0]._p;
224 for (
int n = 1; n < (int)_points.size(); n++) {
225 median += _points[n]._p;
227 median /= _points.size();
229 return to_3d(median, to_3d_mat);
239 bool bounds_only)
const {
241 if (cpa ==
nullptr) {
244 return CollisionSolid::get_viz(trav, data, bounds_only);
247 if (collide_cat.is_debug()) {
249 <<
"drawing polygon with clip plane " << *cpa <<
"\n";
258 if (apply_clip_plane(new_points, cpa, data.get_net_transform(trav))) {
260 return CollisionSolid::get_viz(trav, data, bounds_only);
263 if (new_points.empty()) {
271 draw_polygon(viz_geom_node, bounds_viz_geom_node, new_points);
274 return bounds_viz_geom_node;
276 return viz_geom_node;
286 return _volume_pcollector;
295 return _test_pcollector;
301 void CollisionPolygon::
302 output(std::ostream &out)
const {
303 out <<
"cpolygon, (" << get_plane()
304 <<
"), " << _points.size() <<
" vertices";
310 void CollisionPolygon::
311 write(std::ostream &out,
int indent_level)
const {
312 indent(out, indent_level) << (*this) <<
"\n";
313 Points::const_iterator pi;
314 for (pi = _points.begin(); pi != _points.end(); ++pi) {
315 indent(out, indent_level + 2) << (*pi)._p <<
"\n";
319 rederive_to_3d_mat(to_3d_mat);
320 out <<
"In 3-d space:\n";
321 for (pi = _points.begin(); pi != _points.end(); ++pi) {
322 LVertex vert = to_3d((*pi)._p, to_3d_mat);
323 indent(out, indent_level + 2) << vert <<
"\n";
331 compute_internal_bounds()
const {
332 if (_points.empty()) {
337 rederive_to_3d_mat(to_3d_mat);
339 Points::const_iterator pi = _points.begin();
340 LPoint3 p = to_3d((*pi)._p, to_3d_mat);
345 for (++pi; pi != _points.end(); ++pi) {
346 p = to_3d((*pi)._p, to_3d_mat);
348 n.set(min(n[0], p[0]),
351 x.set(max(x[0], p[0]),
364 test_intersection_from_sphere(
const CollisionEntry &entry)
const {
365 if (_points.size() < 3) {
370 DCAST_INTO_R(sphere, entry.
get_from(),
nullptr);
375 const LMatrix4 &wrt_mat = wrt_space->get_mat();
377 LPoint3 orig_center = sphere->get_center() * wrt_mat;
378 LPoint3 from_center = orig_center;
379 bool moved_from_center =
false;
380 PN_stdfloat t = 1.0f;
381 LPoint3 contact_point(from_center);
382 PN_stdfloat actual_t = 1.0f;
384 LVector3 from_radius_v =
385 LVector3(sphere->get_radius(), 0.0f, 0.0f) * wrt_mat;
386 PN_stdfloat from_radius_2 = from_radius_v.length_squared();
387 PN_stdfloat from_radius = csqrt(from_radius_2);
389 if (wrt_prev_space != wrt_space) {
393 LPoint3 b = from_center;
394 LPoint3 a = sphere->get_center() * wrt_prev_space->get_mat();
395 LVector3 delta = b - a;
399 PN_stdfloat dot = delta.dot(get_normal());
404 if (IS_NEARLY_ZERO(dot)) {
417 PN_stdfloat dist_to_p = dist_to_plane(a);
418 t = (dist_to_p / -dot);
422 actual_t = ((dist_to_p - from_radius) / -dot);
423 actual_t = min((PN_stdfloat)1.0, max((PN_stdfloat)0.0, actual_t));
424 contact_point = a + (actual_t * delta);
429 }
else if (t < 0.0f) {
431 moved_from_center =
true;
434 from_center = a + t * delta;
435 moved_from_center =
true;
442 if (!IS_THRESHOLD_EQUAL(normal.length_squared(), 1.0f, 0.001)) {
443 if (collide_cat.is_info()) {
446 <<
" has normal " << normal <<
" of length " << normal.length()
456 if (!get_plane().intersects_line(dist, from_center, -get_normal())) {
462 if (dist > from_radius || dist < -from_radius) {
467 LPoint2 p = to_2d(from_center - dist * get_normal());
468 PN_stdfloat edge_dist = 0.0f;
471 if (cpa !=
nullptr) {
474 if (apply_clip_plane(new_points, cpa, entry.
get_into_node_path().get_net_transform())) {
476 edge_dist = dist_to_polygon(p, _points);
478 }
else if (new_points.empty()) {
484 edge_dist = dist_to_polygon(p, new_points);
489 edge_dist = dist_to_polygon(p, _points);
495 if (edge_dist > from_radius) {
505 PN_stdfloat max_dist = from_radius;
506 if (edge_dist >= 0.0f) {
507 PN_stdfloat max_dist_2 = max(from_radius_2 - edge_dist * edge_dist, (PN_stdfloat)0.0);
508 max_dist = csqrt(max_dist_2);
511 if (dist > max_dist || -dist > max_dist) {
516 if (collide_cat.is_debug()) {
523 PN_stdfloat into_depth = max_dist - dist;
524 if (moved_from_center) {
527 PN_stdfloat orig_dist;
528 get_plane().intersects_line(orig_dist, orig_center, -normal);
529 into_depth = max_dist - orig_dist;
532 new_entry->set_surface_normal(normal);
533 new_entry->set_surface_point(from_center - normal * dist);
534 new_entry->set_interior_point(from_center - normal * (dist + into_depth));
535 new_entry->set_contact_pos(contact_point);
536 new_entry->set_contact_normal(get_normal());
537 new_entry->set_t(actual_t);
548 if (_points.size() < 3) {
553 DCAST_INTO_R(line, entry.
get_from(),
nullptr);
555 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
557 LPoint3 from_origin = line->get_origin() * wrt_mat;
558 LVector3 from_direction = line->get_direction() * wrt_mat;
561 if (!get_plane().intersects_line(t, from_origin, from_direction)) {
566 LPoint3 plane_point = from_origin + t * from_direction;
567 LPoint2 p = to_2d(plane_point);
570 if (cpa !=
nullptr) {
573 if (apply_clip_plane(new_points, cpa, entry.
get_into_node_path().get_net_transform())) {
575 if (!point_is_inside(p, _points)) {
580 if (new_points.size() < 3) {
583 if (!point_is_inside(p, new_points)) {
590 if (!point_is_inside(p, _points)) {
595 if (collide_cat.is_debug()) {
604 new_entry->set_surface_normal(normal);
605 new_entry->set_surface_point(plane_point);
616 if (_points.size() < 3) {
621 DCAST_INTO_R(ray, entry.
get_from(),
nullptr);
623 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
625 LPoint3 from_origin = ray->get_origin() * wrt_mat;
626 LVector3 from_direction = ray->get_direction() * wrt_mat;
629 if (!get_plane().intersects_line(t, from_origin, from_direction)) {
639 LPoint3 plane_point = from_origin + t * from_direction;
640 LPoint2 p = to_2d(plane_point);
643 if (cpa !=
nullptr) {
646 if (apply_clip_plane(new_points, cpa, entry.
get_into_node_path().get_net_transform())) {
648 if (!point_is_inside(p, _points)) {
653 if (new_points.size() < 3) {
656 if (!point_is_inside(p, new_points)) {
663 if (!point_is_inside(p, _points)) {
668 if (collide_cat.is_debug()) {
677 new_entry->set_surface_normal(normal);
678 new_entry->set_surface_point(plane_point);
688 test_intersection_from_segment(
const CollisionEntry &entry)
const {
689 if (_points.size() < 3) {
694 DCAST_INTO_R(segment, entry.
get_from(),
nullptr);
696 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
698 LPoint3 from_a = segment->get_point_a() * wrt_mat;
699 LPoint3 from_b = segment->get_point_b() * wrt_mat;
700 LPoint3 from_direction = from_b - from_a;
703 if (!get_plane().intersects_line(t, from_a, from_direction)) {
708 if (t < 0.0f || t > 1.0f) {
714 LPoint3 plane_point = from_a + t * from_direction;
715 LPoint2 p = to_2d(plane_point);
718 if (cpa !=
nullptr) {
721 if (apply_clip_plane(new_points, cpa, entry.
get_into_node_path().get_net_transform())) {
723 if (!point_is_inside(p, _points)) {
728 if (new_points.size() < 3) {
731 if (!point_is_inside(p, new_points)) {
738 if (!point_is_inside(p, _points)) {
743 if (collide_cat.is_debug()) {
752 new_entry->set_surface_normal(normal);
753 new_entry->set_surface_point(plane_point);
763 test_intersection_from_parabola(
const CollisionEntry &entry)
const {
764 if (_points.size() < 3) {
769 DCAST_INTO_R(parabola, entry.
get_from(),
nullptr);
771 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
775 local_p.xform(wrt_mat);
778 if (!get_plane().intersects_parabola(t1, t2, local_p)) {
784 if (t1 >= parabola->
get_t1() && t1 <= parabola->get_t2()) {
785 if (t2 >= parabola->
get_t1() && t2 <= parabola->get_t2()) {
794 }
else if (t2 >= parabola->
get_t1() && t2 <= parabola->get_t2()) {
803 LPoint3 plane_point = local_p.calc_point(t);
804 LPoint2 p = to_2d(plane_point);
807 if (cpa !=
nullptr) {
810 if (apply_clip_plane(new_points, cpa, entry.
get_into_node_path().get_net_transform())) {
812 if (!point_is_inside(p, _points)) {
817 if (new_points.size() < 3) {
820 if (!point_is_inside(p, new_points)) {
827 if (!point_is_inside(p, _points)) {
832 if (collide_cat.is_debug()) {
841 new_entry->set_surface_normal(normal);
842 new_entry->set_surface_point(plane_point);
854 DCAST_INTO_R(box, entry.
get_from(),
nullptr);
858 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
859 LMatrix4 plane_mat = wrt_mat * _to_2d_mat;
861 LPoint3 from_center = box->get_center() * plane_mat;
862 LVector3 from_extents = box->get_dimensions() * 0.5f;
865 LVecBase3 box_x = plane_mat.get_row3(0) * from_extents[0];
866 LVecBase3 box_y = plane_mat.get_row3(1) * from_extents[1];
867 LVecBase3 box_z = plane_mat.get_row3(2) * from_extents[2];
870 if (cabs(from_center[1]) > cabs(box_x[1]) + cabs(box_y[1]) + cabs(box_z[1])) {
876 PN_stdfloat r1, center, r2;
878 r1 = cabs(box_x.dot(box_x)) + cabs(box_y.dot(box_x)) + cabs(box_z.dot(box_x));
879 project(box_x, center, r2);
880 if (cabs(from_center.dot(box_x) - center) > r1 + r2) {
884 r1 = cabs(box_x.dot(box_y)) + cabs(box_y.dot(box_y)) + cabs(box_z.dot(box_y));
885 project(box_y, center, r2);
886 if (cabs(from_center.dot(box_y) - center) > r1 + r2) {
890 r1 = cabs(box_x.dot(box_z)) + cabs(box_y.dot(box_z)) + cabs(box_z.dot(box_z));
891 project(box_z, center, r2);
892 if (cabs(from_center.dot(box_z) - center) > r1 + r2) {
898 Points::const_iterator pi;
899 for (pi = _points.begin(); pi != _points.end(); ++pi) {
900 const PointDef &pd = *pi;
903 axis.set(-box_x[1] * pd._v[1],
904 box_x[0] * pd._v[1] - box_x[2] * pd._v[0],
905 box_x[1] * pd._v[0]);
906 r1 = cabs(box_x.dot(axis)) + cabs(box_y.dot(axis)) + cabs(box_z.dot(axis));
907 project(axis, center, r2);
908 if (cabs(from_center.dot(axis) - center) > r1 + r2) {
912 axis.set(-box_y[1] * pd._v[1],
913 box_y[0] * pd._v[1] - box_y[2] * pd._v[0],
914 box_y[1] * pd._v[0]);
915 r1 = cabs(box_x.dot(axis)) + cabs(box_y.dot(axis)) + cabs(box_z.dot(axis));
916 project(axis, center, r2);
917 if (cabs(from_center.dot(axis) - center) > r1 + r2) {
921 axis.set(-box_z[1] * pd._v[1],
922 box_z[0] * pd._v[1] - box_z[2] * pd._v[0],
923 box_z[1] * pd._v[0]);
924 r1 = cabs(box_x.dot(axis)) + cabs(box_y.dot(axis)) + cabs(box_z.dot(axis));
925 project(axis, center, r2);
926 if (cabs(from_center.dot(axis) - center) > r1 + r2) {
931 if (collide_cat.is_debug()) {
939 new_entry->set_surface_normal(normal);
944 LPoint3 interior_point = box->get_center() * wrt_mat +
945 wrt_mat.get_row3(0) * from_extents[0] * ((box_x[1] > 0) - (box_x[1] < 0)) +
946 wrt_mat.get_row3(1) * from_extents[1] * ((box_y[1] > 0) - (box_y[1] < 0)) +
947 wrt_mat.get_row3(2) * from_extents[2] * ((box_z[1] > 0) - (box_z[1] < 0));
950 new_entry->set_surface_point(get_plane().project(interior_point));
951 new_entry->set_interior_point(interior_point);
960 void CollisionPolygon::
962 if (collide_cat.is_debug()) {
964 <<
"Recomputing viz for " << *
this <<
"\n";
966 nassertv(_viz_geom !=
nullptr && _bounds_viz_geom !=
nullptr);
967 draw_polygon(_viz_geom, _bounds_viz_geom, _points);
978 PN_stdfloat CollisionPolygon::
979 dist_to_line_segment(
const LPoint2 &p,
980 const LPoint2 &f,
const LPoint2 &t,
982 LVector2 v1 = (p - f);
983 PN_stdfloat d = (v1[0] * v[1] - v1[1] * v[0]);
989 LPoint2 q = p + LVector2(-v[1], v[0]) * d;
999 return (p - f).length();
1000 }
if (q[0] > t[0]) {
1001 return (p - t).length();
1008 return (p - f).length();
1009 }
if (q[1] > t[1]) {
1010 return (p - t).length();
1020 return (p - f).length();
1021 }
if (q[0] > t[0]) {
1022 return (p - t).length();
1029 return (p - f).length();
1030 }
if (q[1] < t[1]) {
1031 return (p - t).length();
1044 return (p - f).length();
1045 }
if (q[0] < t[0]) {
1046 return (p - t).length();
1053 return (p - f).length();
1054 }
if (q[1] > t[1]) {
1055 return (p - t).length();
1062 if (-v[0] > -v[1]) {
1065 return (p - f).length();
1066 }
if (q[0] < t[0]) {
1067 return (p - t).length();
1074 return (p - f).length();
1075 }
if (q[1] < t[1]) {
1076 return (p - t).length();
1090 void CollisionPolygon::
1091 compute_vectors(Points &points) {
1092 size_t num_points = points.size();
1093 for (
size_t i = 0; i < num_points; i++) {
1094 points[i]._v = points[(i + 1) % num_points]._p - points[i]._p;
1095 points[i]._v.normalize();
1103 void CollisionPolygon::
1106 if (points.size() < 3) {
1107 if (collide_cat.is_debug()) {
1109 <<
"(Degenerate poly, ignoring.)\n";
1115 rederive_to_3d_mat(to_3d_mat);
1122 Points::const_iterator pi;
1123 for (pi = points.begin(); pi != points.end(); ++pi) {
1124 vertex.add_data3(to_3d((*pi)._p, to_3d_mat));
1128 body->add_consecutive_vertices(0, points.size());
1129 body->close_primitive();
1132 border->add_consecutive_vertices(0, points.size());
1133 border->add_vertex(0);
1134 border->close_primitive();
1137 geom1->add_primitive(body);
1140 geom2->add_primitive(border);
1154 bool CollisionPolygon::
1161 for (
int i = 0; i < (int)points.size() - 1; i++) {
1162 if (is_right(p - points[i]._p, points[i+1]._p - points[i]._p)) {
1166 if (is_right(p - points[points.size() - 1]._p,
1167 points[0]._p - points[points.size() - 1]._p)) {
1179 PN_stdfloat CollisionPolygon::
1190 bool got_dist =
false;
1191 PN_stdfloat best_dist = -1.0f;
1193 size_t num_points = points.size();
1194 for (
size_t i = 0; i < num_points - 1; ++i) {
1195 PN_stdfloat d = dist_to_line_segment(p, points[i]._p, points[i + 1]._p,
1198 if (!got_dist || d < best_dist) {
1205 PN_stdfloat d = dist_to_line_segment(p, points[num_points - 1]._p, points[0]._p,
1206 points[num_points - 1]._v);
1208 if (!got_dist || d < best_dist) {
1221 void CollisionPolygon::
1222 project(
const LVector3 &axis, PN_stdfloat ¢er, PN_stdfloat &extent)
const {
1223 PN_stdfloat begin, end;
1225 Points::const_iterator pi;
1226 pi = _points.begin();
1228 const LPoint2 &point = (*pi)._p;
1229 begin = point[0] * axis[0] + point[1] * axis[2];
1232 for (; pi != _points.end(); ++pi) {
1233 const LPoint2 &point = (*pi)._p;
1235 PN_stdfloat t = point[0] * axis[0] + point[1] * axis[2];
1236 begin = min(begin, t);
1240 center = (end + begin) * 0.5f;
1241 extent = cabs((end - begin) * 0.5f);
1247 void CollisionPolygon::
1248 setup_points(
const LPoint3 *begin,
const LPoint3 *end) {
1249 int num_points = end - begin;
1250 nassertv(num_points >= 3);
1256 LVector3 normal = LVector3::zero();
1262 for (
int i = 0; i < num_points; i++) {
1263 const LPoint3 &p0 = begin[i];
1264 const LPoint3 &p1 = begin[(i + 1) % num_points];
1265 normal[0] += p0[1] * p1[2] - p0[2] * p1[1];
1266 normal[1] += p0[2] * p1[0] - p0[0] * p1[2];
1267 normal[2] += p0[0] * p1[1] - p0[1] * p1[0];
1270 if (normal.length_squared() == 0.0f) {
1279 collide_cat.error() <<
"Invalid points in CollisionPolygon:\n";
1281 for (pi = begin; pi != end; ++pi) {
1282 collide_cat.error(
false) <<
" " << (*pi) <<
"\n";
1284 collide_cat.error(
false)
1285 <<
" normal " << normal <<
" with length " << normal.length() <<
"\n";
1291 if (collide_cat.is_spam()) {
1293 <<
"CollisionPolygon defined with " << num_points <<
" vertices:\n";
1295 for (pi = begin; pi != end; ++pi) {
1296 collide_cat.spam(
false) <<
" " << (*pi) <<
"\n";
1301 set_plane(LPlane(normal, begin[0]));
1306 calc_to_3d_mat(to_3d_mat);
1309 _to_2d_mat.invert_from(to_3d_mat);
1314 for (pi = begin; pi != end; ++pi) {
1315 LPoint3 point = (*pi) * _to_2d_mat;
1316 _points.push_back(PointDef(point[0], point[2]));
1319 nassertv(_points.size() >= 3);
1337 compute_vectors(_points);
1344 LPoint3 CollisionPolygon::
1345 legacy_to_3d(
const LVecBase2 &point2d,
int axis)
const {
1346 nassertr(!point2d.is_nan(), LPoint3(0.0f, 0.0f, 0.0f));
1348 LVector3 normal = get_normal();
1349 PN_stdfloat D = get_plane()[3];
1351 nassertr(!normal.is_nan(), LPoint3(0.0f, 0.0f, 0.0f));
1352 nassertr(!cnan(D), LPoint3(0.0f, 0.0f, 0.0f));
1356 return LPoint3(-(normal[1]*point2d[0] + normal[2]*point2d[1] + D)/normal[0], point2d[0], point2d[1]);
1359 return LPoint3(point2d[0],
1360 -(normal[0]*point2d[0] + normal[2]*point2d[1] + D)/normal[1], point2d[1]);
1363 return LPoint3(point2d[0], point2d[1],
1364 -(normal[0]*point2d[0] + normal[1]*point2d[1] + D)/normal[2]);
1367 nassertr(
false, LPoint3(0.0f, 0.0f, 0.0f));
1368 return LPoint3(0.0f, 0.0f, 0.0f);
1379 bool CollisionPolygon::
1382 const LPlane &plane)
const {
1384 if (source_points.empty()) {
1390 if (!plane.intersects_plane(from3d, delta3d, get_plane())) {
1393 if (plane.dist_to_plane(get_plane().
get_point()) < 0.0) {
1396 new_points = source_points;
1404 LPoint2 from2d = to_2d(from3d);
1405 LVector2 delta2d = to_2d(delta3d);
1407 PN_stdfloat a = -delta2d[1];
1408 PN_stdfloat b = delta2d[0];
1409 PN_stdfloat c = from2d[0] * delta2d[1] - from2d[1] * delta2d[0];
1417 new_points.reserve(source_points.size() + 1);
1419 LPoint2 last_point = source_points.back()._p;
1420 bool last_is_in = !is_right(last_point - from2d, delta2d);
1421 bool all_in = last_is_in;
1422 Points::const_iterator pi;
1423 for (pi = source_points.begin(); pi != source_points.end(); ++pi) {
1424 const LPoint2 &this_point = (*pi)._p;
1425 bool this_is_in = !is_right(this_point - from2d, delta2d);
1429 bool crossed_over = (this_is_in != last_is_in);
1433 LVector2 d = this_point - last_point;
1434 PN_stdfloat denom = (a * d[0] + b * d[1]);
1436 PN_stdfloat t = -(a * last_point[0] + b * last_point[1] + c) / denom;
1437 LPoint2 p = last_point + t * d;
1439 new_points.push_back(PointDef(p[0], p[1]));
1440 last_is_in = this_is_in;
1446 new_points.push_back(PointDef(this_point[0], this_point[1]));
1451 last_point = this_point;
1464 bool CollisionPolygon::
1471 bool first_plane =
true;
1473 for (
int i = 0; i < num_planes; i++) {
1478 net_transform->invert_compose(plane_path.get_net_transform());
1480 LPlane plane = plane_node->
get_plane() * new_transform->get_mat();
1482 first_plane =
false;
1483 if (!clip_polygon(new_points, _points, plane)) {
1488 last_points.swap(new_points);
1489 if (!clip_polygon(new_points, last_points, plane)) {
1497 compute_vectors(new_points);
1511 for (
size_t i = 0; i < _points.size(); i++) {
1512 _points[i]._p.write_datagram(me);
1513 _points[i]._v.write_datagram(me);
1515 _to_2d_mat.write_datagram(me);
1523 void CollisionPolygon::
1525 CollisionPlane::fillin(scan, manager);
1528 for (
size_t i = 0; i < size; i++) {
1531 p.read_datagram(scan);
1532 v.read_datagram(scan);
1533 _points.push_back(PointDef(p, v));
1535 _to_2d_mat.read_datagram(scan);
1541 if (_points.size() >= 3) {
1543 rederive_to_3d_mat(to_3d_mat);
1545 epvector<LPoint3> verts;
1546 verts.reserve(_points.size());
1547 Points::const_iterator pi;
1548 for (pi = _points.begin(); pi != _points.end(); ++pi) {
1549 verts.push_back(to_3d((*pi)._p, to_3d_mat));
1552 const LPoint3 *verts_begin = &verts[0];
1553 const LPoint3 *verts_end = verts_begin + verts.size();
1554 setup_points(verts_begin, verts_end);
1570 me->fillin(scan, manager);
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...
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
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 ...
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
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.
Defines a single collision event.
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.
An infinite line, similar to a CollisionRay, except that it extends in both directions.
This defines a parabolic arc, or subset of an arc, similar to the path of a projectile or falling obj...
get_t1
Returns the starting point on the parabola.
get_parabola
Returns the parabola specified by this solid.
virtual void write_datagram(BamWriter *manager, Datagram &me)
Function to write the important information in the particular object to a Datagram.
static bool verify_points(const LPoint3 *begin, const LPoint3 *end)
Verifies that the indicated set of points will define a valid CollisionPolygon: that is,...
get_point
Returns the nth vertex of the CollisionPolygon, expressed in 3-D space.
virtual void write_datagram(BamWriter *manager, Datagram &me)
Function to write the important information in the particular object to a Datagram.
virtual LPoint3 get_collision_origin() const
Returns the point in space deemed to be the "origin" of the solid for collision purposes.
is_concave
Returns true if the CollisionPolygon appears to be concave, or false if it is safely convex.
virtual PStatCollector & get_test_pcollector()
Returns a PStatCollector that is used to count the number of intersection tests made against a solid ...
static void register_with_read_factory()
Factory method to generate a CollisionPolygon object.
virtual void xform(const LMatrix4 &mat)
Transforms the solid by the indicated matrix.
static TypedWritable * make_CollisionPolygon(const FactoryParams ¶ms)
Factory method to generate a CollisionPolygon object.
virtual PStatCollector & get_volume_pcollector()
Returns a PStatCollector that is used to count the number of bounding volume tests made against a sol...
is_valid
Returns true if the CollisionPolygon is valid (that is, it has at least three vertices),...
An infinite ray, with a specific origin and direction.
A finite line segment, with two specific endpoints but no thickness.
The abstract base class for all things that can collide with other things in the world,...
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 spherical collision volume or object.
This collects together the pieces of data that are accumulated for each node while walking the scene ...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
A class to retrieve the individual data elements previously stored in a Datagram.
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_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.
Defines a series of line strips.
A node that holds Geom objects, renderable pieces of geometry.
void add_geom(Geom *geom, const RenderState *state=RenderState::make_empty())
Adds a new Geom to the node.
Defines a series of triangle fans.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
A container for geometry primitives.
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 basic node of the scene graph or data graph.
A node that contains a plane.
const LPlane & get_plane() const
Returns the plane represented by the PlaneNode.
int get_clip_effect() const
Returns the clip_effect bits for this clip plane.
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.
PT(PandaNode) CollisionPolygon
Returns a GeomNode that may be rendered to visualize the CollisionSolid.
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.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.