Panda3D

collisionSolid.cxx

00001 // Filename: collisionSolid.cxx
00002 // Created by:  drose (24Apr00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "collisionSolid.h"
00016 #include "config_collide.h"
00017 #include "collisionSphere.h"
00018 #include "collisionLine.h"
00019 #include "collisionRay.h"
00020 #include "collisionSegment.h"
00021 #include "collisionParabola.h"
00022 #include "collisionBox.h"
00023 #include "collisionEntry.h"
00024 #include "boundingSphere.h"
00025 #include "datagram.h"
00026 #include "datagramIterator.h"
00027 #include "bamReader.h"
00028 #include "bamWriter.h"
00029 #include "indent.h"
00030 #include "cullFaceAttrib.h"
00031 #include "colorAttrib.h"
00032 #include "renderModeAttrib.h"
00033 #include "transparencyAttrib.h"
00034 #include "geomNode.h"
00035 
00036 PStatCollector CollisionSolid::_volume_pcollector(
00037   "Collision Volumes:CollisionSolid");
00038 PStatCollector CollisionSolid::_test_pcollector(
00039   "Collision Tests:CollisionSolid");
00040 TypeHandle CollisionSolid::_type_handle;
00041 
00042 ////////////////////////////////////////////////////////////////////
00043 //     Function: CollisionSolid::Constructor
00044 //       Access: Public
00045 //  Description:
00046 ////////////////////////////////////////////////////////////////////
00047 CollisionSolid::
00048 CollisionSolid() : _lock("CollisionSolid") {
00049   _flags = F_viz_geom_stale | F_tangible | F_internal_bounds_stale;
00050 }
00051 
00052 ////////////////////////////////////////////////////////////////////
00053 //     Function: CollisionSolid::Copy Constructor
00054 //       Access: Public
00055 //  Description:
00056 ////////////////////////////////////////////////////////////////////
00057 CollisionSolid::
00058 CollisionSolid(const CollisionSolid &copy) :
00059   CopyOnWriteObject(copy),
00060   _effective_normal(copy._effective_normal),
00061   _internal_bounds(copy._internal_bounds),
00062   _flags(copy._flags),
00063   _lock("CollisionSolid")
00064 {
00065   _flags |= F_viz_geom_stale;
00066 }
00067 
00068 ////////////////////////////////////////////////////////////////////
00069 //     Function: CollisionSolid::Destructor
00070 //       Access: Public, Virtual
00071 //  Description:
00072 ////////////////////////////////////////////////////////////////////
00073 CollisionSolid::
00074 ~CollisionSolid() {
00075 }
00076 
00077 ////////////////////////////////////////////////////////////////////
00078 //     Function: CollisionSolid::make_cow_copy
00079 //       Access: Protected, Virtual
00080 //  Description: Required to implement CopyOnWriteObject.
00081 ////////////////////////////////////////////////////////////////////
00082 PT(CopyOnWriteObject) CollisionSolid::
00083 make_cow_copy() {
00084   return make_copy();
00085 }
00086 
00087 ////////////////////////////////////////////////////////////////////
00088 //     Function: CollisionSolid::get_bounds
00089 //       Access: Protected
00090 //  Description: Returns the solid's bounding volume.
00091 ////////////////////////////////////////////////////////////////////
00092 CPT(BoundingVolume) CollisionSolid::
00093 get_bounds() const {
00094   LightMutexHolder holder(_lock);
00095   if (_flags & F_internal_bounds_stale) {
00096     ((CollisionSolid *)this)->_internal_bounds = compute_internal_bounds();
00097     ((CollisionSolid *)this)->_flags &= ~F_internal_bounds_stale;
00098   }
00099   return _internal_bounds;
00100 }
00101 
00102 ////////////////////////////////////////////////////////////////////
00103 //     Function: CollisionSolid::set_bounds
00104 //       Access: Protected
00105 //  Description: Returns the solid's bounding volume.
00106 ////////////////////////////////////////////////////////////////////
00107 void CollisionSolid::
00108 set_bounds(const BoundingVolume &bounding_volume) {
00109   LightMutexHolder holder(_lock);
00110   ((CollisionSolid *)this)->_internal_bounds = bounding_volume.make_copy();
00111   ((CollisionSolid *)this)->_flags &= ~F_internal_bounds_stale;
00112 }
00113 
00114 ////////////////////////////////////////////////////////////////////
00115 //     Function: CollisionSolid::test_intersection
00116 //       Access: Public, Virtual
00117 //  Description: Tests for a collision between this object (which is
00118 //               also the "from" object in the entry) and the "into"
00119 //               object.  If a collision is detected, returns a new
00120 //               CollisionEntry object that records the collision;
00121 //               otherwise, returns NULL.
00122 ////////////////////////////////////////////////////////////////////
00123 PT(CollisionEntry) CollisionSolid::
00124 test_intersection(const CollisionEntry &) const {
00125   report_undefined_from_intersection(get_type());
00126   return NULL;
00127 }
00128 
00129 ////////////////////////////////////////////////////////////////////
00130 //     Function: CollisionSolid::xform
00131 //       Access: Public, Virtual
00132 //  Description: Transforms the solid by the indicated matrix.
00133 ////////////////////////////////////////////////////////////////////
00134 void CollisionSolid::
00135 xform(const LMatrix4f &mat) {
00136   LightMutexHolder holder(_lock);
00137   if ((_flags & F_effective_normal) != 0) {
00138     _effective_normal = _effective_normal * mat;
00139     _effective_normal.normalize();
00140   }
00141 
00142   _flags |= F_viz_geom_stale | F_internal_bounds_stale;
00143 }
00144 
00145 ////////////////////////////////////////////////////////////////////
00146 //     Function: CollisionSolid::get_viz
00147 //       Access: Public, Virtual
00148 //  Description: Returns a GeomNode that may be rendered to visualize
00149 //               the CollisionSolid.  This is used during the cull
00150 //               traversal to render the CollisionNodes that have been
00151 //               made visible.
00152 ////////////////////////////////////////////////////////////////////
00153 PT(PandaNode) CollisionSolid::
00154 get_viz(const CullTraverser *, const CullTraverserData &, bool bounds_only) const {
00155   LightMutexHolder holder(_lock);
00156   if ((_flags & F_viz_geom_stale) != 0) {
00157     if (_viz_geom == (GeomNode *)NULL) {
00158       ((CollisionSolid *)this)->_viz_geom = new GeomNode("viz");
00159       ((CollisionSolid *)this)->_bounds_viz_geom = new GeomNode("bounds_viz");
00160     } else {
00161       _viz_geom->remove_all_geoms();
00162       _bounds_viz_geom->remove_all_geoms();
00163     }
00164     ((CollisionSolid *)this)->fill_viz_geom();
00165     ((CollisionSolid *)this)->_flags &= ~F_viz_geom_stale;
00166   }
00167 
00168   if (bounds_only) {
00169     return _bounds_viz_geom.p();
00170   } else {
00171     return _viz_geom.p();
00172   }
00173 }
00174 
00175 ////////////////////////////////////////////////////////////////////
00176 //     Function: CollisionSolid::get_volume_pcollector
00177 //       Access: Public, Virtual
00178 //  Description: Returns a PStatCollector that is used to count the
00179 //               number of bounding volume tests made against a solid
00180 //               of this type in a given frame.
00181 ////////////////////////////////////////////////////////////////////
00182 PStatCollector &CollisionSolid::
00183 get_volume_pcollector() {
00184   return _volume_pcollector;
00185 }
00186 
00187 ////////////////////////////////////////////////////////////////////
00188 //     Function: CollisionSolid::get_test_pcollector
00189 //       Access: Public, Virtual
00190 //  Description: Returns a PStatCollector that is used to count the
00191 //               number of intersection tests made against a solid
00192 //               of this type in a given frame.
00193 ////////////////////////////////////////////////////////////////////
00194 PStatCollector &CollisionSolid::
00195 get_test_pcollector() {
00196   return _test_pcollector;
00197 }
00198 
00199 ////////////////////////////////////////////////////////////////////
00200 //     Function: CollisionSolid::output
00201 //       Access: Public, Virtual
00202 //  Description:
00203 ////////////////////////////////////////////////////////////////////
00204 void CollisionSolid::
00205 output(ostream &out) const {
00206   out << get_type();
00207 }
00208 
00209 ////////////////////////////////////////////////////////////////////
00210 //     Function: CollisionSolid::write
00211 //       Access: Public, Virtual
00212 //  Description:
00213 ////////////////////////////////////////////////////////////////////
00214 void CollisionSolid::
00215 write(ostream &out, int indent_level) const {
00216   indent(out, indent_level) << (*this) << "\n";
00217 }
00218 
00219 ////////////////////////////////////////////////////////////////////
00220 //     Function: CollisionSolid::compute_internal_bounds
00221 //       Access: Protected, Virtual
00222 //  Description:
00223 ////////////////////////////////////////////////////////////////////
00224 PT(BoundingVolume) CollisionSolid::
00225 compute_internal_bounds() const {
00226   return new BoundingSphere;
00227 }
00228 
00229 ////////////////////////////////////////////////////////////////////
00230 //     Function: CollisionSolid::test_intersection_from_ds_solid
00231 //       Access: Protected, Virtual
00232 //  Description: This is part of the double-dispatch implementation of
00233 //               test_intersection().  It is called when the "from"
00234 //               object is a DSSolid.
00235 ////////////////////////////////////////////////////////////////////
00236 PT(CollisionEntry) CollisionSolid::
00237 test_intersection_from_ds_solid(const CollisionEntry &) const {
00238   report_undefined_intersection_test(CollisionSphere::get_class_type(),
00239                                      get_type());
00240   return NULL;
00241 }
00242 
00243 ////////////////////////////////////////////////////////////////////
00244 //     Function: CollisionSolid::test_intersection_from_sphere
00245 //       Access: Protected, Virtual
00246 //  Description: This is part of the double-dispatch implementation of
00247 //               test_intersection().  It is called when the "from"
00248 //               object is a sphere.
00249 ////////////////////////////////////////////////////////////////////
00250 PT(CollisionEntry) CollisionSolid::
00251 test_intersection_from_sphere(const CollisionEntry &) const {
00252   report_undefined_intersection_test(CollisionSphere::get_class_type(),
00253                                      get_type());
00254   return NULL;
00255 }
00256 
00257 ////////////////////////////////////////////////////////////////////
00258 //     Function: CollisionSolid::test_intersection_from_line
00259 //       Access: Protected, Virtual
00260 //  Description: This is part of the double-dispatch implementation of
00261 //               test_intersection().  It is called when the "from"
00262 //               object is a line.
00263 ////////////////////////////////////////////////////////////////////
00264 PT(CollisionEntry) CollisionSolid::
00265 test_intersection_from_line(const CollisionEntry &) const {
00266   report_undefined_intersection_test(CollisionLine::get_class_type(),
00267                                      get_type());
00268   return NULL;
00269 }
00270 
00271 ////////////////////////////////////////////////////////////////////
00272 //     Function: CollisionSolid::test_intersection_from_ray
00273 //       Access: Protected, Virtual
00274 //  Description: This is part of the double-dispatch implementation of
00275 //               test_intersection().  It is called when the "from"
00276 //               object is a ray.
00277 ////////////////////////////////////////////////////////////////////
00278 PT(CollisionEntry) CollisionSolid::
00279 test_intersection_from_ray(const CollisionEntry &) const {
00280   report_undefined_intersection_test(CollisionRay::get_class_type(),
00281                                      get_type());
00282   return NULL;
00283 }
00284 
00285 ////////////////////////////////////////////////////////////////////
00286 //     Function: CollisionSolid::test_intersection_from_segment
00287 //       Access: Protected, Virtual
00288 //  Description: This is part of the double-dispatch implementation of
00289 //               test_intersection().  It is called when the "from"
00290 //               object is a segment.
00291 ////////////////////////////////////////////////////////////////////
00292 PT(CollisionEntry) CollisionSolid::
00293 test_intersection_from_segment(const CollisionEntry &) const {
00294   report_undefined_intersection_test(CollisionSegment::get_class_type(),
00295                                      get_type());
00296   return NULL;
00297 }
00298 
00299 ////////////////////////////////////////////////////////////////////
00300 //     Function: CollisionSolid::test_intersection_from_parabola
00301 //       Access: Protected, Virtual
00302 //  Description: This is part of the double-dispatch implementation of
00303 //               test_intersection().  It is called when the "from"
00304 //               object is a parabola.
00305 ////////////////////////////////////////////////////////////////////
00306 PT(CollisionEntry) CollisionSolid::
00307 test_intersection_from_parabola(const CollisionEntry &) const {
00308   report_undefined_intersection_test(CollisionParabola::get_class_type(),
00309                                      get_type());
00310   return NULL;
00311 }
00312 
00313 ////////////////////////////////////////////////////////////////////
00314 //     Function: CollisionSolid::test_intersection_from_box
00315 //       Access: Protected, Virtual
00316 //  Description: This is part of the double-dispatch implementation of
00317 //               test_intersection().  It is called when the "from"
00318 //               object is a box.
00319 ////////////////////////////////////////////////////////////////////
00320 PT(CollisionEntry) CollisionSolid::
00321 test_intersection_from_box(const CollisionEntry &) const {
00322   report_undefined_intersection_test(CollisionBox::get_class_type(),
00323                                      get_type());
00324   return NULL;
00325 }
00326 
00327 
00328 #ifndef NDEBUG
00329 class CollisionSolidUndefinedPair {
00330 public:
00331   CollisionSolidUndefinedPair(TypeHandle a, TypeHandle b) :
00332     _a(a), _b(b)
00333   {}
00334   bool operator < (const CollisionSolidUndefinedPair &other) const {
00335     if (_a != other._a) {
00336       return _a < other._a;
00337     }
00338     return _b < other._b;
00339   }
00340 
00341   TypeHandle _a;
00342   TypeHandle _b;
00343 };
00344 #endif  // NDEBUG
00345 
00346 ////////////////////////////////////////////////////////////////////
00347 //     Function: CollisionSolid::report_undefined_intersection_test
00348 //       Access: Protected, Static
00349 //  Description: Outputs a message the first time an intersection test
00350 //               is attempted that isn't defined, and explains a bit
00351 //               about what it means.
00352 ////////////////////////////////////////////////////////////////////
00353 void CollisionSolid::
00354 report_undefined_intersection_test(TypeHandle from_type, TypeHandle into_type) {
00355 #ifndef NDEBUG
00356   typedef pset<CollisionSolidUndefinedPair> Reported;
00357   static Reported reported;
00358 
00359   if (reported.insert(CollisionSolidUndefinedPair(from_type, into_type)).second) {
00360     collide_cat.error()
00361       << "Invalid attempt to detect collision from " << from_type << " into "
00362       << into_type << "!\n\n"
00363 
00364       "This means that a " << from_type << " object attempted to test for an\n"
00365       "intersection into a " << into_type << " object.  This intersection\n"
00366       "test has not yet been defined; it is possible the " << into_type << "\n"
00367       "object is not intended to be collidable.  Consider calling\n"
00368       "set_into_collide_mask(0) on the " << into_type << " object, or\n"
00369       "set_from_collide_mask(0) on the " << from_type << " object.\n\n";
00370   }
00371 #endif  // NDEBUG
00372 }
00373 
00374 ////////////////////////////////////////////////////////////////////
00375 //     Function: CollisionSolid::report_undefined_from_intersection
00376 //       Access: Protected, Static
00377 //  Description: Outputs a message the first time an intersection test
00378 //               is attempted that isn't defined, and explains a bit
00379 //               about what it means.
00380 ////////////////////////////////////////////////////////////////////
00381 void CollisionSolid::
00382 report_undefined_from_intersection(TypeHandle from_type) {
00383 #ifndef NDEBUG
00384   typedef pset<TypeHandle> Reported;
00385   static Reported reported;
00386 
00387   if (reported.insert(from_type).second) {
00388     collide_cat.error()
00389       << "Invalid attempt to detect collision from " << from_type << "!\n\n"
00390       
00391       "This means that a " << from_type << " object was added to a\n"
00392       "CollisionTraverser as if it were a colliding object.  However,\n"
00393       "no implementation for this kind of object has yet been defined\n"
00394       "to collide with other objects.\n\n";
00395   }
00396 #endif  // NDEBUG
00397 }
00398 
00399 ////////////////////////////////////////////////////////////////////
00400 //     Function: CollisionSolid::write_datagram
00401 //       Access: Public
00402 //  Description: Function to write the important information in
00403 //               the particular object to a Datagram
00404 ////////////////////////////////////////////////////////////////////
00405 void CollisionSolid::
00406 write_datagram(BamWriter *, Datagram &me) {
00407   // For now, we need only 8 bits of flags.  If we need to expand this
00408   // later, we will have to increase the bam version.
00409   LightMutexHolder holder(_lock);
00410   me.add_uint8(_flags);
00411   if ((_flags & F_effective_normal) != 0) {
00412     _effective_normal.write_datagram(me);
00413   }
00414 }
00415 
00416 ////////////////////////////////////////////////////////////////////
00417 //     Function: CollisionSolid::fillin
00418 //       Access: Protected
00419 //  Description: Function that reads out of the datagram (or asks
00420 //               manager to read) all of the data that is needed to
00421 //               re-create this object and stores it in the appropiate
00422 //               place
00423 ////////////////////////////////////////////////////////////////////
00424 void CollisionSolid::
00425 fillin(DatagramIterator &scan, BamReader *manager) {
00426   _flags = scan.get_uint8();
00427   if ((_flags & F_effective_normal) != 0) {
00428     _effective_normal.read_datagram(scan);
00429   }
00430 
00431   // The viz is always stale after reading from a bam file.  So is the
00432   // bounding volume.
00433   _flags |= F_viz_geom_stale | F_internal_bounds_stale;
00434 }
00435 
00436 
00437 ////////////////////////////////////////////////////////////////////
00438 //     Function: CollisionSolid::fill_viz_geom
00439 //       Access: Protected, Virtual
00440 //  Description: Fills the _viz_geom GeomNode up with Geoms suitable
00441 //               for rendering this solid.
00442 ////////////////////////////////////////////////////////////////////
00443 void CollisionSolid::
00444 fill_viz_geom() {
00445 }
00446 
00447 ////////////////////////////////////////////////////////////////////
00448 //     Function: CollisionSolid::get_solid_viz_state
00449 //       Access: Protected
00450 //  Description: Returns a RenderState for rendering collision
00451 //               visualizations in solid.  This automatically returns
00452 //               the appropriate state according to the setting of
00453 //               _tangible.
00454 //
00455 //               Assumes the lock is already held.
00456 ////////////////////////////////////////////////////////////////////
00457 CPT(RenderState) CollisionSolid::
00458 get_solid_viz_state() {
00459   // Once someone asks for this pointer, we hold its reference count
00460   // and never free it.
00461   static CPT(RenderState) base_state = (const RenderState *)NULL;
00462   if (base_state == (const RenderState *)NULL) {
00463     base_state = RenderState::make
00464       (CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise),
00465        RenderModeAttrib::make(RenderModeAttrib::M_filled),
00466        TransparencyAttrib::make(TransparencyAttrib::M_alpha));
00467   }
00468 
00469   if (!do_is_tangible()) {
00470     static CPT(RenderState) intangible_state = (const RenderState *)NULL;
00471     if (intangible_state == (const RenderState *)NULL) {
00472       intangible_state = base_state->add_attrib
00473         (ColorAttrib::make_flat(Colorf(1.0f, 0.3f, 0.5f, 0.5f)));
00474     }
00475     return intangible_state;
00476 
00477   } else if (do_has_effective_normal()) {
00478     static CPT(RenderState) fakenormal_state = (const RenderState *)NULL;
00479     if (fakenormal_state == (const RenderState *)NULL) {
00480       fakenormal_state = base_state->add_attrib
00481         (ColorAttrib::make_flat(Colorf(0.5f, 0.5f, 1.0f, 0.5f)));
00482     }
00483     return fakenormal_state;
00484 
00485   } else {
00486     static CPT(RenderState) tangible_state = (const RenderState *)NULL;
00487     if (tangible_state == (const RenderState *)NULL) {
00488       tangible_state = base_state->add_attrib
00489         (ColorAttrib::make_flat(Colorf(1.0f, 1.0f, 1.0f, 0.5f)));
00490     }
00491     return tangible_state;
00492   }
00493 }
00494 
00495 
00496 ////////////////////////////////////////////////////////////////////
00497 //     Function: CollisionSolid::get_wireframe_viz_state
00498 //       Access: Protected
00499 //  Description: Returns a RenderState for rendering collision
00500 //               visualizations in wireframe.  This automatically returns
00501 //               the appropriate state according to the setting of
00502 //               _tangible.
00503 //
00504 //               Assumes the lock is already held.
00505 ////////////////////////////////////////////////////////////////////
00506 CPT(RenderState) CollisionSolid::
00507 get_wireframe_viz_state() {
00508   // Once someone asks for this pointer, we hold its reference count
00509   // and never free it.
00510   static CPT(RenderState) base_state = (const RenderState *)NULL;
00511   if (base_state == (const RenderState *)NULL) {
00512     base_state = RenderState::make
00513       (CullFaceAttrib::make(CullFaceAttrib::M_cull_none),
00514        RenderModeAttrib::make(RenderModeAttrib::M_wireframe),
00515        TransparencyAttrib::make(TransparencyAttrib::M_none));
00516   }
00517 
00518   if (!do_is_tangible()) {
00519     static CPT(RenderState) intangible_state = (const RenderState *)NULL;
00520     if (intangible_state == (const RenderState *)NULL) {
00521       intangible_state = base_state->add_attrib
00522         (ColorAttrib::make_flat(Colorf(1.0f, 1.0f, 0.0f, 1.0f)));
00523     }
00524     return intangible_state;
00525 
00526   } else if (do_has_effective_normal()) {
00527     static CPT(RenderState) fakenormal_state = (const RenderState *)NULL;
00528     if (fakenormal_state == (const RenderState *)NULL) {
00529       fakenormal_state = base_state->add_attrib
00530         (ColorAttrib::make_flat(Colorf(0.0f, 0.0f, 1.0f, 1.0f)));
00531     }
00532     return fakenormal_state;
00533 
00534   } else {
00535     static CPT(RenderState) tangible_state = (const RenderState *)NULL;
00536     if (tangible_state == (const RenderState *)NULL) {
00537       tangible_state = base_state->add_attrib
00538         (ColorAttrib::make_flat(Colorf(0.0f, 0.0f, 1.0f, 1.0f)));
00539     }
00540     return tangible_state;
00541   }
00542 }
00543 
00544 
00545 ////////////////////////////////////////////////////////////////////
00546 //     Function: CollisionSolid::get_other_viz_state
00547 //       Access: Protected
00548 //  Description: Returns a RenderState for rendering collision
00549 //               visualizations for things that are neither solid nor
00550 //               exactly wireframe, like rays and segments.
00551 //
00552 //               Assumes the lock is already held.
00553 ////////////////////////////////////////////////////////////////////
00554 CPT(RenderState) CollisionSolid::
00555 get_other_viz_state() {
00556   // Once someone asks for this pointer, we hold its reference count
00557   // and never free it.
00558   static CPT(RenderState) base_state = (const RenderState *)NULL;
00559   if (base_state == (const RenderState *)NULL) {
00560     base_state = RenderState::make
00561       (CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise),
00562        RenderModeAttrib::make(RenderModeAttrib::M_filled),
00563        TransparencyAttrib::make(TransparencyAttrib::M_alpha));
00564   }
00565 
00566   // We don't bother to make a distinction here between tangible and
00567   // intangible.
00568   return base_state;
00569 }
00570 
00571 ////////////////////////////////////////////////////////////////////
00572 //     Function: CollisionSolid::get_solid_bounds_viz_state
00573 //       Access: Protected
00574 //  Description: Returns a RenderState for rendering collision
00575 //               visualizations in solid.  This automatically returns
00576 //               the appropriate state according to the setting of
00577 //               _tangible.
00578 //
00579 //               Assumes the lock is already held.
00580 ////////////////////////////////////////////////////////////////////
00581 CPT(RenderState) CollisionSolid::
00582 get_solid_bounds_viz_state() {
00583   // Once someone asks for this pointer, we hold its reference count
00584   // and never free it.
00585   static CPT(RenderState) base_state = (const RenderState *)NULL;
00586   if (base_state == (const RenderState *)NULL) {
00587     base_state = RenderState::make
00588       (CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise),
00589        RenderModeAttrib::make(RenderModeAttrib::M_filled),
00590        TransparencyAttrib::make(TransparencyAttrib::M_alpha));
00591   }
00592 
00593   if (!do_is_tangible()) {
00594     static CPT(RenderState) intangible_state = (const RenderState *)NULL;
00595     if (intangible_state == (const RenderState *)NULL) {
00596       intangible_state = base_state->add_attrib
00597         (ColorAttrib::make_flat(Colorf(1.0f, 1.0f, 0.5f, 0.3f)));
00598     }
00599     return intangible_state;
00600 
00601   } else if (do_has_effective_normal()) {
00602     static CPT(RenderState) fakenormal_state = (const RenderState *)NULL;
00603     if (fakenormal_state == (const RenderState *)NULL) {
00604       fakenormal_state = base_state->add_attrib
00605         (ColorAttrib::make_flat(Colorf(0.5f, 0.5f, 1.0f, 0.3f)));
00606     }
00607     return fakenormal_state;
00608 
00609   } else {
00610     static CPT(RenderState) tangible_state = (const RenderState *)NULL;
00611     if (tangible_state == (const RenderState *)NULL) {
00612       tangible_state = base_state->add_attrib
00613         (ColorAttrib::make_flat(Colorf(1.0f, 1.0f, 0.5f, 0.3f)));
00614     }
00615     return tangible_state;
00616   }
00617 }
00618 
00619 
00620 ////////////////////////////////////////////////////////////////////
00621 //     Function: CollisionSolid::get_wireframe_bounds_viz_state
00622 //       Access: Protected
00623 //  Description: Returns a RenderState for rendering collision
00624 //               visualizations in wireframe.  This automatically returns
00625 //               the appropriate state according to the setting of
00626 //               _tangible.
00627 //
00628 //               Assumes the lock is already held.
00629 ////////////////////////////////////////////////////////////////////
00630 CPT(RenderState) CollisionSolid::
00631 get_wireframe_bounds_viz_state() {
00632   // Once someone asks for this pointer, we hold its reference count
00633   // and never free it.
00634   static CPT(RenderState) base_state = (const RenderState *)NULL;
00635   if (base_state == (const RenderState *)NULL) {
00636     base_state = RenderState::make
00637       (CullFaceAttrib::make(CullFaceAttrib::M_cull_none),
00638        RenderModeAttrib::make(RenderModeAttrib::M_wireframe),
00639        TransparencyAttrib::make(TransparencyAttrib::M_none),
00640        ColorAttrib::make_flat(Colorf(1.0f, 0.0f, 0.0f, 1.0f)));
00641   }
00642 
00643   return base_state;
00644 }
00645 
00646 
00647 ////////////////////////////////////////////////////////////////////
00648 //     Function: CollisionSolid::get_other_bounds_viz_state
00649 //       Access: Protected
00650 //  Description: Returns a RenderState for rendering collision
00651 //               visualizations for things that are neither solid nor
00652 //               exactly wireframe, like rays and segments.
00653 //
00654 //               Assumes the lock is already held.
00655 ////////////////////////////////////////////////////////////////////
00656 CPT(RenderState) CollisionSolid::
00657 get_other_bounds_viz_state() {
00658   // Once someone asks for this pointer, we hold its reference count
00659   // and never free it.
00660   static CPT(RenderState) base_state = (const RenderState *)NULL;
00661   if (base_state == (const RenderState *)NULL) {
00662     base_state = RenderState::make
00663       (CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise),
00664        RenderModeAttrib::make(RenderModeAttrib::M_filled),
00665        TransparencyAttrib::make(TransparencyAttrib::M_alpha));
00666   }
00667 
00668   // We don't bother to make a distinction here between tangible and
00669   // intangible.
00670   return base_state;
00671 }
00672 
 All Classes Functions Variables Enumerations