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;
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(), 0);
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()) {
148 <<
"intersection detected from " << entry.get_from_node_path()
149 <<
" into " << entry.get_into_node_path() <<
"\n";
154 has_effective_normal() && sphere->get_respect_effective_normal())
155 ? get_effective_normal() : get_normal();
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(), 0);
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()) {
194 <<
"intersection detected from " << entry.get_from_node_path()
195 <<
" into " << entry.get_into_node_path() <<
"\n";
199 LPoint3 into_intersection_point = from_origin + t * from_direction;
202 (has_effective_normal() && line->get_respect_effective_normal())
203 ? get_effective_normal() : get_normal();
205 new_entry->set_surface_normal(normal);
206 new_entry->set_surface_point(into_intersection_point);
219 DCAST_INTO_R(ray, entry.get_from(), 0);
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()) {
248 <<
"intersection detected from " << entry.get_from_node_path()
249 <<
" into " << entry.get_into_node_path() <<
"\n";
253 LPoint3 into_intersection_point = from_origin + t * from_direction;
256 (has_effective_normal() && ray->get_respect_effective_normal())
257 ? get_effective_normal() : get_normal();
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(), 0);
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()) {
290 <<
"intersection detected from " << entry.get_from_node_path()
291 <<
" into " << entry.get_into_node_path() <<
"\n";
295 LVector3 normal = (has_effective_normal() && segment->get_respect_effective_normal()) ? get_effective_normal() : get_normal();
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(), 0);
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()) {
378 <<
"intersection detected from " << entry.get_from_node_path()
379 <<
" into " << entry.get_into_node_path() <<
"\n";
383 LPoint3 into_intersection_point = local_p.calc_point(t);
385 LVector3 normal = (has_effective_normal() && parabola->get_respect_effective_normal()) ? get_effective_normal() : get_normal();
387 new_entry->set_surface_normal(normal);
388 new_entry->set_surface_point(into_intersection_point);
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(),
454 vertex.add_data3(cp + p1 * plane_scale);
455 vertex.add_data3(cp + p2 * plane_scale);
456 vertex.add_data3(cp + p3 * plane_scale);
457 vertex.add_data3(cp + p4 * plane_scale);
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);
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.
virtual LPoint3 get_collision_origin() const
Returns the point in space deemed to be the "origin" of the solid for collision purposes.
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).
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.
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...
PN_stdfloat get_t2() const
Returns the ending point on the parabola.
virtual PStatCollector & get_test_pcollector()
Returns a PStatCollector that is used to count the number of intersection tests made against a solid ...
const LParabola & get_parabola() const
Returns the parabola specified by this solid.
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.
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. ...
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 ...