Panda3D
collisionPlane.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file collisionPlane.cxx
10  * @author drose
11  * @date 2000-04-25
12  */
13 
14 #include "collisionPlane.h"
15 #include "collisionHandler.h"
16 #include "collisionEntry.h"
17 #include "collisionSphere.h"
18 #include "collisionLine.h"
19 #include "collisionRay.h"
20 #include "collisionSegment.h"
21 #include "collisionCapsule.h"
22 #include "collisionParabola.h"
23 #include "config_collide.h"
24 #include "pointerToArray.h"
25 #include "geomNode.h"
26 #include "geom.h"
27 #include "datagram.h"
28 #include "datagramIterator.h"
29 #include "bamReader.h"
30 #include "bamWriter.h"
31 #include "boundingPlane.h"
32 #include "geom.h"
33 #include "geomTrifans.h"
34 #include "geomLinestrips.h"
35 #include "geomVertexWriter.h"
36 
37 PStatCollector CollisionPlane::_volume_pcollector("Collision Volumes:CollisionPlane");
38 PStatCollector CollisionPlane::_test_pcollector("Collision Tests:CollisionPlane");
39 TypeHandle CollisionPlane::_type_handle;
40 
41 /**
42  *
43  */
44 CollisionSolid *CollisionPlane::
45 make_copy() {
46  return new CollisionPlane(*this);
47 }
48 
49 /**
50  * Transforms the solid by the indicated matrix.
51  */
53 xform(const LMatrix4 &mat) {
54  _plane = _plane * mat;
55  CollisionSolid::xform(mat);
56 }
57 
58 /**
59  * Returns the point in space deemed to be the "origin" of the solid for
60  * collision purposes. The closest intersection point to this origin point is
61  * considered to be the most significant.
62  */
63 LPoint3 CollisionPlane::
65  // No real sensible origin exists for a plane. We return 0, 0, 0, without
66  // even bothering to ensure that that point exists on the plane.
67  return LPoint3::origin();
68 }
69 
70 /**
71  * Returns a PStatCollector that is used to count the number of bounding
72  * volume tests made against a solid of this type in a given frame.
73  */
76  return _volume_pcollector;
77 }
78 
79 /**
80  * Returns a PStatCollector that is used to count the number of intersection
81  * tests made against a solid of this type in a given frame.
82  */
85  return _test_pcollector;
86 }
87 
88 /**
89  *
90  */
91 void CollisionPlane::
92 output(std::ostream &out) const {
93  out << "cplane, (" << _plane << ")";
94 }
95 
96 /**
97  *
98  */
99 PT(BoundingVolume) CollisionPlane::
100 compute_internal_bounds() const {
101  return new BoundingPlane(_plane);
102 }
103 
104 /**
105  *
106  */
107 PT(CollisionEntry) CollisionPlane::
108 test_intersection_from_sphere(const CollisionEntry &entry) const {
109  const CollisionSphere *sphere;
110  DCAST_INTO_R(sphere, entry.get_from(), nullptr);
111 
112  const LMatrix4 &wrt_mat = entry.get_wrt_mat();
113 
114  LPoint3 from_center = sphere->get_center() * wrt_mat;
115  LVector3 from_radius_v =
116  LVector3(sphere->get_radius(), 0.0f, 0.0f) * wrt_mat;
117  PN_stdfloat from_radius = length(from_radius_v);
118 
119  PN_stdfloat dist = dist_to_plane(from_center);
120  if (dist > from_radius) {
121  // No intersection.
122  return nullptr;
123  }
124 
125  if (collide_cat.is_debug()) {
126  collide_cat.debug()
127  << "intersection detected from " << entry.get_from_node_path()
128  << " into " << entry.get_into_node_path() << "\n";
129  }
130  PT(CollisionEntry) new_entry = new CollisionEntry(entry);
131 
132  LVector3 normal = (
134  ? get_effective_normal() : get_normal();
135 
136  new_entry->set_surface_normal(normal);
137  new_entry->set_surface_point(from_center - get_normal() * dist);
138  new_entry->set_interior_point(from_center - get_normal() * from_radius);
139 
140  return new_entry;
141 }
142 
143 /**
144  *
145  */
146 PT(CollisionEntry) CollisionPlane::
147 test_intersection_from_line(const CollisionEntry &entry) const {
148  const CollisionLine *line;
149  DCAST_INTO_R(line, entry.get_from(), nullptr);
150 
151  const LMatrix4 &wrt_mat = entry.get_wrt_mat();
152 
153  LPoint3 from_origin = line->get_origin() * wrt_mat;
154  LVector3 from_direction = line->get_direction() * wrt_mat;
155 
156  PN_stdfloat t;
157  if (!_plane.intersects_line(t, from_origin, from_direction)) {
158  // No intersection. The line is parallel to the plane.
159 
160  if (_plane.dist_to_plane(from_origin) > 0.0f) {
161  // The line is entirely in front of the plane.
162  return nullptr;
163  }
164 
165  // The line is entirely behind the plane.
166  t = 0.0f;
167  }
168 
169  if (collide_cat.is_debug()) {
170  collide_cat.debug()
171  << "intersection detected from " << entry.get_from_node_path()
172  << " into " << entry.get_into_node_path() << "\n";
173  }
174  PT(CollisionEntry) new_entry = new CollisionEntry(entry);
175 
176  LPoint3 into_intersection_point = from_origin + t * from_direction;
177 
178  LVector3 normal =
180  ? get_effective_normal() : get_normal();
181 
182  new_entry->set_surface_normal(normal);
183  new_entry->set_surface_point(into_intersection_point);
184 
185  return new_entry;
186 }
187 
188 /**
189  *
190  */
191 PT(CollisionEntry) CollisionPlane::
192 test_intersection_from_ray(const CollisionEntry &entry) const {
193  const CollisionRay *ray;
194  DCAST_INTO_R(ray, entry.get_from(), nullptr);
195 
196  const LMatrix4 &wrt_mat = entry.get_wrt_mat();
197 
198  LPoint3 from_origin = ray->get_origin() * wrt_mat;
199  LVector3 from_direction = ray->get_direction() * wrt_mat;
200 
201  PN_stdfloat t;
202 
203  if (_plane.dist_to_plane(from_origin) < 0.0f) {
204  // The origin of the ray is behind the plane, so we don't need to test
205  // further.
206  t = 0.0f;
207 
208  } else {
209  if (!_plane.intersects_line(t, from_origin, from_direction)) {
210  // No intersection. The ray is parallel to the plane.
211  return nullptr;
212  }
213 
214  if (t < 0.0f) {
215  // The intersection point is before the start of the ray, and so the ray
216  // is entirely in front of the plane.
217  return nullptr;
218  }
219  }
220 
221  if (collide_cat.is_debug()) {
222  collide_cat.debug()
223  << "intersection detected from " << entry.get_from_node_path()
224  << " into " << entry.get_into_node_path() << "\n";
225  }
226  PT(CollisionEntry) new_entry = new CollisionEntry(entry);
227 
228  LPoint3 into_intersection_point = from_origin + t * from_direction;
229 
230  LVector3 normal =
232  ? get_effective_normal() : get_normal();
233 
234  new_entry->set_surface_normal(normal);
235  new_entry->set_surface_point(into_intersection_point);
236 
237  return new_entry;
238 }
239 
240 /**
241  *
242  */
243 PT(CollisionEntry) CollisionPlane::
244 test_intersection_from_segment(const CollisionEntry &entry) const {
245  const CollisionSegment *segment;
246  DCAST_INTO_R(segment, entry.get_from(), nullptr);
247 
248  const LMatrix4 &wrt_mat = entry.get_wrt_mat();
249 
250  LPoint3 from_a = segment->get_point_a() * wrt_mat;
251  LPoint3 from_b = segment->get_point_b() * wrt_mat;
252 
253  PN_stdfloat dist_a = _plane.dist_to_plane(from_a);
254  PN_stdfloat dist_b = _plane.dist_to_plane(from_b);
255 
256  if (dist_a >= 0.0f && dist_b >= 0.0f) {
257  // Entirely in front of the plane means no intersection.
258  return nullptr;
259  }
260 
261  if (collide_cat.is_debug()) {
262  collide_cat.debug()
263  << "intersection detected from " << entry.get_from_node_path()
264  << " into " << entry.get_into_node_path() << "\n";
265  }
266  PT(CollisionEntry) new_entry = new CollisionEntry(entry);
267 
268  LVector3 normal = (has_effective_normal() && segment->get_respect_effective_normal()) ? get_effective_normal() : get_normal();
269  new_entry->set_surface_normal(normal);
270 
271  PN_stdfloat t;
272  LVector3 from_direction = from_b - from_a;
273  if (_plane.intersects_line(t, from_a, from_direction)) {
274  // It intersects the plane.
275  if (t >= 0.0f && t <= 1.0f) {
276  // Within the segment! Yay, that means we have a surface point.
277  new_entry->set_surface_point(from_a + t * from_direction);
278  }
279  }
280 
281  if (dist_a < dist_b) {
282  // Point A penetrates deeper.
283  new_entry->set_interior_point(from_a);
284 
285  } else if (dist_b < dist_a) {
286  // No, point B does.
287  new_entry->set_interior_point(from_b);
288 
289  } else {
290  // Let's be fair and choose the center of the segment.
291  new_entry->set_interior_point((from_a + from_b) * 0.5);
292  }
293 
294  return new_entry;
295 }
296 
297 /**
298  *
299  */
300 PT(CollisionEntry) CollisionPlane::
301 test_intersection_from_capsule(const CollisionEntry &entry) const {
302  const CollisionCapsule *capsule;
303  DCAST_INTO_R(capsule, entry.get_from(), nullptr);
304 
305  const LMatrix4 &wrt_mat = entry.get_wrt_mat();
306 
307  LPoint3 from_a = capsule->get_point_a() * wrt_mat;
308  LPoint3 from_b = capsule->get_point_b() * wrt_mat;
309  LVector3 from_radius_v =
310  LVector3(capsule->get_radius(), 0.0f, 0.0f) * wrt_mat;
311  PN_stdfloat from_radius = length(from_radius_v);
312 
313  PN_stdfloat dist_a = _plane.dist_to_plane(from_a);
314  PN_stdfloat dist_b = _plane.dist_to_plane(from_b);
315 
316  if (dist_a >= from_radius && dist_b >= from_radius) {
317  // Entirely in front of the plane means no intersection.
318  return nullptr;
319  }
320 
321  if (collide_cat.is_debug()) {
322  collide_cat.debug()
323  << "intersection detected from " << entry.get_from_node_path()
324  << " into " << entry.get_into_node_path() << "\n";
325  }
326  PT(CollisionEntry) new_entry = new CollisionEntry(entry);
327 
328  LVector3 normal = (has_effective_normal() && capsule->get_respect_effective_normal()) ? get_effective_normal() : get_normal();
329  new_entry->set_surface_normal(normal);
330 
331  PN_stdfloat t;
332  LVector3 from_direction = from_b - from_a;
333  if (_plane.intersects_line(t, from_a, from_direction)) {
334  // It intersects the plane.
335  if (t >= 1.0f) {
336  new_entry->set_surface_point(from_b - get_normal() * dist_b);
337 
338  } else if (t <= 0.0f) {
339  new_entry->set_surface_point(from_a - get_normal() * dist_a);
340 
341  } else {
342  // Within the capsule! Yay, that means we have a surface point.
343  new_entry->set_surface_point(from_a + t * from_direction);
344  }
345  } else {
346  // If it's completely parallel, pretend it's colliding in the center of
347  // the capsule.
348  new_entry->set_surface_point(from_a + 0.5f * from_direction - get_normal() * dist_a);
349  }
350 
351  if (IS_NEARLY_EQUAL(dist_a, dist_b)) {
352  // Let's be fair and choose the center of the capsule.
353  new_entry->set_interior_point(from_a + 0.5f * from_direction - get_normal() * from_radius);
354 
355  } else if (dist_a < dist_b) {
356  // Point A penetrates deeper.
357  new_entry->set_interior_point(from_a - get_normal() * from_radius);
358 
359  } else if (dist_b < dist_a) {
360  // No, point B does.
361  new_entry->set_interior_point(from_b - get_normal() * from_radius);
362  }
363 
364  return new_entry;
365 }
366 
367 /**
368  * This is part of the double-dispatch implementation of test_intersection().
369  * It is called when the "from" object is a parabola.
370  */
371 PT(CollisionEntry) CollisionPlane::
372 test_intersection_from_parabola(const CollisionEntry &entry) const {
373  const CollisionParabola *parabola;
374  DCAST_INTO_R(parabola, entry.get_from(), nullptr);
375 
376  const LMatrix4 &wrt_mat = entry.get_wrt_mat();
377 
378  // Convert the parabola into local coordinate space.
379  LParabola local_p(parabola->get_parabola());
380  local_p.xform(wrt_mat);
381 
382  PN_stdfloat t;
383  if (_plane.dist_to_plane(local_p.calc_point(parabola->get_t1())) < 0.0f) {
384  // The first point in the parabola is behind the plane, so we don't need
385  // to test further.
386  t = parabola->get_t1();
387 
388  } else {
389  PN_stdfloat t1, t2;
390  if (!get_plane().intersects_parabola(t1, t2, local_p)) {
391  // No intersection. The infinite parabola is entirely in front of the
392  // plane.
393  return nullptr;
394  }
395 
396  if (t1 >= parabola->get_t1() && t1 <= parabola->get_t2()) {
397  if (t2 >= parabola->get_t1() && t2 <= parabola->get_t2()) {
398  // Both intersection points are within our segment of the parabola.
399  // Choose the first of the two.
400  t = std::min(t1, t2);
401  } else {
402  // Only t1 is within our segment.
403  t = t1;
404  }
405 
406  } else if (t2 >= parabola->get_t1() && t2 <= parabola->get_t2()) {
407  // Only t2 is within our segment.
408  t = t2;
409 
410  } else {
411  // Neither intersection point is within our segment.
412  return nullptr;
413  }
414  }
415 
416  if (collide_cat.is_debug()) {
417  collide_cat.debug()
418  << "intersection detected from " << entry.get_from_node_path()
419  << " into " << entry.get_into_node_path() << "\n";
420  }
421  PT(CollisionEntry) new_entry = new CollisionEntry(entry);
422 
423  LPoint3 into_intersection_point = local_p.calc_point(t);
424 
425  LVector3 normal = (has_effective_normal() && parabola->get_respect_effective_normal()) ? get_effective_normal() : get_normal();
426 
427  new_entry->set_surface_normal(normal);
428  new_entry->set_surface_point(into_intersection_point);
429 
430  return new_entry;
431 }
432 
433 /**
434  * This is part of the double-dispatch implementation of test_intersection().
435  * It is called when the "from" object is a box.
436  */
437 PT(CollisionEntry) CollisionPlane::
438 test_intersection_from_box(const CollisionEntry &entry) const {
439  const CollisionBox *box;
440  DCAST_INTO_R(box, entry.get_from(), nullptr);
441 
442  const LMatrix4 &wrt_mat = entry.get_wrt_mat();
443 
444  LPoint3 from_center = box->get_center() * wrt_mat;
445  LVector3 from_extents = box->get_dimensions() * 0.5f;
446  PN_stdfloat dist = _plane.dist_to_plane(from_center);
447 
448  // Determine the basis vectors describing the box.
449  LVecBase3 box_x = wrt_mat.get_row3(0) * from_extents[0];
450  LVecBase3 box_y = wrt_mat.get_row3(1) * from_extents[1];
451  LVecBase3 box_z = wrt_mat.get_row3(2) * from_extents[2];
452 
453  // Project the box onto the normal vector of the plane to determine whether
454  // there is a separating axis.
455  PN_stdfloat dx = box_x.dot(_plane.get_normal());
456  PN_stdfloat dy = box_y.dot(_plane.get_normal());
457  PN_stdfloat dz = box_z.dot(_plane.get_normal());
458  PN_stdfloat depth = dist - (cabs(dx) + cabs(dy) + cabs(dz));
459 
460  if (depth > 0) {
461  // No collision.
462  return nullptr;
463  }
464 
465  if (collide_cat.is_debug()) {
466  collide_cat.debug()
467  << "intersection detected from " << entry.get_from_node_path()
468  << " into " << entry.get_into_node_path() << "\n";
469  }
470  PT(CollisionEntry) new_entry = new CollisionEntry(entry);
471 
472  LVector3 normal = (has_effective_normal() && box->get_respect_effective_normal()) ? get_effective_normal() : get_normal();
473  new_entry->set_surface_normal(normal);
474 
475  // Determine which point on the cube will be the interior point. If the
476  // points are equally close, this chooses their center instead.
477  LPoint3 interior_point = from_center +
478  box_x * ((dx < 0) - (dx > 0)) +
479  box_y * ((dy < 0) - (dy > 0)) +
480  box_z * ((dz < 0) - (dz > 0));
481 
482  // The surface point is the interior point projected onto the plane.
483  new_entry->set_surface_point(interior_point - get_normal() * depth);
484  new_entry->set_interior_point(interior_point);
485 
486  return new_entry;
487 }
488 
489 /**
490  * Fills the _viz_geom GeomNode up with Geoms suitable for rendering this
491  * solid.
492  */
493 void CollisionPlane::
494 fill_viz_geom() {
495  if (collide_cat.is_debug()) {
496  collide_cat.debug()
497  << "Recomputing viz for " << *this << "\n";
498  }
499 
500  // Since we can't represent an infinite plane, we'll have to be satisfied
501  // with drawing a big polygon. Choose four points on the plane to be the
502  // corners of the polygon.
503 
504  // We must choose four points fairly reasonably spread apart on the plane.
505  // We'll start with a center point and one corner point, and then use cross
506  // products to find the remaining three corners of a square.
507 
508  // The center point will be on the axis with the largest coefficent. The
509  // first corner will be diagonal in the other two dimensions.
510 
511  LPoint3 cp;
512  LVector3 p1, p2, p3, p4;
513 
514  LVector3 normal = get_normal();
515  PN_stdfloat D = _plane[3];
516 
517  if (fabs(normal[0]) > fabs(normal[1]) &&
518  fabs(normal[0]) > fabs(normal[2])) {
519  // X has the largest coefficient.
520  cp.set(-D / normal[0], 0.0f, 0.0f);
521  p1 = LPoint3(-(normal[1] + normal[2] + D)/normal[0], 1.0f, 1.0f) - cp;
522 
523  } else if (fabs(normal[1]) > fabs(normal[2])) {
524  // Y has the largest coefficient.
525  cp.set(0.0f, -D / normal[1], 0.0f);
526  p1 = LPoint3(1.0f, -(normal[0] + normal[2] + D)/normal[1], 1.0f) - cp;
527 
528  } else {
529  // Z has the largest coefficient.
530  cp.set(0.0f, 0.0f, -D / normal[2]);
531  p1 = LPoint3(1.0f, 1.0f, -(normal[0] + normal[1] + D)/normal[2]) - cp;
532  }
533 
534  p1.normalize();
535  p2 = cross(normal, p1);
536  p3 = cross(normal, p2);
537  p4 = cross(normal, p3);
538 
539  static const double plane_scale = 10.0;
540 
541  PT(GeomVertexData) vdata = new GeomVertexData
542  ("collision", GeomVertexFormat::get_v3(),
543  Geom::UH_static);
544  GeomVertexWriter vertex(vdata, InternalName::get_vertex());
545 
546  vertex.add_data3(cp + p1 * plane_scale);
547  vertex.add_data3(cp + p2 * plane_scale);
548  vertex.add_data3(cp + p3 * plane_scale);
549  vertex.add_data3(cp + p4 * plane_scale);
550 
551  PT(GeomTrifans) body = new GeomTrifans(Geom::UH_static);
552  body->add_consecutive_vertices(0, 4);
553  body->close_primitive();
554 
555  PT(GeomLinestrips) border = new GeomLinestrips(Geom::UH_static);
556  border->add_consecutive_vertices(0, 4);
557  border->add_vertex(0);
558  border->close_primitive();
559 
560  PT(Geom) geom1 = new Geom(vdata);
561  geom1->add_primitive(body);
562 
563  PT(Geom) geom2 = new Geom(vdata);
564  geom2->add_primitive(border);
565 
566  _viz_geom->add_geom(geom1, get_solid_viz_state());
567  _viz_geom->add_geom(geom2, get_wireframe_viz_state());
568 
569  _bounds_viz_geom->add_geom(geom1, get_solid_bounds_viz_state());
570  _bounds_viz_geom->add_geom(geom2, get_wireframe_bounds_viz_state());
571 }
572 
573 /**
574  * Function to write the important information in the particular object to a
575  * Datagram
576  */
577 void CollisionPlane::
579 {
580  CollisionSolid::write_datagram(manager, me);
581  _plane.write_datagram(me);
582 }
583 
584 /**
585  * Function that reads out of the datagram (or asks manager to read) all of
586  * the data that is needed to re-create this object and stores it in the
587  * appropiate place
588  */
589 void CollisionPlane::
590 fillin(DatagramIterator& scan, BamReader* manager)
591 {
592  CollisionSolid::fillin(scan, manager);
593  _plane.read_datagram(scan);
594 }
595 
596 /**
597  * Factory method to generate a CollisionPlane object
598  */
601 {
602  CollisionPlane *me = new CollisionPlane;
603  DatagramIterator scan;
604  BamReader *manager;
605 
606  parse_params(params, scan, manager);
607  me->fillin(scan, manager);
608  return me;
609 }
610 
611 /**
612  * Factory method to generate a CollisionPlane object
613  */
614 void CollisionPlane::
616 {
618 }
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.
PT(BoundingVolume) CollisionPlane
This is part of the double-dispatch implementation of test_intersection().
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 infinite ray, with a specific origin and direction.
Definition: collisionRay.h:27
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.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
The abstract base class for all things that can collide with other things in the world,...
A cuboid collision volume or object.
Definition: collisionBox.h:27
Defines a series of triangle fans.
Definition: geomTrifans.h:23
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
get_parabola
Returns the parabola specified by this solid.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
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.
static TypedWritable * make_CollisionPlane(const FactoryParams &params)
Factory method to generate a CollisionPlane object.
get_into_node_path
Returns the NodePath that represents the specific CollisionNode or GeomNode instance that was collide...
get_respect_effective_normal
See set_respect_effective_normal().
This funny bounding volume is an infinite plane that divides space into two regions: the part behind ...
Definition: boundingPlane.h:28
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...
A lightweight class that represents a single element that may be timed and/or counted via stats.
virtual void xform(const LMatrix4 &mat)
Transforms the solid by the indicated matrix.
void parse_params(const FactoryParams &params, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
Definition: bamReader.I:275
virtual LPoint3 get_collision_origin() const
Returns the point in space deemed to be the "origin" of the solid for collision purposes.
A finite line segment, with two specific endpoints but no thickness.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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...
This implements a solid consisting of a cylinder with hemispherical endcaps, also known as a capsule ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A container for geometry primitives.
Definition: geom.h:54
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
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.
Definition: factory.I:73
virtual PStatCollector & get_test_pcollector()
Returns a PStatCollector that is used to count the number of intersection tests made against a solid ...
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...
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.
Definition: collisionLine.h:25
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
get_from
Returns the CollisionSolid pointer for the particular solid that triggered this collision.
static void register_with_read_factory()
Factory method to generate a CollisionPlane object.
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.
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.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
static const GeomVertexFormat * get_v3()
Returns a standard vertex format with just a 3-component vertex position.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.