Panda3D
|
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 ©) : 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