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);
128 bool CollisionPolygon::
130 return (_points.size() >= 3);
137 bool CollisionPolygon::
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);
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)) {
445 <<
" has normal " << normal <<
" of length " << normal.length()
454 if (!get_plane().intersects_line(dist, from_center, -get_normal())) {
460 if (dist > from_radius || dist < -from_radius) {
465 LPoint2 p = to_2d(from_center - dist * get_normal());
466 PN_stdfloat edge_dist = 0.0f;
469 if (cpa !=
nullptr) {
472 if (apply_clip_plane(new_points, cpa, entry.
get_into_node_path().get_net_transform())) {
474 edge_dist = dist_to_polygon(p, _points);
476 }
else if (new_points.empty()) {
482 edge_dist = dist_to_polygon(p, new_points);
487 edge_dist = dist_to_polygon(p, _points);
493 if (edge_dist > from_radius) {
503 PN_stdfloat max_dist = from_radius;
504 if (edge_dist >= 0.0f) {
505 PN_stdfloat max_dist_2 = max(from_radius_2 - edge_dist * edge_dist, (PN_stdfloat)0.0);
506 max_dist = csqrt(max_dist_2);
509 if (dist > max_dist) {
514 if (collide_cat.is_debug()) {
521 PN_stdfloat into_depth = max_dist - dist;
522 if (moved_from_center) {
525 PN_stdfloat orig_dist;
526 get_plane().intersects_line(orig_dist, orig_center, -normal);
527 into_depth = max_dist - orig_dist;
530 new_entry->set_surface_normal(normal);
531 new_entry->set_surface_point(from_center - normal * dist);
532 new_entry->set_interior_point(from_center - normal * (dist + into_depth));
533 new_entry->set_contact_pos(contact_point);
534 new_entry->set_contact_normal(get_normal());
535 new_entry->set_t(actual_t);
546 if (_points.size() < 3) {
551 DCAST_INTO_R(line, entry.
get_from(),
nullptr);
553 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
555 LPoint3 from_origin = line->get_origin() * wrt_mat;
556 LVector3 from_direction = line->get_direction() * wrt_mat;
559 if (!get_plane().intersects_line(t, from_origin, from_direction)) {
564 LPoint3 plane_point = from_origin + t * from_direction;
565 LPoint2 p = to_2d(plane_point);
568 if (cpa !=
nullptr) {
571 if (apply_clip_plane(new_points, cpa, entry.
get_into_node_path().get_net_transform())) {
573 if (!point_is_inside(p, _points)) {
578 if (new_points.size() < 3) {
581 if (!point_is_inside(p, new_points)) {
588 if (!point_is_inside(p, _points)) {
593 if (collide_cat.is_debug()) {
602 new_entry->set_surface_normal(normal);
603 new_entry->set_surface_point(plane_point);
614 if (_points.size() < 3) {
619 DCAST_INTO_R(ray, entry.
get_from(),
nullptr);
621 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
623 LPoint3 from_origin = ray->get_origin() * wrt_mat;
624 LVector3 from_direction = ray->get_direction() * wrt_mat;
627 if (!get_plane().intersects_line(t, from_origin, from_direction)) {
637 LPoint3 plane_point = from_origin + t * from_direction;
638 LPoint2 p = to_2d(plane_point);
641 if (cpa !=
nullptr) {
644 if (apply_clip_plane(new_points, cpa, entry.
get_into_node_path().get_net_transform())) {
646 if (!point_is_inside(p, _points)) {
651 if (new_points.size() < 3) {
654 if (!point_is_inside(p, new_points)) {
661 if (!point_is_inside(p, _points)) {
666 if (collide_cat.is_debug()) {
675 new_entry->set_surface_normal(normal);
676 new_entry->set_surface_point(plane_point);
686 test_intersection_from_segment(
const CollisionEntry &entry)
const {
687 if (_points.size() < 3) {
692 DCAST_INTO_R(segment, entry.
get_from(),
nullptr);
694 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
696 LPoint3 from_a = segment->get_point_a() * wrt_mat;
697 LPoint3 from_b = segment->get_point_b() * wrt_mat;
698 LPoint3 from_direction = from_b - from_a;
701 if (!get_plane().intersects_line(t, from_a, from_direction)) {
706 if (t < 0.0f || t > 1.0f) {
712 LPoint3 plane_point = from_a + t * from_direction;
713 LPoint2 p = to_2d(plane_point);
716 if (cpa !=
nullptr) {
719 if (apply_clip_plane(new_points, cpa, entry.
get_into_node_path().get_net_transform())) {
721 if (!point_is_inside(p, _points)) {
726 if (new_points.size() < 3) {
729 if (!point_is_inside(p, new_points)) {
736 if (!point_is_inside(p, _points)) {
741 if (collide_cat.is_debug()) {
750 new_entry->set_surface_normal(normal);
751 new_entry->set_surface_point(plane_point);
761 test_intersection_from_parabola(
const CollisionEntry &entry)
const {
762 if (_points.size() < 3) {
767 DCAST_INTO_R(parabola, entry.
get_from(),
nullptr);
769 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
773 local_p.xform(wrt_mat);
776 if (!get_plane().intersects_parabola(t1, t2, local_p)) {
782 if (t1 >= parabola->
get_t1() && t1 <= parabola->
get_t2()) {
783 if (t2 >= parabola->
get_t1() && t2 <= parabola->
get_t2()) {
792 }
else if (t2 >= parabola->
get_t1() && t2 <= parabola->
get_t2()) {
801 LPoint3 plane_point = local_p.calc_point(t);
802 LPoint2 p = to_2d(plane_point);
805 if (cpa !=
nullptr) {
808 if (apply_clip_plane(new_points, cpa, entry.
get_into_node_path().get_net_transform())) {
810 if (!point_is_inside(p, _points)) {
815 if (new_points.size() < 3) {
818 if (!point_is_inside(p, new_points)) {
825 if (!point_is_inside(p, _points)) {
830 if (collide_cat.is_debug()) {
839 new_entry->set_surface_normal(normal);
840 new_entry->set_surface_point(plane_point);
852 DCAST_INTO_R(box, entry.
get_from(),
nullptr);
856 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
857 LMatrix4 plane_mat = wrt_mat * _to_2d_mat;
859 LPoint3 from_center = box->get_center() * plane_mat;
860 LVector3 from_extents = box->get_dimensions() * 0.5f;
863 LVecBase3 box_x = plane_mat.get_row3(0) * from_extents[0];
864 LVecBase3 box_y = plane_mat.get_row3(1) * from_extents[1];
865 LVecBase3 box_z = plane_mat.get_row3(2) * from_extents[2];
868 if (cabs(from_center[1]) > cabs(box_x[1]) + cabs(box_y[1]) + cabs(box_z[1])) {
874 PN_stdfloat r1, center, r2;
876 r1 = cabs(box_x.dot(box_x)) + cabs(box_y.dot(box_x)) + cabs(box_z.dot(box_x));
877 project(box_x, center, r2);
878 if (cabs(from_center.dot(box_x) - center) > r1 + r2) {
882 r1 = cabs(box_x.dot(box_y)) + cabs(box_y.dot(box_y)) + cabs(box_z.dot(box_y));
883 project(box_y, center, r2);
884 if (cabs(from_center.dot(box_y) - center) > r1 + r2) {
888 r1 = cabs(box_x.dot(box_z)) + cabs(box_y.dot(box_z)) + cabs(box_z.dot(box_z));
889 project(box_z, center, r2);
890 if (cabs(from_center.dot(box_z) - center) > r1 + r2) {
896 Points::const_iterator pi;
897 for (pi = _points.begin(); pi != _points.end(); ++pi) {
898 const PointDef &pd = *pi;
901 axis.set(-box_x[1] * pd._v[1],
902 box_x[0] * pd._v[1] - box_x[2] * pd._v[0],
903 box_x[1] * pd._v[0]);
904 r1 = cabs(box_x.dot(axis)) + cabs(box_y.dot(axis)) + cabs(box_z.dot(axis));
905 project(axis, center, r2);
906 if (cabs(from_center.dot(axis) - center) > r1 + r2) {
910 axis.set(-box_y[1] * pd._v[1],
911 box_y[0] * pd._v[1] - box_y[2] * pd._v[0],
912 box_y[1] * pd._v[0]);
913 r1 = cabs(box_x.dot(axis)) + cabs(box_y.dot(axis)) + cabs(box_z.dot(axis));
914 project(axis, center, r2);
915 if (cabs(from_center.dot(axis) - center) > r1 + r2) {
919 axis.set(-box_z[1] * pd._v[1],
920 box_z[0] * pd._v[1] - box_z[2] * pd._v[0],
921 box_z[1] * pd._v[0]);
922 r1 = cabs(box_x.dot(axis)) + cabs(box_y.dot(axis)) + cabs(box_z.dot(axis));
923 project(axis, center, r2);
924 if (cabs(from_center.dot(axis) - center) > r1 + r2) {
929 if (collide_cat.is_debug()) {
937 new_entry->set_surface_normal(normal);
942 LPoint3 interior_point = box->get_center() * wrt_mat +
943 wrt_mat.get_row3(0) * from_extents[0] * ((box_x[1] > 0) - (box_x[1] < 0)) +
944 wrt_mat.get_row3(1) * from_extents[1] * ((box_y[1] > 0) - (box_y[1] < 0)) +
945 wrt_mat.get_row3(2) * from_extents[2] * ((box_z[1] > 0) - (box_z[1] < 0));
948 new_entry->set_surface_point(get_plane().project(interior_point));
949 new_entry->set_interior_point(interior_point);
958 void CollisionPolygon::
960 if (collide_cat.is_debug()) {
962 <<
"Recomputing viz for " << *
this <<
"\n";
964 nassertv(_viz_geom !=
nullptr && _bounds_viz_geom !=
nullptr);
965 draw_polygon(_viz_geom, _bounds_viz_geom, _points);
976 PN_stdfloat CollisionPolygon::
977 dist_to_line_segment(
const LPoint2 &p,
978 const LPoint2 &f,
const LPoint2 &t,
980 LVector2 v1 = (p - f);
981 PN_stdfloat d = (v1[0] * v[1] - v1[1] * v[0]);
987 LPoint2 q = p + LVector2(-v[1], v[0]) * d;
997 return (p - f).length();
999 return (p - t).length();
1006 return (p - f).length();
1007 }
if (q[1] > t[1]) {
1008 return (p - t).length();
1018 return (p - f).length();
1019 }
if (q[0] > t[0]) {
1020 return (p - t).length();
1027 return (p - f).length();
1028 }
if (q[1] < t[1]) {
1029 return (p - t).length();
1042 return (p - f).length();
1043 }
if (q[0] < t[0]) {
1044 return (p - t).length();
1051 return (p - f).length();
1052 }
if (q[1] > t[1]) {
1053 return (p - t).length();
1060 if (-v[0] > -v[1]) {
1063 return (p - f).length();
1064 }
if (q[0] < t[0]) {
1065 return (p - t).length();
1072 return (p - f).length();
1073 }
if (q[1] < t[1]) {
1074 return (p - t).length();
1088 void CollisionPolygon::
1089 compute_vectors(Points &points) {
1090 size_t num_points = points.size();
1091 for (
size_t i = 0; i < num_points; i++) {
1092 points[i]._v = points[(i + 1) % num_points]._p - points[i]._p;
1093 points[i]._v.normalize();
1101 void CollisionPolygon::
1104 if (points.size() < 3) {
1105 if (collide_cat.is_debug()) {
1107 <<
"(Degenerate poly, ignoring.)\n";
1113 rederive_to_3d_mat(to_3d_mat);
1120 Points::const_iterator pi;
1121 for (pi = points.begin(); pi != points.end(); ++pi) {
1122 vertex.add_data3(to_3d((*pi)._p, to_3d_mat));
1126 body->add_consecutive_vertices(0, points.size());
1127 body->close_primitive();
1130 border->add_consecutive_vertices(0, points.size());
1131 border->add_vertex(0);
1132 border->close_primitive();
1135 geom1->add_primitive(body);
1138 geom2->add_primitive(border);
1152 bool CollisionPolygon::
1159 for (
int i = 0; i < (int)points.size() - 1; i++) {
1160 if (is_right(p - points[i]._p, points[i+1]._p - points[i]._p)) {
1164 if (is_right(p - points[points.size() - 1]._p,
1165 points[0]._p - points[points.size() - 1]._p)) {
1177 PN_stdfloat CollisionPolygon::
1188 bool got_dist =
false;
1189 PN_stdfloat best_dist = -1.0f;
1191 size_t num_points = points.size();
1192 for (
size_t i = 0; i < num_points - 1; ++i) {
1193 PN_stdfloat d = dist_to_line_segment(p, points[i]._p, points[i + 1]._p,
1196 if (!got_dist || d < best_dist) {
1203 PN_stdfloat d = dist_to_line_segment(p, points[num_points - 1]._p, points[0]._p,
1204 points[num_points - 1]._v);
1206 if (!got_dist || d < best_dist) {
1219 void CollisionPolygon::
1220 project(
const LVector3 &axis, PN_stdfloat ¢er, PN_stdfloat &extent)
const {
1221 PN_stdfloat begin, end;
1223 Points::const_iterator pi;
1224 pi = _points.begin();
1226 const LPoint2 &point = (*pi)._p;
1227 begin = point[0] * axis[0] + point[1] * axis[2];
1230 for (; pi != _points.end(); ++pi) {
1231 const LPoint2 &point = (*pi)._p;
1233 PN_stdfloat t = point[0] * axis[0] + point[1] * axis[2];
1234 begin = min(begin, t);
1238 center = (end + begin) * 0.5f;
1239 extent = cabs((end - begin) * 0.5f);
1245 void CollisionPolygon::
1246 setup_points(
const LPoint3 *begin,
const LPoint3 *end) {
1247 int num_points = end - begin;
1248 nassertv(num_points >= 3);
1254 LVector3 normal = LVector3::zero();
1260 for (
int i = 0; i < num_points; i++) {
1261 const LPoint3 &p0 = begin[i];
1262 const LPoint3 &p1 = begin[(i + 1) % num_points];
1263 normal[0] += p0[1] * p1[2] - p0[2] * p1[1];
1264 normal[1] += p0[2] * p1[0] - p0[0] * p1[2];
1265 normal[2] += p0[0] * p1[1] - p0[1] * p1[0];
1268 if (normal.length_squared() == 0.0f) {
1277 collide_cat.error() <<
"Invalid points in CollisionPolygon:\n";
1279 for (pi = begin; pi != end; ++pi) {
1280 collide_cat.error(
false) <<
" " << (*pi) <<
"\n";
1282 collide_cat.error(
false)
1283 <<
" normal " << normal <<
" with length " << normal.length() <<
"\n";
1289 if (collide_cat.is_spam()) {
1291 <<
"CollisionPolygon defined with " << num_points <<
" vertices:\n";
1293 for (pi = begin; pi != end; ++pi) {
1294 collide_cat.spam(
false) <<
" " << (*pi) <<
"\n";
1299 set_plane(LPlane(normal, begin[0]));
1304 calc_to_3d_mat(to_3d_mat);
1307 _to_2d_mat.invert_from(to_3d_mat);
1312 for (pi = begin; pi != end; ++pi) {
1313 LPoint3 point = (*pi) * _to_2d_mat;
1314 _points.push_back(PointDef(point[0], point[2]));
1317 nassertv(_points.size() >= 3);
1335 compute_vectors(_points);
1342 LPoint3 CollisionPolygon::
1343 legacy_to_3d(
const LVecBase2 &point2d,
int axis)
const {
1344 nassertr(!point2d.is_nan(), LPoint3(0.0f, 0.0f, 0.0f));
1346 LVector3 normal = get_normal();
1347 PN_stdfloat D = get_plane()[3];
1349 nassertr(!normal.is_nan(), LPoint3(0.0f, 0.0f, 0.0f));
1350 nassertr(!cnan(D), LPoint3(0.0f, 0.0f, 0.0f));
1354 return LPoint3(-(normal[1]*point2d[0] + normal[2]*point2d[1] + D)/normal[0], point2d[0], point2d[1]);
1357 return LPoint3(point2d[0],
1358 -(normal[0]*point2d[0] + normal[2]*point2d[1] + D)/normal[1], point2d[1]);
1361 return LPoint3(point2d[0], point2d[1],
1362 -(normal[0]*point2d[0] + normal[1]*point2d[1] + D)/normal[2]);
1365 nassertr(
false, LPoint3(0.0f, 0.0f, 0.0f));
1366 return LPoint3(0.0f, 0.0f, 0.0f);
1377 bool CollisionPolygon::
1380 const LPlane &plane)
const {
1382 if (source_points.empty()) {
1388 if (!plane.intersects_plane(from3d, delta3d, get_plane())) {
1391 if (plane.dist_to_plane(get_plane().
get_point()) < 0.0) {
1394 new_points = source_points;
1402 LPoint2 from2d = to_2d(from3d);
1403 LVector2 delta2d = to_2d(delta3d);
1405 PN_stdfloat a = -delta2d[1];
1406 PN_stdfloat b = delta2d[0];
1407 PN_stdfloat c = from2d[0] * delta2d[1] - from2d[1] * delta2d[0];
1415 new_points.reserve(source_points.size() + 1);
1417 LPoint2 last_point = source_points.back()._p;
1418 bool last_is_in = !is_right(last_point - from2d, delta2d);
1419 bool all_in = last_is_in;
1420 Points::const_iterator pi;
1421 for (pi = source_points.begin(); pi != source_points.end(); ++pi) {
1422 const LPoint2 &this_point = (*pi)._p;
1423 bool this_is_in = !is_right(this_point - from2d, delta2d);
1427 bool crossed_over = (this_is_in != last_is_in);
1431 LVector2 d = this_point - last_point;
1432 PN_stdfloat denom = (a * d[0] + b * d[1]);
1434 PN_stdfloat t = -(a * last_point[0] + b * last_point[1] + c) / denom;
1435 LPoint2 p = last_point + t * d;
1437 new_points.push_back(PointDef(p[0], p[1]));
1438 last_is_in = this_is_in;
1444 new_points.push_back(PointDef(this_point[0], this_point[1]));
1449 last_point = this_point;
1462 bool CollisionPolygon::
1469 bool first_plane =
true;
1471 for (
int i = 0; i < num_planes; i++) {
1476 net_transform->invert_compose(plane_path.get_net_transform());
1478 LPlane plane = plane_node->
get_plane() * new_transform->get_mat();
1480 first_plane =
false;
1481 if (!clip_polygon(new_points, _points, plane)) {
1486 last_points.swap(new_points);
1487 if (!clip_polygon(new_points, last_points, plane)) {
1495 compute_vectors(new_points);
1509 for (
size_t i = 0; i < _points.size(); i++) {
1510 _points[i]._p.write_datagram(me);
1511 _points[i]._v.write_datagram(me);
1513 _to_2d_mat.write_datagram(me);
1521 void CollisionPolygon::
1523 CollisionPlane::fillin(scan, manager);
1526 for (
size_t i = 0; i < size; i++) {
1529 p.read_datagram(scan);
1530 v.read_datagram(scan);
1531 _points.push_back(PointDef(p, v));
1533 _to_2d_mat.read_datagram(scan);
1539 if (_points.size() >= 3) {
1541 rederive_to_3d_mat(to_3d_mat);
1543 epvector<LPoint3> verts;
1544 verts.reserve(_points.size());
1545 Points::const_iterator pi;
1546 for (pi = _points.begin(); pi != _points.end(); ++pi) {
1547 verts.push_back(to_3d((*pi)._p, to_3d_mat));
1550 const LPoint3 *verts_begin = &verts[0];
1551 const LPoint3 *verts_end = verts_begin + verts.size();
1552 setup_points(verts_begin, verts_end);
1568 me->fillin(scan, manager);
virtual void write_datagram(BamWriter *manager, Datagram &me)
Function to write the important information in the particular object to a Datagram.
get_t2
Returns the ending point on the parabola.
A basic node of the scene graph or data graph.
const LVector3 & get_effective_normal() const
Returns the normal that was set by set_effective_normal().
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
get_from_node_path
Returns the NodePath that represents the CollisionNode that contains the CollisionSolid that triggere...
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
An infinite ray, with a specific origin and direction.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static void register_with_read_factory()
Factory method to generate a CollisionPolygon object.
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.
virtual LPoint3 get_collision_origin() const
Returns the point in space deemed to be the "origin" of the solid for collision purposes.
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...
PT(PandaNode) CollisionPolygon
Returns a GeomNode that may be rendered to visualize the CollisionSolid.
The abstract base class for all things that can collide with other things in the world,...
virtual PStatCollector & get_test_pcollector()
Returns a PStatCollector that is used to count the number of intersection tests made against a solid ...
A cuboid collision volume or object.
Defines a series of triangle fans.
Base class for objects that can be written to and read from Bam files.
get_parabola
Returns the parabola specified by this solid.
virtual void xform(const LMatrix4 &mat)
Transforms the solid by the indicated matrix.
This collects together the pieces of data that are accumulated for each node while walking the scene ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This functions similarly to a LightAttrib.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
A spherical collision volume or object.
virtual void write_datagram(BamWriter *manager, Datagram &me)
Function to write the important information in the particular object to a Datagram.
get_into_node_path
Returns the NodePath that represents the specific CollisionNode or GeomNode instance that was collide...
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
get_respect_effective_normal
See set_respect_effective_normal().
static TypedWritable * make_CollisionPolygon(const FactoryParams ¶ms)
Factory method to generate a CollisionPolygon object.
get_t1
Returns the starting point on the parabola.
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A lightweight class that represents a single element that may be timed and/or counted via stats.
void parse_params(const FactoryParams ¶ms, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
A finite line segment, with two specific endpoints but no thickness.
static bool verify_points(const LPoint3 &a, const LPoint3 &b, const LPoint3 &c)
Verifies that the indicated set of points will define a valid CollisionPolygon: that is,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
const LPlane & get_plane() const
Returns the plane represented by the PlaneNode.
get_num_on_planes
Returns the number of planes that are enabled by the attribute.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Defines a single collision event.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A container for geometry primitives.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
An infinite line, similar to a CollisionRay, except that it extends in both directions.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
PandaNode * node() const
Returns the referenced node of the path.
get_on_plane
Returns the nth plane enabled by the attribute, sorted in render order.
get_from
Returns the CollisionSolid pointer for the particular solid that triggered this collision.
This defines a parabolic arc, or subset of an arc, similar to the path of a projectile or falling obj...
Defines a series of line strips.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_point
Returns the nth vertex of the CollisionPolygon, expressed in 3-D space.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool has_effective_normal() const
Returns true if a special normal was set by set_effective_normal(), false otherwise.
A class to retrieve the individual data elements previously stored in a Datagram.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual PStatCollector & get_volume_pcollector()
Returns a PStatCollector that is used to count the number of bounding volume tests made against a sol...
TypeHandle is the identifier used to differentiate C++ class types.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
A node that holds Geom objects, renderable pieces of geometry.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A node that contains a plane.
void add_geom(Geom *geom, const RenderState *state=RenderState::make_empty())
Adds a new Geom to the node.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_clip_effect() const
Returns the clip_effect bits for this clip plane.