15 #include "collisionPolygon.h"
16 #include "collisionHandler.h"
17 #include "collisionEntry.h"
18 #include "collisionSphere.h"
19 #include "collisionLine.h"
20 #include "collisionRay.h"
21 #include "collisionSegment.h"
22 #include "collisionParabola.h"
23 #include "config_collide.h"
24 #include "cullTraverserData.h"
25 #include "boundingBox.h"
26 #include "pointerToArray.h"
30 #include "datagramIterator.h"
31 #include "bamReader.h"
32 #include "bamWriter.h"
33 #include "transformState.h"
34 #include "clipPlaneAttrib.h"
35 #include "nearly_zero.h"
37 #include "geomTrifans.h"
38 #include "geomLinestrips.h"
39 #include "geomVertexWriter.h"
40 #include "renderState.h"
45 PStatCollector CollisionPolygon::_volume_pcollector(
"Collision Volumes:CollisionPolygon");
46 PStatCollector CollisionPolygon::_test_pcollector(
"Collision Tests:CollisionPolygon");
57 _points(copy._points),
58 _to_2d_mat(copy._to_2d_mat)
86 int num_points = end - begin;
95 for (pi = begin; pi != end && all_ok; ++pi) {
101 for (pj = begin; pj != pi && all_ok; ++pj) {
102 if ((*pj) == (*pi)) {
113 bool got_normal =
false;
114 for (
int i = 2; i < num_points && !got_normal; i++) {
115 LPlane plane(begin[0], begin[1], begin[i]);
116 LVector3 normal = plane.get_normal();
117 PN_stdfloat normal_length = normal.
length();
118 got_normal = IS_THRESHOLD_EQUAL(normal_length, 1.0f, 0.001f);
138 return (_points.size() >= 3);
149 if (_points.size() < 3) {
156 PN_stdfloat dx1 = p1[0] - p0[0];
157 PN_stdfloat dy1 = p1[1] - p0[1];
161 PN_stdfloat dx2 = p1[0] - p0[0];
162 PN_stdfloat dy2 = p1[1] - p0[1];
163 int asum = ((dx1 * dy2 - dx2 * dy1 >= 0.0f) ? 1 : 0);
165 for (
size_t i = 0; i < _points.size() - 1; i++) {
167 p1 = _points[(i+3) % _points.size()]._p;
173 int csum = ((dx1 * dy2 - dx2 * dy1 >= 0.0f) ? 1 : 0);
196 if (collide_cat.is_spam()) {
198 <<
"CollisionPolygon transformed by:\n";
199 mat.write(collide_cat.spam(
false), 2);
200 if (_points.empty()) {
201 collide_cat.spam(
false)
206 if (!_points.empty()) {
208 rederive_to_3d_mat(to_3d_mat);
210 epvector<LPoint3> verts;
211 verts.reserve(_points.size());
212 Points::const_iterator pi;
213 for (pi = _points.begin(); pi != _points.end(); ++pi) {
214 verts.push_back(to_3d((*pi)._p, to_3d_mat) * mat);
217 const LPoint3 *verts_begin = &verts[0];
218 const LPoint3 *verts_end = verts_begin + verts.
size();
219 setup_points(verts_begin, verts_end);
236 rederive_to_3d_mat(to_3d_mat);
238 LPoint2 median = _points[0]._p;
239 for (
int n = 1; n < (int)_points.size(); n++) {
240 median += _points[n]._p;
242 median /= _points.size();
244 return to_3d(median, to_3d_mat);
257 bool bounds_only)
const {
262 return CollisionSolid::get_viz(trav, data, bounds_only);
265 if (collide_cat.is_debug()) {
267 <<
"drawing polygon with clip plane " << *cpa <<
"\n";
277 if (apply_clip_plane(new_points, cpa, data.get_net_transform(trav))) {
280 return CollisionSolid::get_viz(trav, data, bounds_only);
283 if (new_points.empty()) {
291 draw_polygon(viz_geom_node, bounds_viz_geom_node, new_points);
294 return bounds_viz_geom_node.p();
296 return viz_geom_node.p();
309 return _volume_pcollector;
321 return _test_pcollector;
329 void CollisionPolygon::
330 output(ostream &out)
const {
331 out <<
"cpolygon, (" << get_plane()
332 <<
"), " << _points.size() <<
" vertices";
340 void CollisionPolygon::
341 write(ostream &out,
int indent_level)
const {
342 indent(out, indent_level) << (*this) <<
"\n";
343 Points::const_iterator pi;
344 for (pi = _points.begin(); pi != _points.end(); ++pi) {
345 indent(out, indent_level + 2) << (*pi)._p <<
"\n";
349 rederive_to_3d_mat(to_3d_mat);
350 out <<
"In 3-d space:\n";
351 for (pi = _points.begin(); pi != _points.end(); ++pi) {
352 LVertex vert = to_3d((*pi)._p, to_3d_mat);
353 indent(out, indent_level + 2) << vert <<
"\n";
363 compute_internal_bounds()
const {
364 if (_points.empty()) {
369 rederive_to_3d_mat(to_3d_mat);
371 Points::const_iterator pi = _points.begin();
372 LPoint3 p = to_3d((*pi)._p, to_3d_mat);
377 for (++pi; pi != _points.end(); ++pi) {
378 p = to_3d((*pi)._p, to_3d_mat);
380 n.set(min(n[0], p[0]),
383 x.set(max(x[0], p[0]),
399 test_intersection_from_sphere(const
CollisionEntry &entry)
const {
400 if (_points.size() < 3) {
405 DCAST_INTO_R(sphere, entry.get_from(), 0);
407 CPT(TransformState) wrt_space = entry.get_wrt_space();
408 CPT(TransformState) wrt_prev_space = entry.get_wrt_prev_space();
410 const
LMatrix4 &wrt_mat = wrt_space->get_mat();
412 LPoint3 orig_center = sphere->get_center() * wrt_mat;
413 LPoint3 from_center = orig_center;
414 bool moved_from_center = false;
415 PN_stdfloat t = 1.0f;
416 LPoint3 contact_point(from_center);
417 PN_stdfloat actual_t = 1.0f;
420 LVector3(sphere->get_radius(), 0.0f, 0.0f) * wrt_mat;
421 PN_stdfloat from_radius_2 = from_radius_v.length_squared();
422 PN_stdfloat from_radius = csqrt(from_radius_2);
424 if (wrt_prev_space != wrt_space) {
429 LPoint3 a = sphere->get_center() * wrt_prev_space->get_mat();
434 PN_stdfloat dot = delta.dot(get_normal());
439 if (IS_NEARLY_ZERO(dot)) {
452 PN_stdfloat dist_to_p = dist_to_plane(a);
453 t = (dist_to_p / -dot);
457 actual_t = ((dist_to_p - from_radius) / -dot);
458 actual_t = min((PN_stdfloat)1.0, max((PN_stdfloat)0.0, actual_t));
459 contact_point = a + (actual_t * delta);
464 }
else if (t < 0.0f) {
466 moved_from_center =
true;
469 from_center = a + t * delta;
470 moved_from_center =
true;
479 <<
"polygon within " << entry.get_into_node_path()
480 <<
" has normal " << normal <<
" of length " << normal.
length()
489 if (!get_plane().intersects_line(dist, from_center, -get_normal())) {
495 if (dist > from_radius || dist < -from_radius) {
500 LPoint2 p = to_2d(from_center - dist * get_normal());
501 PN_stdfloat edge_dist = 0.0f;
507 if (apply_clip_plane(new_points, cpa, entry.get_into_node_path().get_net_transform())) {
510 edge_dist = dist_to_polygon(p, _points);
512 }
else if (new_points.empty()) {
518 edge_dist = dist_to_polygon(p, new_points);
523 edge_dist = dist_to_polygon(p, _points);
530 if (edge_dist > from_radius) {
541 PN_stdfloat max_dist = from_radius;
542 if (edge_dist >= 0.0f) {
543 PN_stdfloat max_dist_2 = max(from_radius_2 - edge_dist * edge_dist, (PN_stdfloat)0.0);
544 max_dist = csqrt(max_dist_2);
547 if (dist > max_dist) {
552 if (collide_cat.is_debug()) {
554 <<
"intersection detected from " << entry.get_from_node_path()
555 <<
" into " << entry.get_into_node_path() <<
"\n";
559 PN_stdfloat into_depth = max_dist - dist;
560 if (moved_from_center) {
564 PN_stdfloat orig_dist;
565 get_plane().intersects_line(orig_dist, orig_center, -normal);
566 into_depth = max_dist - orig_dist;
569 new_entry->set_surface_normal(normal);
570 new_entry->set_surface_point(from_center - normal * dist);
571 new_entry->set_interior_point(from_center - normal * (dist + into_depth));
572 new_entry->set_contact_pos(contact_point);
573 new_entry->set_contact_normal(get_normal());
574 new_entry->set_t(actual_t);
588 if (_points.size() < 3) {
593 DCAST_INTO_R(line, entry.get_from(), 0);
595 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
597 LPoint3 from_origin = line->get_origin() * wrt_mat;
598 LVector3 from_direction = line->get_direction() * wrt_mat;
601 if (!get_plane().intersects_line(t, from_origin, from_direction)) {
606 LPoint3 plane_point = from_origin + t * from_direction;
607 LPoint2 p = to_2d(plane_point);
613 if (apply_clip_plane(new_points, cpa, entry.get_into_node_path().get_net_transform())) {
615 if (!point_is_inside(p, _points)) {
620 if (new_points.size() < 3) {
623 if (!point_is_inside(p, new_points)) {
630 if (!point_is_inside(p, _points)) {
635 if (collide_cat.is_debug()) {
637 <<
"intersection detected from " << entry.get_from_node_path()
638 <<
" into " << entry.get_into_node_path() <<
"\n";
642 LVector3 normal = (has_effective_normal() && line->get_respect_effective_normal()) ? get_effective_normal() : get_normal();
644 new_entry->set_surface_normal(normal);
645 new_entry->set_surface_point(plane_point);
659 if (_points.size() < 3) {
664 DCAST_INTO_R(ray, entry.get_from(), 0);
666 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
668 LPoint3 from_origin = ray->get_origin() * wrt_mat;
669 LVector3 from_direction = ray->get_direction() * wrt_mat;
672 if (!get_plane().intersects_line(t, from_origin, from_direction)) {
682 LPoint3 plane_point = from_origin + t * from_direction;
683 LPoint2 p = to_2d(plane_point);
689 if (apply_clip_plane(new_points, cpa, entry.get_into_node_path().get_net_transform())) {
691 if (!point_is_inside(p, _points)) {
696 if (new_points.size() < 3) {
699 if (!point_is_inside(p, new_points)) {
706 if (!point_is_inside(p, _points)) {
711 if (collide_cat.is_debug()) {
713 <<
"intersection detected from " << entry.get_from_node_path()
714 <<
" into " << entry.get_into_node_path() <<
"\n";
718 LVector3 normal = (has_effective_normal() && ray->get_respect_effective_normal()) ? get_effective_normal() : get_normal();
720 new_entry->set_surface_normal(normal);
721 new_entry->set_surface_point(plane_point);
734 test_intersection_from_segment(const
CollisionEntry &entry)
const {
735 if (_points.size() < 3) {
740 DCAST_INTO_R(segment, entry.get_from(), 0);
742 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
744 LPoint3 from_a = segment->get_point_a() * wrt_mat;
745 LPoint3 from_b = segment->get_point_b() * wrt_mat;
746 LPoint3 from_direction = from_b - from_a;
749 if (!get_plane().intersects_line(t, from_a, from_direction)) {
754 if (t < 0.0f || t > 1.0f) {
760 LPoint3 plane_point = from_a + t * from_direction;
761 LPoint2 p = to_2d(plane_point);
767 if (apply_clip_plane(new_points, cpa, entry.get_into_node_path().get_net_transform())) {
769 if (!point_is_inside(p, _points)) {
774 if (new_points.size() < 3) {
777 if (!point_is_inside(p, new_points)) {
784 if (!point_is_inside(p, _points)) {
789 if (collide_cat.is_debug()) {
791 <<
"intersection detected from " << entry.get_from_node_path()
792 <<
" into " << entry.get_into_node_path() <<
"\n";
796 LVector3 normal = (has_effective_normal() && segment->get_respect_effective_normal()) ? get_effective_normal() : get_normal();
798 new_entry->set_surface_normal(normal);
799 new_entry->set_surface_point(plane_point);
812 test_intersection_from_parabola(const
CollisionEntry &entry)
const {
813 if (_points.size() < 3) {
818 DCAST_INTO_R(parabola, entry.get_from(), 0);
820 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
824 local_p.xform(wrt_mat);
827 if (!get_plane().intersects_parabola(t1, t2, local_p)) {
833 if (t1 >= parabola->
get_t1() && t1 <= parabola->
get_t2()) {
834 if (t2 >= parabola->
get_t1() && t2 <= parabola->
get_t2()) {
843 }
else if (t2 >= parabola->
get_t1() && t2 <= parabola->
get_t2()) {
852 LPoint3 plane_point = local_p.calc_point(t);
853 LPoint2 p = to_2d(plane_point);
859 if (apply_clip_plane(new_points, cpa, entry.get_into_node_path().get_net_transform())) {
861 if (!point_is_inside(p, _points)) {
866 if (new_points.size() < 3) {
869 if (!point_is_inside(p, new_points)) {
876 if (!point_is_inside(p, _points)) {
881 if (collide_cat.is_debug()) {
883 <<
"intersection detected from " << entry.get_from_node_path()
884 <<
" into " << entry.get_into_node_path() <<
"\n";
888 LVector3 normal = (has_effective_normal() && parabola->get_respect_effective_normal()) ? get_effective_normal() : get_normal();
890 new_entry->set_surface_normal(normal);
891 new_entry->set_surface_point(plane_point);
904 if (collide_cat.is_debug()) {
906 <<
"Recomputing viz for " << *
this <<
"\n";
908 nassertv(_viz_geom != (
GeomNode *)NULL && _bounds_viz_geom != (
GeomNode *)NULL);
909 draw_polygon(_viz_geom, _bounds_viz_geom, _points);
924 PN_stdfloat CollisionPolygon::
925 dist_to_line_segment(
const LPoint2 &p,
929 PN_stdfloat d = (v1[0] * v[1] - v1[1] * v[0]);
947 return (p - t).length();
954 return (p - f).length();
956 return (p - t).length();
966 return (p - f).length();
968 return (p - t).length();
975 return (p - f).length();
977 return (p - t).length();
990 return (p - f).length();
992 return (p - t).length();
999 return (p - f).length();
1000 }
if (q[1] > t[1]) {
1001 return (p - t).length();
1008 if (-v[0] > -v[1]) {
1011 return (p - f).length();
1012 }
if (q[0] < t[0]) {
1013 return (p - t).length();
1020 return (p - f).length();
1021 }
if (q[1] < t[1]) {
1022 return (p - t).length();
1039 void CollisionPolygon::
1040 compute_vectors(Points &points) {
1041 size_t num_points = points.size();
1042 for (
size_t i = 0; i < num_points; i++) {
1043 points[i]._v = points[(i + 1) % num_points]._p - points[i]._p;
1044 points[i]._v.normalize();
1055 void CollisionPolygon::
1058 if (points.size() < 3) {
1059 if (collide_cat.is_debug()) {
1061 <<
"(Degenerate poly, ignoring.)\n";
1067 rederive_to_3d_mat(to_3d_mat);
1070 ("collision", GeomVertexFormat::get_v3(),
1074 Points::const_iterator pi;
1075 for (pi = points.begin(); pi != points.end(); ++pi) {
1076 vertex.
add_data3(to_3d((*pi)._p, to_3d_mat));
1080 body->add_consecutive_vertices(0, points.size());
1081 body->close_primitive();
1084 border->add_consecutive_vertices(0, points.size());
1085 border->add_vertex(0);
1086 border->close_primitive();
1089 geom1->add_primitive(body);
1092 geom2->add_primitive(border);
1094 viz_geom_node->add_geom(geom1, ((
CollisionPolygon *)this)->get_solid_viz_state());
1095 viz_geom_node->add_geom(geom2, ((
CollisionPolygon *)this)->get_wireframe_viz_state());
1097 bounds_viz_geom_node->add_geom(geom1, ((
CollisionPolygon *)this)->get_solid_bounds_viz_state());
1098 bounds_viz_geom_node->add_geom(geom2, ((
CollisionPolygon *)this)->get_wireframe_bounds_viz_state());
1115 for (
int i = 0; i < (int)points.size() - 1; i++) {
1116 if (is_right(p - points[i]._p, points[i+1]._p - points[i]._p)) {
1120 if (is_right(p - points[points.size() - 1]._p,
1121 points[0]._p - points[points.size() - 1]._p)) {
1136 PN_stdfloat CollisionPolygon::
1147 bool got_dist =
false;
1148 PN_stdfloat best_dist = -1.0f;
1150 size_t num_points = points.size();
1151 for (
size_t i = 0; i < num_points - 1; ++i) {
1152 PN_stdfloat d = dist_to_line_segment(p, points[i]._p, points[i + 1]._p,
1155 if (!got_dist || d < best_dist) {
1162 PN_stdfloat d = dist_to_line_segment(p, points[num_points - 1]._p, points[0]._p,
1163 points[num_points - 1]._v);
1165 if (!got_dist || d < best_dist) {
1179 void CollisionPolygon::
1181 int num_points = end - begin;
1182 nassertv(num_points >= 3);
1195 for (
int i = 0; i < num_points; i++) {
1197 const LPoint3 &p1 = begin[(i + 1) % num_points];
1198 normal[0] += p0[1] * p1[2] - p0[2] * p1[1];
1199 normal[1] += p0[2] * p1[0] - p0[0] * p1[2];
1200 normal[2] += p0[0] * p1[1] - p0[1] * p1[0];
1212 collide_cat.error() <<
"Invalid points in CollisionPolygon:\n";
1214 for (pi = begin; pi != end; ++pi) {
1215 collide_cat.error(
false) <<
" " << (*pi) <<
"\n";
1217 collide_cat.error(
false)
1218 <<
" normal " << normal <<
" with length " << normal.
length() <<
"\n";
1224 if (collide_cat.is_spam()) {
1226 <<
"CollisionPolygon defined with " << num_points <<
" vertices:\n";
1228 for (pi = begin; pi != end; ++pi) {
1229 collide_cat.spam(
false) <<
" " << (*pi) <<
"\n";
1234 set_plane(LPlane(normal, begin[0]));
1239 calc_to_3d_mat(to_3d_mat);
1248 for (pi = begin; pi != end; ++pi) {
1249 LPoint3 point = (*pi) * _to_2d_mat;
1250 _points.push_back(PointDef(point[0], point[2]));
1253 nassertv(_points.size() >= 3);
1271 compute_vectors(_points);
1282 legacy_to_3d(
const LVecBase2 &point2d,
int axis)
const {
1286 PN_stdfloat D = get_plane()[3];
1288 nassertr(!normal.is_nan(),
LPoint3(0.0f, 0.0f, 0.0f));
1289 nassertr(!cnan(D),
LPoint3(0.0f, 0.0f, 0.0f));
1293 return LPoint3(-(normal[1]*point2d[0] + normal[2]*point2d[1] + D)/normal[0], point2d[0], point2d[1]);
1297 -(normal[0]*point2d[0] + normal[2]*point2d[1] + D)/normal[1], point2d[1]);
1300 return LPoint3(point2d[0], point2d[1],
1301 -(normal[0]*point2d[0] + normal[1]*point2d[1] + D)/normal[2]);
1304 nassertr(
false,
LPoint3(0.0f, 0.0f, 0.0f));
1305 return LPoint3(0.0f, 0.0f, 0.0f);
1320 bool CollisionPolygon::
1323 const LPlane &plane)
const {
1325 if (source_points.empty()) {
1331 if (!plane.intersects_plane(from3d, delta3d, get_plane())) {
1334 if (plane.dist_to_plane(get_plane().
get_point()) < 0.0) {
1337 new_points = source_points;
1345 LPoint2 from2d = to_2d(from3d);
1348 PN_stdfloat a = -delta2d[1];
1349 PN_stdfloat b = delta2d[0];
1350 PN_stdfloat c = from2d[0] * delta2d[1] - from2d[1] * delta2d[0];
1359 new_points.reserve(source_points.size() + 1);
1361 LPoint2 last_point = source_points.back()._p;
1362 bool last_is_in = !is_right(last_point - from2d, delta2d);
1363 bool all_in = last_is_in;
1364 Points::const_iterator pi;
1365 for (pi = source_points.begin(); pi != source_points.end(); ++pi) {
1366 const LPoint2 &this_point = (*pi)._p;
1367 bool this_is_in = !is_right(this_point - from2d, delta2d);
1371 bool crossed_over = (this_is_in != last_is_in);
1375 LVector2 d = this_point - last_point;
1376 PN_stdfloat denom = (a * d[0] + b * d[1]);
1378 PN_stdfloat t = -(a * last_point[0] + b * last_point[1] + c) / denom;
1379 LPoint2 p = last_point + t * d;
1381 new_points.push_back(PointDef(p[0], p[1]));
1382 last_is_in = this_is_in;
1388 new_points.push_back(PointDef(this_point[0], this_point[1]));
1393 last_point = this_point;
1410 bool CollisionPolygon::
1413 const TransformState *net_transform)
const {
1417 bool first_plane =
true;
1419 for (
int i = 0; i < num_planes; i++) {
1423 CPT(TransformState) new_transform =
1424 net_transform->invert_compose(plane_path.get_net_transform());
1426 LPlane plane = plane_node->get_plane() * new_transform->get_mat();
1428 first_plane =
false;
1429 if (!clip_polygon(new_points, _points, plane)) {
1434 last_points.swap(new_points);
1435 if (!clip_polygon(new_points, last_points, plane)) {
1443 compute_vectors(new_points);
1459 for (
size_t i = 0; i < _points.size(); i++) {
1460 _points[i]._p.write_datagram(me);
1461 _points[i]._v.write_datagram(me);
1463 _to_2d_mat.write_datagram(me);
1474 void CollisionPolygon::
1476 CollisionPlane::fillin(scan, manager);
1479 for (
size_t i = 0; i < size; i++) {
1484 _points.push_back(PointDef(p, v));
1486 _to_2d_mat.read_datagram(scan);
1492 if (_points.size() >= 3) {
1494 rederive_to_3d_mat(to_3d_mat);
1496 epvector<LPoint3> verts;
1497 verts.reserve(_points.size());
1498 Points::const_iterator pi;
1499 for (pi = _points.begin(); pi != _points.end(); ++pi) {
1500 verts.push_back(to_3d((*pi)._p, to_3d_mat));
1503 const LPoint3 *verts_begin = &verts[0];
1504 const LPoint3 *verts_end = verts_begin + verts.
size();
1505 setup_points(verts_begin, verts_end);
1522 parse_params(params, scan, manager);
1523 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.
A basic node of the scene graph or data graph.
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
An infinite ray, with a specific origin and direction.
static void register_with_read_factory()
Factory method to generate a CollisionPolygon object.
bool get_respect_effective_normal() const
See set_respect_effective_normal().
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
The abstract base class for all things that can collide with other things in the world, and all the things they can collide with (except geometry).
virtual PStatCollector & get_test_pcollector()
Returns a PStatCollector that is used to count the number of intersection tests made against a solid ...
Defines a series of triangle fans.
Base class for objects that can be written to and read from Bam files.
bool is_nan() const
Returns true if any component of the vector is not-a-number, false otherwise.
static const LVector3f & zero()
Returns a zero-length vector.
virtual void xform(const LMatrix4 &mat)
Transforms the solid by the indicated matrix.
float length_squared() const
Returns the square of the vector's length, cheap and easy.
This collects together the pieces of data that are accumulated for each node while walking the scene ...
PandaNode * node() const
Returns the referenced node of the path.
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
This functions similarly to a LightAttrib.
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
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.
PN_uint16 get_uint16()
Extracts an unsigned 16-bit integer.
static TypedWritable * make_CollisionPolygon(const FactoryParams ¶ms)
Factory method to generate a CollisionPolygon object.
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
float length() const
Returns the length of the vector, by the Pythagorean theorem.
A lightweight class that represents a single element that may be timed and/or counted via stats...
A finite line segment, with two specific endpoints but no thickness.
float length() const
Returns the length of the vector, by the Pythagorean theorem.
int get_clip_effect() const
Returns the clip_effect bits for this clip plane.
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...
void read_datagram(DatagramIterator &source)
Reads the vector from the Datagram using get_stdfloat().
This is a 4-by-4 transform matrix.
Defines a single collision event.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
A container for geometry primitives.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
bool invert_from(const LMatrix4f &other)
Computes the inverse of the other matrix, and stores the result in this matrix.
NodePath get_on_plane(int n) const
Returns the nth plane enabled by the attribute, sorted in render order.
void add_data3(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Sets the write row to a particular 3-component value, and advances the write row. ...
This is the base class for all two-component vectors and points.
PN_stdfloat get_t2() const
Returns the ending point on the parabola.
bool is_concave() const
Returns true if the CollisionPolygon appears to be concave, or false if it is safely convex...
const LParabola & get_parabola() const
Returns the parabola specified by this solid.
int get_num_on_planes() const
Returns the number of planes that are enabled by the attribute.
LPoint3 get_point(int n) const
Returns the nth vertex of the CollisionPolygon, expressed in 3-D space.
void register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
void add_uint16(PN_uint16 value)
Adds an unsigned 16-bit integer to the datagram.
An infinite line, similar to a CollisionRay, except that it extends in both directions.
This is a two-component vector offset.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
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.
virtual void xform(const LMatrix4 &mat)
Transforms the solid by the indicated matrix.
PN_stdfloat get_t1() const
Returns the starting point on the parabola.
A class to retrieve the individual data elements previously stored in a Datagram. ...
This is a two-component point in space.
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
TypeHandle is the identifier used to differentiate C++ class types.
bool normalize()
Normalizes the vector in place.
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.
A node that contains a plane.
bool is_valid() const
Returns true if the CollisionPolygon is valid (that is, it has at least three vertices), or false otherwise.
virtual LPoint3 get_collision_origin() const
Returns the point in space deemed to be the "origin" of the solid for collision purposes.
static int size()
Returns 3: the number of components of a LVecBase3.
virtual PStatCollector & get_volume_pcollector()
Returns a PStatCollector that is used to count the number of bounding volume tests made against a sol...