40   "Collision Volumes:CollisionSphere");
    42   "Collision Tests:CollisionSphere");
    58   return entry.
get_into()->test_intersection_from_sphere(entry);
    64 void CollisionSphere::
    65 xform(
const LMatrix4 &mat) {
    66   _center = _center * mat;
    70   LVector3 radius_v = LVector3(_radius, 0.0f, 0.0f) * mat;
    71   _radius = length(radius_v);
    73   mark_internal_bounds_stale();
    92   return _volume_pcollector;
   101   return _test_pcollector;
   107 void CollisionSphere::
   108 output(std::ostream &out)
 const {
   109   out << 
"sphere, c (" << get_center() << 
"), r " << get_radius();
   116 compute_internal_bounds()
 const {
   124 test_intersection_from_sphere(
const CollisionEntry &entry)
 const {
   126   DCAST_INTO_R(sphere, entry.
get_from(), 
nullptr);
   130   const LMatrix4 &wrt_mat = wrt_space->get_mat();
   132   LPoint3 from_b = sphere->get_center() * wrt_mat;
   134   LPoint3 into_center(get_center());
   135   PN_stdfloat into_radius(get_radius());
   137   LVector3 from_radius_v =
   138     LVector3(sphere->get_radius(), 0.0f, 0.0f) * wrt_mat;
   139   PN_stdfloat from_radius = length(from_radius_v);
   141   LPoint3 into_intersection_point(from_b);
   143   LPoint3 contact_point(into_intersection_point);
   144   PN_stdfloat actual_t = 0.0f;
   146   LVector3 vec = from_b - into_center;
   147   PN_stdfloat dist2 = dot(vec, vec);
   148   if (dist2 > (into_radius + from_radius) * (into_radius + from_radius)) {
   152     LPoint3 from_a = sphere->get_center() * wrt_prev_space->get_mat();
   154     if (!from_a.almost_equal(from_b)) {
   155       LVector3 from_direction = from_b - from_a;
   156       if (!intersects_line(t1, t2, from_a, from_direction, from_radius)) {
   161       if (t2 < 0.0 || t1 > 1.0) {
   168       actual_t = min(1.0, max(0.0, t1));
   169       contact_point = from_a + actual_t * (from_b - from_a);
   174         into_intersection_point = from_a;
   178         into_intersection_point = from_a + t1 * from_direction;
   186   if (collide_cat.is_debug()) {
   193   LPoint3 from_center = sphere->get_center() * wrt_mat;
   195   LVector3 surface_normal;
   196   LVector3 v(into_intersection_point - into_center);
   197   PN_stdfloat vec_length = v.length();
   198   if (IS_NEARLY_ZERO(vec_length)) {
   202     surface_normal.set(1.0, 0.0, 0.0);
   204     surface_normal = v / vec_length;
   209   LVector3 contact_normal;
   210   LVector3 v2 = contact_point - into_center;
   211   PN_stdfloat v2_len = v2.length();
   212   if (IS_NEARLY_ZERO(v2_len)) {
   216     contact_normal.set(1.0, 0.0, 0.0);
   218     contact_normal = v2 / v2_len;
   221   new_entry->set_surface_normal(eff_normal);
   222   new_entry->set_surface_point(into_center + surface_normal * into_radius);
   223   new_entry->set_interior_point(from_center - surface_normal * from_radius);
   224   new_entry->set_contact_pos(contact_point);
   225   new_entry->set_contact_normal(contact_normal);
   226   new_entry->set_t(actual_t);
   237   DCAST_INTO_R(line, entry.
get_from(), 
nullptr);
   239   const LMatrix4 &wrt_mat = entry.get_wrt_mat();
   241   LPoint3 from_origin = line->get_origin() * wrt_mat;
   242   LVector3 from_direction = line->get_direction() * wrt_mat;
   245   if (!intersects_line(t1, t2, from_origin, from_direction, 0.0f)) {
   250   if (collide_cat.is_debug()) {
   257   LPoint3 into_intersection_point = from_origin + t1 * from_direction;
   258   new_entry->set_surface_point(into_intersection_point);
   263     LVector3 normal = into_intersection_point - get_center();
   265     new_entry->set_surface_normal(normal);
   277   DCAST_INTO_R(box, entry.
get_from(), 
nullptr);
   281   const LMatrix4 &wrt_mat = entry.get_inv_wrt_mat();
   283   LPoint3 center = wrt_mat.xform_point(_center);
   284   PN_stdfloat radius_sq = wrt_mat.xform_vec(LVector3(0, 0, _radius)).length_squared();
   286   LPoint3 box_min = box->get_min();
   287   LPoint3 box_max = box->get_max();
   293   if (center[0] < box_min[0]) {
   294     s = center[0] - box_min[0];
   297   } 
else if (center[0] > box_max[0]) {
   298     s = center[0] - box_max[0];
   302   if (center[1] < box_min[1]) {
   303     s = center[1] - box_min[1];
   306   } 
else if (center[1] > box_max[1]) {
   307     s = center[1] - box_max[1];
   311   if (center[2] < box_min[2]) {
   312     s = center[2] - box_min[2];
   315   } 
else if (center[2] > box_max[2]) {
   316     s = center[2] - box_max[2];
   324   if (collide_cat.is_debug()) {
   333   LPoint3 interior = entry.get_wrt_mat().xform_point(center.fmax(box_min).fmin(box_max));
   334   new_entry->set_interior_point(interior);
   337   LVector3 normal = interior - _center;
   339   new_entry->set_surface_point(_center + normal * _radius);
   340   new_entry->set_surface_normal(
   353   DCAST_INTO_R(ray, entry.
get_from(), 
nullptr);
   355   const LMatrix4 &wrt_mat = entry.get_wrt_mat();
   357   LPoint3 from_origin = ray->get_origin() * wrt_mat;
   358   LVector3 from_direction = ray->get_direction() * wrt_mat;
   361   if (!intersects_line(t1, t2, from_origin, from_direction, 0.0f)) {
   373   if (collide_cat.is_debug()) {
   380   LPoint3 into_intersection_point = from_origin + t1 * from_direction;
   381   new_entry->set_surface_point(into_intersection_point);
   386     LVector3 normal = into_intersection_point - get_center();
   388     new_entry->set_surface_normal(normal);
   398 test_intersection_from_segment(
const CollisionEntry &entry)
 const {
   400   DCAST_INTO_R(segment, entry.
get_from(), 
nullptr);
   402   const LMatrix4 &wrt_mat = entry.get_wrt_mat();
   404   LPoint3 from_a = segment->get_point_a() * wrt_mat;
   405   LPoint3 from_b = segment->get_point_b() * wrt_mat;
   406   LVector3 from_direction = from_b - from_a;
   409   if (!intersects_line(t1, t2, from_a, from_direction, 0.0f)) {
   414   if (t2 < 0.0 || t1 > 1.0) {
   422   if (collide_cat.is_debug()) {
   429   LPoint3 into_intersection_point = from_a + t1 * from_direction;
   430   new_entry->set_surface_point(into_intersection_point);
   435     LVector3 normal = into_intersection_point - get_center();
   437     new_entry->set_surface_normal(normal);
   447 test_intersection_from_capsule(
const CollisionEntry &entry)
 const {
   449   DCAST_INTO_R(capsule, entry.
get_from(), 
nullptr);
   451   const LMatrix4 &wrt_mat = entry.get_wrt_mat();
   453   LPoint3 from_a = capsule->get_point_a() * wrt_mat;
   454   LPoint3 from_b = capsule->get_point_b() * wrt_mat;
   455   LVector3 from_direction = from_b - from_a;
   457   LVector3 from_radius_v =
   458     LVector3(capsule->get_radius(), 0.0f, 0.0f) * wrt_mat;
   459   PN_stdfloat from_radius = length(from_radius_v);
   462   if (!intersects_line(t1, t2, from_a, from_direction, from_radius)) {
   467   if (t2 < 0.0 || t1 > 1.0) {
   473   PN_stdfloat t = (t1 + t2) * (PN_stdfloat)0.5;
   474   t = max(t, (PN_stdfloat)0.0);
   475   t = min(t, (PN_stdfloat)1.0);
   476   LPoint3 inner_point = from_a + t * from_direction;
   478   if (collide_cat.is_debug()) {
   485   LVector3 normal = inner_point - get_center();
   487   new_entry->set_surface_point(get_center() + normal * get_radius());
   488   new_entry->set_interior_point(inner_point - normal * from_radius);
   493     new_entry->set_surface_normal(normal);
   503 test_intersection_from_parabola(
const CollisionEntry &entry)
 const {
   505   DCAST_INTO_R(parabola, entry.
get_from(), 
nullptr);
   507   const LMatrix4 &wrt_mat = entry.get_wrt_mat();
   511   local_p.xform(wrt_mat);
   514   if (!intersects_parabola(t, local_p, parabola->
get_t1(), parabola->
get_t2(),
   515                            local_p.calc_point(parabola->
get_t1()),
   516                            local_p.calc_point(parabola->
get_t2()))) {
   521   if (collide_cat.is_debug()) {
   528   LPoint3 into_intersection_point = local_p.calc_point(t);
   529   new_entry->set_surface_point(into_intersection_point);
   534     LVector3 normal = into_intersection_point - get_center();
   536     new_entry->set_surface_normal(normal);
   546 void CollisionSphere::
   548   if (collide_cat.is_debug()) {
   550       << 
"Recomputing viz for " << *
this << 
"\n";
   553   static const int num_slices = 16;
   554   static const int num_stacks = 8;
   562   for (
int sl = 0; sl < num_slices; ++sl) {
   563     PN_stdfloat longitude0 = (PN_stdfloat)sl / (PN_stdfloat)num_slices;
   564     PN_stdfloat longitude1 = (PN_stdfloat)(sl + 1) / (PN_stdfloat)num_slices;
   565     vertex.add_data3(compute_point(0.0, longitude0));
   566     for (
int st = 1; st < num_stacks; ++st) {
   567       PN_stdfloat latitude = (PN_stdfloat)st / (PN_stdfloat)num_stacks;
   568       vertex.add_data3(compute_point(latitude, longitude0));
   569       vertex.add_data3(compute_point(latitude, longitude1));
   571     vertex.add_data3(compute_point(1.0, longitude0));
   573     strip->add_next_vertices(num_stacks * 2);
   574     strip->close_primitive();
   578   geom->add_primitive(strip);
   580   _viz_geom->add_geom(geom, get_solid_viz_state());
   581   _bounds_viz_geom->add_geom(geom, get_solid_bounds_viz_state());
   592 bool CollisionSphere::
   593 intersects_line(
double &t1, 
double &t2,
   594                 const LPoint3 &from, 
const LVector3 &delta,
   595                 PN_stdfloat inflate_radius)
 const {
   621   double A = dot(delta, delta);
   623   nassertr(A != 0.0, 
false);
   625   LVector3 fc = from - get_center();
   626   double B = 2.0f* dot(delta, fc);
   627   double fc_d2 = dot(fc, fc);
   628   double radius = get_radius() + inflate_radius;
   629   double C = fc_d2 - radius * radius;
   631   double radical = B*B - 4.0*A*C;
   633   if (IS_NEARLY_ZERO(radical)) {
   635     t1 = t2 = -B /(2.0*A);
   638   } 
else if (radical < 0.0) {
   643   double reciprocal_2A = 1.0/(2.0*A);
   644   double sqrt_radical = sqrtf(radical);
   645   t1 = ( -B - sqrt_radical ) * reciprocal_2A;
   646   t2 = ( -B + sqrt_radical ) * reciprocal_2A;
   659 bool CollisionSphere::
   660 intersects_parabola(
double &t, 
const LParabola ¶bola,
   661                     double t1, 
double t2,
   662                     const LPoint3 &p1, 
const LPoint3 &p2)
 const {
   665     if ((p1 - _center).length_squared() > _radius * _radius) {
   683   double tmid = (t1 + t2) * 0.5;
   684   if (tmid != t1 && tmid != t2) {
   685     LPoint3 pmid = parabola.calc_point(tmid);
   686     LPoint3 pmid2 = (p1 + p2) * 0.5f;
   688     if ((pmid - pmid2).length_squared() > 0.001f) {
   690       if (intersects_parabola(t, parabola, t1, tmid, p1, pmid)) {
   693       return intersects_parabola(t, parabola, tmid, t2, pmid, p2);
   699   if (!intersects_line(t1a, t2a, p1, p2 - p1, 0.0f)) {
   703   if (t2a < 0.0 || t1a > 1.0) {
   716 LVertex CollisionSphere::
   717 compute_point(PN_stdfloat latitude, PN_stdfloat longitude)
 const {
   719   csincos(latitude * MathNumbers::pi, &s1, &c1);
   722   csincos(longitude * 2.0f * MathNumbers::pi, &s2, &c2);
   724   LVertex p(s1 * c2, s1 * s2, c1);
   725   return p * get_radius() + get_center();
   743   _center.write_datagram(me);
   757   me->fillin(scan, manager);
   766 void CollisionSphere::
   768   CollisionSolid::fillin(scan, manager);
   769   _center.read_datagram(scan);
 get_t2
Returns the ending point on the parabola.
 
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
 
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.
 
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.
 
PN_stdfloat get_stdfloat()
Extracts either a 32-bit or a 64-bit floating-point number, according to Datagram::set_stdfloat_doubl...
 
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 void write_datagram(BamWriter *manager, Datagram &me)
Function to write the important information in the particular object to a Datagram.
 
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...
 
static void register_with_read_factory()
Factory method to generate a CollisionSphere object.
 
The abstract base class for all things that can collide with other things in the world,...
 
virtual PStatCollector & get_volume_pcollector()
Returns a PStatCollector that is used to count the number of bounding volume tests made against a sol...
 
This defines a bounding sphere, consisting of a center and a radius.
 
A cuboid collision volume or object.
 
Base class for objects that can be written to and read from Bam files.
 
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.
 
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
 
Defines a series of triangle strips.
 
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.
 
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().
 
void add_stdfloat(PN_stdfloat value)
Adds either a 32-bit or a 64-bit floating-point number, according to set_stdfloat_double().
 
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.
 
void parse_params(const FactoryParams ¶ms, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
 
A finite line segment, with two specific endpoints but no thickness.
 
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
 
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.
 
An instance of this class is passed to the Factory when requesting it to do its business and construc...
 
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.
 
PT(CollisionEntry) CollisionSphere
Transforms the solid by the indicated matrix.
 
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.
 
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
 
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
 
get_into
Returns the CollisionSolid pointer for the particular solid was collided into.
 
get_from
Returns the CollisionSolid pointer for the particular solid that triggered this collision.
 
This defines a parabolic arc, or subset of an arc, similar to the path of a projectile or falling obj...
 
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.
 
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
 
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
 
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.