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 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