15 #include "collisionInvSphere.h"
16 #include "collisionSphere.h"
17 #include "collisionLine.h"
18 #include "collisionRay.h"
19 #include "collisionSegment.h"
20 #include "collisionHandler.h"
21 #include "collisionEntry.h"
22 #include "config_collide.h"
23 #include "omniBoundingVolume.h"
25 #include "datagramIterator.h"
26 #include "bamReader.h"
27 #include "bamWriter.h"
28 #include "nearly_zero.h"
30 #include "geomTristrips.h"
31 #include "geomVertexWriter.h"
33 PStatCollector CollisionInvSphere::_volume_pcollector(
"Collision Volumes:CollisionInvSphere");
34 PStatCollector CollisionInvSphere::_test_pcollector(
"Collision Tests:CollisionInvSphere");
54 report_undefined_from_intersection(get_type());
67 return _volume_pcollector;
79 return _test_pcollector;
87 void CollisionInvSphere::
88 output(ostream &out)
const {
89 out <<
"invsphere, c (" << get_center() <<
"), r " << get_radius();
98 compute_internal_bounds()
const {
110 test_intersection_from_sphere(const CollisionEntry &entry)
const {
112 DCAST_INTO_R(sphere, entry.get_from(), 0);
114 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
116 LPoint3 from_center = sphere->get_center() * wrt_mat;
118 LVector3(sphere->get_radius(), 0.0f, 0.0f) * wrt_mat;
119 PN_stdfloat from_radius = length(from_radius_v);
121 LPoint3 into_center = get_center();
122 PN_stdfloat into_radius = get_radius();
124 LVector3 vec = from_center - into_center;
125 PN_stdfloat dist2 = dot(vec, vec);
126 if (dist2 < (into_radius - from_radius) * (into_radius - from_radius)) {
131 if (collide_cat.is_debug()) {
133 <<
"intersection detected from " << entry.get_from_node_path()
134 <<
" into " << entry.get_into_node_path() <<
"\n";
136 PT(CollisionEntry) new_entry = new CollisionEntry(entry);
139 PN_stdfloat vec_length = vec.length();
140 if (IS_NEARLY_ZERO(vec_length)) {
144 surface_normal.set(1.0, 0.0, 0.0);
146 surface_normal = vec / -vec_length;
151 new_entry->set_surface_normal(normal);
152 new_entry->set_surface_point(into_center - surface_normal * into_radius);
153 new_entry->set_interior_point(from_center - surface_normal * from_radius);
164 test_intersection_from_line(const CollisionEntry &entry)
const {
166 DCAST_INTO_R(line, entry.get_from(), 0);
168 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
170 LPoint3 from_origin = line->get_origin() * wrt_mat;
171 LVector3 from_direction = line->get_direction() * wrt_mat;
174 if (!intersects_line(t1, t2, from_origin, from_direction, 0.0f)) {
180 if (collide_cat.is_debug()) {
182 <<
"intersection detected from " << entry.get_from_node_path()
183 <<
" into " << entry.get_into_node_path() <<
"\n";
185 PT(CollisionEntry) new_entry = new CollisionEntry(entry);
187 LPoint3 into_intersection_point = from_origin + t2 * from_direction;
188 new_entry->set_surface_point(into_intersection_point);
190 if (has_effective_normal() && line->get_respect_effective_normal()) {
191 new_entry->set_surface_normal(get_effective_normal());
193 LVector3 normal = into_intersection_point - get_center();
195 new_entry->set_surface_normal(-normal);
207 test_intersection_from_ray(const CollisionEntry &entry)
const {
209 DCAST_INTO_R(ray, entry.get_from(), 0);
211 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
213 LPoint3 from_origin = ray->get_origin() * wrt_mat;
214 LVector3 from_direction = ray->get_direction() * wrt_mat;
217 if (!intersects_line(t1, t2, from_origin, from_direction, 0.0f)) {
225 if (collide_cat.is_debug()) {
227 <<
"intersection detected from " << entry.get_from_node_path()
228 <<
" into " << entry.get_into_node_path() <<
"\n";
230 PT(CollisionEntry) new_entry = new CollisionEntry(entry);
232 LPoint3 into_intersection_point;
233 into_intersection_point = from_origin + t2 * from_direction;
234 new_entry->set_surface_point(into_intersection_point);
236 if (has_effective_normal() && ray->get_respect_effective_normal()) {
237 new_entry->set_surface_normal(get_effective_normal());
239 LVector3 normal = into_intersection_point - get_center();
241 new_entry->set_surface_normal(-normal);
253 test_intersection_from_segment(const CollisionEntry &entry)
const {
255 DCAST_INTO_R(segment, entry.get_from(), 0);
257 const LMatrix4 &wrt_mat = entry.get_wrt_mat();
259 LPoint3 from_a = segment->get_point_a() * wrt_mat;
260 LPoint3 from_b = segment->get_point_b() * wrt_mat;
261 LVector3 from_direction = from_b - from_a;
264 if (!intersects_line(t1, t2, from_a, from_direction, 0.0f)) {
275 }
else if (t1 >= 1.0) {
279 }
else if (t2 <= 1.0) {
283 }
else if (t1 >= 0.0) {
294 if (collide_cat.is_debug()) {
296 <<
"intersection detected from " << entry.get_from_node_path()
297 <<
" into " << entry.get_into_node_path() <<
"\n";
299 PT(CollisionEntry) new_entry = new CollisionEntry(entry);
301 LPoint3 into_intersection_point = from_a + t * from_direction;
302 new_entry->set_surface_point(into_intersection_point);
304 if (has_effective_normal() && segment->get_respect_effective_normal()) {
305 new_entry->set_surface_normal(get_effective_normal());
307 LVector3 normal = into_intersection_point - get_center();
309 new_entry->set_surface_normal(-normal);
321 void CollisionInvSphere::
323 if (collide_cat.is_debug()) {
325 <<
"Recomputing viz for " << *
this <<
"\n";
328 static const int num_slices = 16;
329 static const int num_stacks = 8;
332 ("collision", GeomVertexFormat::get_v3(),
337 for (
int sl = 0; sl < num_slices; ++sl) {
338 PN_stdfloat longitude0 = (PN_stdfloat)sl / (PN_stdfloat)num_slices;
339 PN_stdfloat longitude1 = (PN_stdfloat)(sl + 1) / (PN_stdfloat)num_slices;
340 vertex.add_data3(compute_point(0.0, longitude0));
341 for (
int st = 1; st < num_stacks; ++st) {
342 PN_stdfloat latitude = (PN_stdfloat)st / (PN_stdfloat)num_stacks;
343 vertex.add_data3(compute_point(latitude, longitude1));
344 vertex.add_data3(compute_point(latitude, longitude0));
346 vertex.add_data3(compute_point(1.0, longitude0));
349 strip->close_primitive();
353 geom->add_primitive(strip);
355 _viz_geom->add_geom(geom, get_solid_viz_state());
390 parse_params(params, scan, manager);
391 me->fillin(scan, manager);
403 void CollisionInvSphere::
405 CollisionSphere::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.
bool get_respect_effective_normal() const
See set_respect_effective_normal().
virtual void write_datagram(BamWriter *manager, Datagram &me)
Function to write the important information in the particular object to a Datagram.
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).
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 ...
Defines a series of triangle strips.
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.
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...
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 register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
static void register_with_read_factory()
Factory method to generate a CollisionInvSphere object.
void add_next_vertices(int num_vertices)
Adds the next n vertices in sequence, beginning from the last vertex added to the primitive + 1...
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.
virtual PStatCollector & get_volume_pcollector()
Returns a PStatCollector that is used to count the number of bounding volume tests made against a sol...
This is a special kind of GeometricBoundingVolume that fills all of space.
A class to retrieve the individual data elements previously stored in a Datagram. ...
virtual void write_datagram(BamWriter *manager, Datagram &me)
Function to write the important information in the particular object to 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 ...
An inverted sphere: this is a sphere whose collision surface is the inside surface of the sphere...
virtual PStatCollector & get_test_pcollector()
Returns a PStatCollector that is used to count the number of intersection tests made against a solid ...