16 #include "collisionPlane.h" 17 #include "collisionHandler.h" 18 #include "collisionEntry.h" 19 #include "collisionSphere.h" 20 #include "collisionLine.h" 21 #include "collisionRay.h" 22 #include "collisionSegment.h" 23 #include "collisionParabola.h" 24 #include "config_collide.h" 25 #include "pointerToArray.h" 29 #include "datagramIterator.h" 30 #include "bamReader.h" 31 #include "bamWriter.h" 32 #include "boundingPlane.h" 34 #include "geomTrifans.h" 35 #include "geomLinestrips.h" 36 #include "geomVertexWriter.h" 38 PStatCollector CollisionPlane::_volume_pcollector(
"Collision Volumes:CollisionPlane");
39 PStatCollector CollisionPlane::_test_pcollector(
"Collision Tests:CollisionPlane");
59 _plane = _plane * mat;
60 CollisionSolid::xform(mat);
88 return _volume_pcollector;
100 return _test_pcollector;
108 void CollisionPlane::
109 output(ostream &out)
const {
110 out <<
"cplane, (" << _plane <<
")";
119 compute_internal_bounds()
const {
129 test_intersection_from_sphere(
const CollisionEntry &entry)
const {
131 DCAST_INTO_R(sphere, entry.
get_from(), NULL);
133 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
135 LPoint3 from_center = sphere->get_center() * wrt_mat;
137 LVector3(sphere->get_radius(), 0.0f, 0.0f) * wrt_mat;
138 PN_stdfloat from_radius = length(from_radius_v);
140 PN_stdfloat dist = dist_to_plane(from_center);
141 if (dist > from_radius) {
146 if (collide_cat.is_debug()) {
157 new_entry->set_surface_normal(normal);
158 new_entry->set_surface_point(from_center - get_normal() * dist);
159 new_entry->set_interior_point(from_center - get_normal() * from_radius);
172 DCAST_INTO_R(line, entry.
get_from(), NULL);
174 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
176 LPoint3 from_origin = line->get_origin() * wrt_mat;
177 LVector3 from_direction = line->get_direction() * wrt_mat;
180 if (!_plane.intersects_line(t, from_origin, from_direction)) {
183 if (_plane.dist_to_plane(from_origin) > 0.0f) {
192 if (collide_cat.is_debug()) {
199 LPoint3 into_intersection_point = from_origin + t * from_direction;
205 new_entry->set_surface_normal(normal);
206 new_entry->set_surface_point(into_intersection_point);
219 DCAST_INTO_R(ray, entry.
get_from(), NULL);
221 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
223 LPoint3 from_origin = ray->get_origin() * wrt_mat;
224 LVector3 from_direction = ray->get_direction() * wrt_mat;
228 if (_plane.dist_to_plane(from_origin) < 0.0f) {
234 if (!_plane.intersects_line(t, from_origin, from_direction)) {
246 if (collide_cat.is_debug()) {
253 LPoint3 into_intersection_point = from_origin + t * from_direction;
259 new_entry->set_surface_normal(normal);
260 new_entry->set_surface_point(into_intersection_point);
271 test_intersection_from_segment(
const CollisionEntry &entry)
const {
273 DCAST_INTO_R(segment, entry.
get_from(), NULL);
275 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
277 LPoint3 from_a = segment->get_point_a() * wrt_mat;
278 LPoint3 from_b = segment->get_point_b() * wrt_mat;
280 PN_stdfloat dist_a = _plane.dist_to_plane(from_a);
281 PN_stdfloat dist_b = _plane.dist_to_plane(from_b);
283 if (dist_a >= 0.0f && dist_b >= 0.0f) {
288 if (collide_cat.is_debug()) {
296 new_entry->set_surface_normal(normal);
299 LVector3 from_direction = from_b - from_a;
300 if (_plane.intersects_line(t, from_a, from_direction)) {
302 if (t >= 0.0f && t <= 1.0f) {
304 new_entry->set_surface_point(from_a + t * from_direction);
308 if (dist_a < dist_b) {
310 new_entry->set_interior_point(from_a);
312 }
else if (dist_b < dist_a) {
314 new_entry->set_interior_point(from_b);
318 new_entry->set_interior_point((from_a + from_b) * 0.5);
332 test_intersection_from_parabola(
const CollisionEntry &entry)
const {
334 DCAST_INTO_R(parabola, entry.
get_from(), NULL);
336 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
340 local_p.
xform(wrt_mat);
343 if (_plane.dist_to_plane(local_p.calc_point(parabola->
get_t1())) < 0.0f) {
350 if (!get_plane().intersects_parabola(t1, t2, local_p)) {
356 if (t1 >= parabola->
get_t1() && t1 <= parabola->
get_t2()) {
357 if (t2 >= parabola->
get_t1() && t2 <= parabola->
get_t2()) {
366 }
else if (t2 >= parabola->
get_t1() && t2 <= parabola->
get_t2()) {
376 if (collide_cat.is_debug()) {
383 LPoint3 into_intersection_point = local_p.calc_point(t);
387 new_entry->set_surface_normal(normal);
388 new_entry->set_surface_point(into_intersection_point);
399 void CollisionPlane::
401 if (collide_cat.is_debug()) {
403 <<
"Recomputing viz for " << *
this <<
"\n";
423 PN_stdfloat D = _plane[3];
425 if (fabs(normal[0]) > fabs(normal[1]) &&
426 fabs(normal[0]) > fabs(normal[2])) {
428 cp.set(-D / normal[0], 0.0f, 0.0f);
429 p1 =
LPoint3(-(normal[1] + normal[2] + D)/normal[0], 1.0f, 1.0f) - cp;
431 }
else if (fabs(normal[1]) > fabs(normal[2])) {
433 cp.set(0.0f, -D / normal[1], 0.0f);
434 p1 =
LPoint3(1.0f, -(normal[0] + normal[2] + D)/normal[1], 1.0f) - cp;
438 cp.set(0.0f, 0.0f, -D / normal[2]);
439 p1 =
LPoint3(1.0f, 1.0f, -(normal[0] + normal[1] + D)/normal[2]) - cp;
443 p2 = cross(normal, p1);
444 p3 = cross(normal, p2);
445 p4 = cross(normal, p3);
447 static const double plane_scale = 10.0;
450 (
"collision", GeomVertexFormat::get_v3(),
460 body->add_consecutive_vertices(0, 4);
461 body->close_primitive();
464 border->add_consecutive_vertices(0, 4);
465 border->add_vertex(0);
466 border->close_primitive();
469 geom1->add_primitive(body);
472 geom2->add_primitive(border);
474 _viz_geom->add_geom(geom1, get_solid_viz_state());
475 _viz_geom->add_geom(geom2, get_wireframe_viz_state());
477 _bounds_viz_geom->add_geom(geom1, get_solid_bounds_viz_state());
478 _bounds_viz_geom->add_geom(geom2, get_wireframe_bounds_viz_state());
491 _plane.write_datagram(me);
502 void CollisionPlane::
505 CollisionSolid::fillin(scan, manager);
506 _plane.read_datagram(scan);
521 parse_params(params, scan, manager);
522 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.
const LParabola & get_parabola() const
Returns the parabola specified by this solid.
PN_stdfloat get_t1() const
Returns the starting point on the parabola.
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...
An infinite ray, with a specific origin and direction.
NodePath get_into_node_path() const
Returns the NodePath that represents the specific CollisionNode or GeomNode instance that was collide...
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
PN_stdfloat get_t2() const
Returns the ending point on the parabola.
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).
Defines a series of triangle fans.
Base class for objects that can be written to and read from Bam files.
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
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.
static const LPoint3f & origin(CoordinateSystem cs=CS_default)
Returns the origin of the indicated coordinate system.
static TypedWritable * make_CollisionPlane(const FactoryParams ¶ms)
Factory method to generate a CollisionPlane object.
This funny bounding volume is an infinite plane that divides space into two regions: the part behind ...
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.
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.
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...
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. ...
virtual PStatCollector & get_test_pcollector()
Returns a PStatCollector that is used to count the number of intersection tests made against a solid ...
LVecBase4f xform(const LVecBase4f &v) const
4-component vector or point times matrix.
virtual PStatCollector & get_volume_pcollector()
Returns a PStatCollector that is used to count the number of bounding volume tests made against a sol...
void register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
An infinite line, similar to a CollisionRay, except that it extends in both directions.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
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.
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. ...
NodePath get_from_node_path() const
Returns the NodePath that represents the CollisionNode that contains the CollisionSolid that triggere...
TypeHandle is the identifier used to differentiate C++ class types.
bool get_respect_effective_normal() const
See set_respect_effective_normal().
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 ...
const CollisionSolid * get_from() const
Returns the CollisionSolid pointer for the particular solid that triggered this collision.