Panda3D
 All Classes Functions Variables Enumerations
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 LMatrix4 &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_sphere
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 sphere.
00235 ////////////////////////////////////////////////////////////////////
00236 PT(CollisionEntry) CollisionSolid::
00237 test_intersection_from_sphere(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_line
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 line.
00249 ////////////////////////////////////////////////////////////////////
00250 PT(CollisionEntry) CollisionSolid::
00251 test_intersection_from_line(const CollisionEntry &) const {
00252   report_undefined_intersection_test(CollisionLine::get_class_type(),
00253                                      get_type());
00254   return NULL;
00255 }
00256 
00257 ////////////////////////////////////////////////////////////////////
00258 //     Function: CollisionSolid::test_intersection_from_ray
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 ray.
00263 ////////////////////////////////////////////////////////////////////
00264 PT(CollisionEntry) CollisionSolid::
00265 test_intersection_from_ray(const CollisionEntry &) const {
00266   report_undefined_intersection_test(CollisionRay::get_class_type(),
00267                                      get_type());
00268   return NULL;
00269 }
00270 
00271 ////////////////////////////////////////////////////////////////////
00272 //     Function: CollisionSolid::test_intersection_from_segment
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 segment.
00277 ////////////////////////////////////////////////////////////////////
00278 PT(CollisionEntry) CollisionSolid::
00279 test_intersection_from_segment(const CollisionEntry &) const {
00280   report_undefined_intersection_test(CollisionSegment::get_class_type(),
00281                                      get_type());
00282   return NULL;
00283 }
00284 
00285 ////////////////////////////////////////////////////////////////////
00286 //     Function: CollisionSolid::test_intersection_from_parabola
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 parabola.
00291 ////////////////////////////////////////////////////////////////////
00292 PT(CollisionEntry) CollisionSolid::
00293 test_intersection_from_parabola(const CollisionEntry &) const {
00294   report_undefined_intersection_test(CollisionParabola::get_class_type(),
00295                                      get_type());
00296   return NULL;
00297 }
00298 
00299 ////////////////////////////////////////////////////////////////////
00300 //     Function: CollisionSolid::test_intersection_from_box
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 box.
00305 ////////////////////////////////////////////////////////////////////
00306 PT(CollisionEntry) CollisionSolid::
00307 test_intersection_from_box(const CollisionEntry &) const {
00308   report_undefined_intersection_test(CollisionBox::get_class_type(),
00309                                      get_type());
00310   return NULL;
00311 }
00312 
00313 
00314 #ifndef NDEBUG
00315 class CollisionSolidUndefinedPair {
00316 public:
00317   CollisionSolidUndefinedPair(TypeHandle a, TypeHandle b) :
00318     _a(a), _b(b)
00319   {}
00320   bool operator < (const CollisionSolidUndefinedPair &other) const {
00321     if (_a != other._a) {
00322       return _a < other._a;
00323     }
00324     return _b < other._b;
00325   }
00326 
00327   TypeHandle _a;
00328   TypeHandle _b;
00329 };
00330 #endif  // NDEBUG
00331 
00332 ////////////////////////////////////////////////////////////////////
00333 //     Function: CollisionSolid::report_undefined_intersection_test
00334 //       Access: Protected, Static
00335 //  Description: Outputs a message the first time an intersection test
00336 //               is attempted that isn't defined, and explains a bit
00337 //               about what it means.
00338 ////////////////////////////////////////////////////////////////////
00339 void CollisionSolid::
00340 report_undefined_intersection_test(TypeHandle from_type, TypeHandle into_type) {
00341 #ifndef NDEBUG
00342   typedef pset<CollisionSolidUndefinedPair> Reported;
00343   static Reported reported;
00344 
00345   if (reported.insert(CollisionSolidUndefinedPair(from_type, into_type)).second) {
00346     collide_cat.error()
00347       << "Invalid attempt to detect collision from " << from_type << " into "
00348       << into_type << "!\n\n"
00349 
00350       "This means that a " << from_type << " object attempted to test for an\n"
00351       "intersection into a " << into_type << " object.  This intersection\n"
00352       "test has not yet been defined; it is possible the " << into_type << "\n"
00353       "object is not intended to be collidable.  Consider calling\n"
00354       "set_into_collide_mask(0) on the " << into_type << " object, or\n"
00355       "set_from_collide_mask(0) on the " << from_type << " object.\n\n";
00356   }
00357 #endif  // NDEBUG
00358 }
00359 
00360 ////////////////////////////////////////////////////////////////////
00361 //     Function: CollisionSolid::report_undefined_from_intersection
00362 //       Access: Protected, Static
00363 //  Description: Outputs a message the first time an intersection test
00364 //               is attempted that isn't defined, and explains a bit
00365 //               about what it means.
00366 ////////////////////////////////////////////////////////////////////
00367 void CollisionSolid::
00368 report_undefined_from_intersection(TypeHandle from_type) {
00369 #ifndef NDEBUG
00370   typedef pset<TypeHandle> Reported;
00371   static Reported reported;
00372 
00373   if (reported.insert(from_type).second) {
00374     collide_cat.error()
00375       << "Invalid attempt to detect collision from " << from_type << "!\n\n"
00376       
00377       "This means that a " << from_type << " object was added to a\n"
00378       "CollisionTraverser as if it were a colliding object.  However,\n"
00379       "no implementation for this kind of object has yet been defined\n"
00380       "to collide with other objects.\n\n";
00381   }
00382 #endif  // NDEBUG
00383 }
00384 
00385 ////////////////////////////////////////////////////////////////////
00386 //     Function: CollisionSolid::write_datagram
00387 //       Access: Public
00388 //  Description: Function to write the important information in
00389 //               the particular object to a Datagram
00390 ////////////////////////////////////////////////////////////////////
00391 void CollisionSolid::
00392 write_datagram(BamWriter *, Datagram &me) {
00393   // For now, we need only 8 bits of flags.  If we need to expand this
00394   // later, we will have to increase the bam version.
00395   LightMutexHolder holder(_lock);
00396   me.add_uint8(_flags);
00397   if ((_flags & F_effective_normal) != 0) {
00398     _effective_normal.write_datagram(me);
00399   }
00400 }
00401 
00402 ////////////////////////////////////////////////////////////////////
00403 //     Function: CollisionSolid::fillin
00404 //       Access: Protected
00405 //  Description: Function that reads out of the datagram (or asks
00406 //               manager to read) all of the data that is needed to
00407 //               re-create this object and stores it in the appropiate
00408 //               place
00409 ////////////////////////////////////////////////////////////////////
00410 void CollisionSolid::
00411 fillin(DatagramIterator &scan, BamReader *manager) {
00412   _flags = scan.get_uint8();
00413   if ((_flags & F_effective_normal) != 0) {
00414     _effective_normal.read_datagram(scan);
00415   }
00416 
00417   // The viz is always stale after reading from a bam file.  So is the
00418   // bounding volume.
00419   _flags |= F_viz_geom_stale | F_internal_bounds_stale;
00420 }
00421 
00422 
00423 ////////////////////////////////////////////////////////////////////
00424 //     Function: CollisionSolid::fill_viz_geom
00425 //       Access: Protected, Virtual
00426 //  Description: Fills the _viz_geom GeomNode up with Geoms suitable
00427 //               for rendering this solid.
00428 ////////////////////////////////////////////////////////////////////
00429 void CollisionSolid::
00430 fill_viz_geom() {
00431 }
00432 
00433 ////////////////////////////////////////////////////////////////////
00434 //     Function: CollisionSolid::get_solid_viz_state
00435 //       Access: Protected
00436 //  Description: Returns a RenderState for rendering collision
00437 //               visualizations in solid.  This automatically returns
00438 //               the appropriate state according to the setting of
00439 //               _tangible.
00440 //
00441 //               Assumes the lock is already held.
00442 ////////////////////////////////////////////////////////////////////
00443 CPT(RenderState) CollisionSolid::
00444 get_solid_viz_state() {
00445   // Once someone asks for this pointer, we hold its reference count
00446   // and never free it.
00447   static CPT(RenderState) base_state = (const RenderState *)NULL;
00448   if (base_state == (const RenderState *)NULL) {
00449     base_state = RenderState::make
00450       (CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise),
00451        RenderModeAttrib::make(RenderModeAttrib::M_filled),
00452        TransparencyAttrib::make(TransparencyAttrib::M_alpha));
00453   }
00454 
00455   if (!do_is_tangible()) {
00456     static CPT(RenderState) intangible_state = (const RenderState *)NULL;
00457     if (intangible_state == (const RenderState *)NULL) {
00458       intangible_state = base_state->add_attrib
00459         (ColorAttrib::make_flat(LColor(1.0f, 0.3, 0.5f, 0.5f)));
00460     }
00461     return intangible_state;
00462 
00463   } else if (do_has_effective_normal()) {
00464     static CPT(RenderState) fakenormal_state = (const RenderState *)NULL;
00465     if (fakenormal_state == (const RenderState *)NULL) {
00466       fakenormal_state = base_state->add_attrib
00467         (ColorAttrib::make_flat(LColor(0.5f, 0.5f, 1.0f, 0.5f)));
00468     }
00469     return fakenormal_state;
00470 
00471   } else {
00472     static CPT(RenderState) tangible_state = (const RenderState *)NULL;
00473     if (tangible_state == (const RenderState *)NULL) {
00474       tangible_state = base_state->add_attrib
00475         (ColorAttrib::make_flat(LColor(1.0f, 1.0f, 1.0f, 0.5f)));
00476     }
00477     return tangible_state;
00478   }
00479 }
00480 
00481 
00482 ////////////////////////////////////////////////////////////////////
00483 //     Function: CollisionSolid::get_wireframe_viz_state
00484 //       Access: Protected
00485 //  Description: Returns a RenderState for rendering collision
00486 //               visualizations in wireframe.  This automatically returns
00487 //               the appropriate state according to the setting of
00488 //               _tangible.
00489 //
00490 //               Assumes the lock is already held.
00491 ////////////////////////////////////////////////////////////////////
00492 CPT(RenderState) CollisionSolid::
00493 get_wireframe_viz_state() {
00494   // Once someone asks for this pointer, we hold its reference count
00495   // and never free it.
00496   static CPT(RenderState) base_state = (const RenderState *)NULL;
00497   if (base_state == (const RenderState *)NULL) {
00498     base_state = RenderState::make
00499       (CullFaceAttrib::make(CullFaceAttrib::M_cull_none),
00500        RenderModeAttrib::make(RenderModeAttrib::M_wireframe),
00501        TransparencyAttrib::make(TransparencyAttrib::M_none));
00502   }
00503 
00504   if (!do_is_tangible()) {
00505     static CPT(RenderState) intangible_state = (const RenderState *)NULL;
00506     if (intangible_state == (const RenderState *)NULL) {
00507       intangible_state = base_state->add_attrib
00508         (ColorAttrib::make_flat(LColor(1.0f, 1.0f, 0.0f, 1.0f)));
00509     }
00510     return intangible_state;
00511 
00512   } else if (do_has_effective_normal()) {
00513     static CPT(RenderState) fakenormal_state = (const RenderState *)NULL;
00514     if (fakenormal_state == (const RenderState *)NULL) {
00515       fakenormal_state = base_state->add_attrib
00516         (ColorAttrib::make_flat(LColor(0.0f, 0.0f, 1.0f, 1.0f)));
00517     }
00518     return fakenormal_state;
00519 
00520   } else {
00521     static CPT(RenderState) tangible_state = (const RenderState *)NULL;
00522     if (tangible_state == (const RenderState *)NULL) {
00523       tangible_state = base_state->add_attrib
00524         (ColorAttrib::make_flat(LColor(0.0f, 0.0f, 1.0f, 1.0f)));
00525     }
00526     return tangible_state;
00527   }
00528 }
00529 
00530 
00531 ////////////////////////////////////////////////////////////////////
00532 //     Function: CollisionSolid::get_other_viz_state
00533 //       Access: Protected
00534 //  Description: Returns a RenderState for rendering collision
00535 //               visualizations for things that are neither solid nor
00536 //               exactly wireframe, like rays and segments.
00537 //
00538 //               Assumes the lock is already held.
00539 ////////////////////////////////////////////////////////////////////
00540 CPT(RenderState) CollisionSolid::
00541 get_other_viz_state() {
00542   // Once someone asks for this pointer, we hold its reference count
00543   // and never free it.
00544   static CPT(RenderState) base_state = (const RenderState *)NULL;
00545   if (base_state == (const RenderState *)NULL) {
00546     base_state = RenderState::make
00547       (CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise),
00548        RenderModeAttrib::make(RenderModeAttrib::M_filled),
00549        TransparencyAttrib::make(TransparencyAttrib::M_alpha));
00550   }
00551 
00552   // We don't bother to make a distinction here between tangible and
00553   // intangible.
00554   return base_state;
00555 }
00556 
00557 ////////////////////////////////////////////////////////////////////
00558 //     Function: CollisionSolid::get_solid_bounds_viz_state
00559 //       Access: Protected
00560 //  Description: Returns a RenderState for rendering collision
00561 //               visualizations in solid.  This automatically returns
00562 //               the appropriate state according to the setting of
00563 //               _tangible.
00564 //
00565 //               Assumes the lock is already held.
00566 ////////////////////////////////////////////////////////////////////
00567 CPT(RenderState) CollisionSolid::
00568 get_solid_bounds_viz_state() {
00569   // Once someone asks for this pointer, we hold its reference count
00570   // and never free it.
00571   static CPT(RenderState) base_state = (const RenderState *)NULL;
00572   if (base_state == (const RenderState *)NULL) {
00573     base_state = RenderState::make
00574       (CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise),
00575        RenderModeAttrib::make(RenderModeAttrib::M_filled),
00576        TransparencyAttrib::make(TransparencyAttrib::M_alpha));
00577   }
00578 
00579   if (!do_is_tangible()) {
00580     static CPT(RenderState) intangible_state = (const RenderState *)NULL;
00581     if (intangible_state == (const RenderState *)NULL) {
00582       intangible_state = base_state->add_attrib
00583         (ColorAttrib::make_flat(LColor(1.0f, 1.0f, 0.5f, 0.3)));
00584     }
00585     return intangible_state;
00586 
00587   } else if (do_has_effective_normal()) {
00588     static CPT(RenderState) fakenormal_state = (const RenderState *)NULL;
00589     if (fakenormal_state == (const RenderState *)NULL) {
00590       fakenormal_state = base_state->add_attrib
00591         (ColorAttrib::make_flat(LColor(0.5f, 0.5f, 1.0f, 0.3)));
00592     }
00593     return fakenormal_state;
00594 
00595   } else {
00596     static CPT(RenderState) tangible_state = (const RenderState *)NULL;
00597     if (tangible_state == (const RenderState *)NULL) {
00598       tangible_state = base_state->add_attrib
00599         (ColorAttrib::make_flat(LColor(1.0f, 1.0f, 0.5f, 0.3)));
00600     }
00601     return tangible_state;
00602   }
00603 }
00604 
00605 
00606 ////////////////////////////////////////////////////////////////////
00607 //     Function: CollisionSolid::get_wireframe_bounds_viz_state
00608 //       Access: Protected
00609 //  Description: Returns a RenderState for rendering collision
00610 //               visualizations in wireframe.  This automatically returns
00611 //               the appropriate state according to the setting of
00612 //               _tangible.
00613 //
00614 //               Assumes the lock is already held.
00615 ////////////////////////////////////////////////////////////////////
00616 CPT(RenderState) CollisionSolid::
00617 get_wireframe_bounds_viz_state() {
00618   // Once someone asks for this pointer, we hold its reference count
00619   // and never free it.
00620   static CPT(RenderState) base_state = (const RenderState *)NULL;
00621   if (base_state == (const RenderState *)NULL) {
00622     base_state = RenderState::make
00623       (CullFaceAttrib::make(CullFaceAttrib::M_cull_none),
00624        RenderModeAttrib::make(RenderModeAttrib::M_wireframe),
00625        TransparencyAttrib::make(TransparencyAttrib::M_none),
00626        ColorAttrib::make_flat(LColor(1.0f, 0.0f, 0.0f, 1.0f)));
00627   }
00628 
00629   return base_state;
00630 }
00631 
00632 
00633 ////////////////////////////////////////////////////////////////////
00634 //     Function: CollisionSolid::get_other_bounds_viz_state
00635 //       Access: Protected
00636 //  Description: Returns a RenderState for rendering collision
00637 //               visualizations for things that are neither solid nor
00638 //               exactly wireframe, like rays and segments.
00639 //
00640 //               Assumes the lock is already held.
00641 ////////////////////////////////////////////////////////////////////
00642 CPT(RenderState) CollisionSolid::
00643 get_other_bounds_viz_state() {
00644   // Once someone asks for this pointer, we hold its reference count
00645   // and never free it.
00646   static CPT(RenderState) base_state = (const RenderState *)NULL;
00647   if (base_state == (const RenderState *)NULL) {
00648     base_state = RenderState::make
00649       (CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise),
00650        RenderModeAttrib::make(RenderModeAttrib::M_filled),
00651        TransparencyAttrib::make(TransparencyAttrib::M_alpha));
00652   }
00653 
00654   // We don't bother to make a distinction here between tangible and
00655   // intangible.
00656   return base_state;
00657 }
00658 
 All Classes Functions Variables Enumerations