Panda3D
collisionSolid.cxx
1 // Filename: collisionSolid.cxx
2 // Created by: drose (24Apr00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "collisionSolid.h"
16 #include "config_collide.h"
17 #include "collisionSphere.h"
18 #include "collisionLine.h"
19 #include "collisionRay.h"
20 #include "collisionSegment.h"
21 #include "collisionParabola.h"
22 #include "collisionBox.h"
23 #include "collisionEntry.h"
24 #include "boundingSphere.h"
25 #include "datagram.h"
26 #include "datagramIterator.h"
27 #include "bamReader.h"
28 #include "bamWriter.h"
29 #include "indent.h"
30 #include "cullFaceAttrib.h"
31 #include "colorAttrib.h"
32 #include "renderModeAttrib.h"
33 #include "transparencyAttrib.h"
34 #include "geomNode.h"
35 
36 PStatCollector CollisionSolid::_volume_pcollector(
37  "Collision Volumes:CollisionSolid");
38 PStatCollector CollisionSolid::_test_pcollector(
39  "Collision Tests:CollisionSolid");
40 TypeHandle CollisionSolid::_type_handle;
41 
42 ////////////////////////////////////////////////////////////////////
43 // Function: CollisionSolid::Constructor
44 // Access: Public
45 // Description:
46 ////////////////////////////////////////////////////////////////////
47 CollisionSolid::
48 CollisionSolid() : _lock("CollisionSolid") {
49  _flags = F_viz_geom_stale | F_tangible | F_internal_bounds_stale;
50 }
51 
52 ////////////////////////////////////////////////////////////////////
53 // Function: CollisionSolid::Copy Constructor
54 // Access: Public
55 // Description:
56 ////////////////////////////////////////////////////////////////////
57 CollisionSolid::
58 CollisionSolid(const CollisionSolid &copy) :
59  CopyOnWriteObject(copy),
60  _effective_normal(copy._effective_normal),
61  _internal_bounds(copy._internal_bounds),
62  _flags(copy._flags),
63  _lock("CollisionSolid")
64 {
65  _flags |= F_viz_geom_stale;
66 }
67 
68 ////////////////////////////////////////////////////////////////////
69 // Function: CollisionSolid::Destructor
70 // Access: Public, Virtual
71 // Description:
72 ////////////////////////////////////////////////////////////////////
73 CollisionSolid::
74 ~CollisionSolid() {
75 }
76 
77 ////////////////////////////////////////////////////////////////////
78 // Function: CollisionSolid::make_cow_copy
79 // Access: Protected, Virtual
80 // Description: Required to implement CopyOnWriteObject.
81 ////////////////////////////////////////////////////////////////////
82 PT(CopyOnWriteObject) CollisionSolid::
83 make_cow_copy() {
84  return make_copy();
85 }
86 
87 ////////////////////////////////////////////////////////////////////
88 // Function: CollisionSolid::get_bounds
89 // Access: Protected
90 // Description: Returns the solid's bounding volume.
91 ////////////////////////////////////////////////////////////////////
92 CPT(BoundingVolume) CollisionSolid::
93 get_bounds() const {
94  LightMutexHolder holder(_lock);
95  if (_flags & F_internal_bounds_stale) {
96  ((CollisionSolid *)this)->_internal_bounds = compute_internal_bounds();
97  ((CollisionSolid *)this)->_flags &= ~F_internal_bounds_stale;
98  }
99  return _internal_bounds;
100 }
101 
102 ////////////////////////////////////////////////////////////////////
103 // Function: CollisionSolid::set_bounds
104 // Access: Protected
105 // Description: Returns the solid's bounding volume.
106 ////////////////////////////////////////////////////////////////////
107 void CollisionSolid::
108 set_bounds(const BoundingVolume &bounding_volume) {
109  LightMutexHolder holder(_lock);
110  ((CollisionSolid *)this)->_internal_bounds = bounding_volume.make_copy();
111  ((CollisionSolid *)this)->_flags &= ~F_internal_bounds_stale;
112 }
113 
114 ////////////////////////////////////////////////////////////////////
115 // Function: CollisionSolid::test_intersection
116 // Access: Public, Virtual
117 // Description: Tests for a collision between this object (which is
118 // also the "from" object in the entry) and the "into"
119 // object. If a collision is detected, returns a new
120 // CollisionEntry object that records the collision;
121 // otherwise, returns NULL.
122 ////////////////////////////////////////////////////////////////////
123 PT(CollisionEntry) CollisionSolid::
124 test_intersection(const CollisionEntry &) const {
125  report_undefined_from_intersection(get_type());
126  return NULL;
127 }
128 
129 ////////////////////////////////////////////////////////////////////
130 // Function: CollisionSolid::xform
131 // Access: Public, Virtual
132 // Description: Transforms the solid by the indicated matrix.
133 ////////////////////////////////////////////////////////////////////
134 void CollisionSolid::
135 xform(const LMatrix4 &mat) {
136  LightMutexHolder holder(_lock);
137  if ((_flags & F_effective_normal) != 0) {
138  _effective_normal = _effective_normal * mat;
139  _effective_normal.normalize();
140  }
141 
142  _flags |= F_viz_geom_stale | F_internal_bounds_stale;
143 }
144 
145 ////////////////////////////////////////////////////////////////////
146 // Function: CollisionSolid::get_viz
147 // Access: Public, Virtual
148 // Description: Returns a GeomNode that may be rendered to visualize
149 // the CollisionSolid. This is used during the cull
150 // traversal to render the CollisionNodes that have been
151 // made visible.
152 ////////////////////////////////////////////////////////////////////
153 PT(PandaNode) CollisionSolid::
154 get_viz(const CullTraverser *, const CullTraverserData &, bool bounds_only) const {
155  LightMutexHolder holder(_lock);
156  if ((_flags & F_viz_geom_stale) != 0) {
157  if (_viz_geom == (GeomNode *)NULL) {
158  ((CollisionSolid *)this)->_viz_geom = new GeomNode("viz");
159  ((CollisionSolid *)this)->_bounds_viz_geom = new GeomNode("bounds_viz");
160  } else {
161  _viz_geom->remove_all_geoms();
162  _bounds_viz_geom->remove_all_geoms();
163  }
164  ((CollisionSolid *)this)->fill_viz_geom();
165  ((CollisionSolid *)this)->_flags &= ~F_viz_geom_stale;
166  }
167 
168  if (bounds_only) {
169  return _bounds_viz_geom.p();
170  } else {
171  return _viz_geom.p();
172  }
173 }
174 
175 ////////////////////////////////////////////////////////////////////
176 // Function: CollisionSolid::get_volume_pcollector
177 // Access: Public, Virtual
178 // Description: Returns a PStatCollector that is used to count the
179 // number of bounding volume tests made against a solid
180 // of this type in a given frame.
181 ////////////////////////////////////////////////////////////////////
182 PStatCollector &CollisionSolid::
183 get_volume_pcollector() {
184  return _volume_pcollector;
185 }
186 
187 ////////////////////////////////////////////////////////////////////
188 // Function: CollisionSolid::get_test_pcollector
189 // Access: Public, Virtual
190 // Description: Returns a PStatCollector that is used to count the
191 // number of intersection tests made against a solid
192 // of this type in a given frame.
193 ////////////////////////////////////////////////////////////////////
196  return _test_pcollector;
197 }
198 
199 ////////////////////////////////////////////////////////////////////
200 // Function: CollisionSolid::output
201 // Access: Public, Virtual
202 // Description:
203 ////////////////////////////////////////////////////////////////////
204 void CollisionSolid::
205 output(ostream &out) const {
206  out << get_type();
207 }
208 
209 ////////////////////////////////////////////////////////////////////
210 // Function: CollisionSolid::write
211 // Access: Public, Virtual
212 // Description:
213 ////////////////////////////////////////////////////////////////////
214 void CollisionSolid::
215 write(ostream &out, int indent_level) const {
216  indent(out, indent_level) << (*this) << "\n";
217 }
218 
219 ////////////////////////////////////////////////////////////////////
220 // Function: CollisionSolid::compute_internal_bounds
221 // Access: Protected, Virtual
222 // Description:
223 ////////////////////////////////////////////////////////////////////
224 PT(BoundingVolume) CollisionSolid::
225 compute_internal_bounds() const {
226  return new BoundingSphere;
227 }
228 
229 ////////////////////////////////////////////////////////////////////
230 // Function: CollisionSolid::test_intersection_from_sphere
231 // Access: Protected, Virtual
232 // Description: This is part of the double-dispatch implementation of
233 // test_intersection(). It is called when the "from"
234 // object is a sphere.
235 ////////////////////////////////////////////////////////////////////
236 PT(CollisionEntry) CollisionSolid::
237 test_intersection_from_sphere(const CollisionEntry &) const {
238  report_undefined_intersection_test(CollisionSphere::get_class_type(),
239  get_type());
240  return NULL;
241 }
242 
243 ////////////////////////////////////////////////////////////////////
244 // Function: CollisionSolid::test_intersection_from_line
245 // Access: Protected, Virtual
246 // Description: This is part of the double-dispatch implementation of
247 // test_intersection(). It is called when the "from"
248 // object is a line.
249 ////////////////////////////////////////////////////////////////////
250 PT(CollisionEntry) CollisionSolid::
251 test_intersection_from_line(const CollisionEntry &) const {
252  report_undefined_intersection_test(CollisionLine::get_class_type(),
253  get_type());
254  return NULL;
255 }
256 
257 ////////////////////////////////////////////////////////////////////
258 // Function: CollisionSolid::test_intersection_from_ray
259 // Access: Protected, Virtual
260 // Description: This is part of the double-dispatch implementation of
261 // test_intersection(). It is called when the "from"
262 // object is a ray.
263 ////////////////////////////////////////////////////////////////////
264 PT(CollisionEntry) CollisionSolid::
265 test_intersection_from_ray(const CollisionEntry &) const {
266  report_undefined_intersection_test(CollisionRay::get_class_type(),
267  get_type());
268  return NULL;
269 }
270 
271 ////////////////////////////////////////////////////////////////////
272 // Function: CollisionSolid::test_intersection_from_segment
273 // Access: Protected, Virtual
274 // Description: This is part of the double-dispatch implementation of
275 // test_intersection(). It is called when the "from"
276 // object is a segment.
277 ////////////////////////////////////////////////////////////////////
278 PT(CollisionEntry) CollisionSolid::
279 test_intersection_from_segment(const CollisionEntry &) const {
280  report_undefined_intersection_test(CollisionSegment::get_class_type(),
281  get_type());
282  return NULL;
283 }
284 
285 ////////////////////////////////////////////////////////////////////
286 // Function: CollisionSolid::test_intersection_from_parabola
287 // Access: Protected, Virtual
288 // Description: This is part of the double-dispatch implementation of
289 // test_intersection(). It is called when the "from"
290 // object is a parabola.
291 ////////////////////////////////////////////////////////////////////
292 PT(CollisionEntry) CollisionSolid::
293 test_intersection_from_parabola(const CollisionEntry &) const {
294  report_undefined_intersection_test(CollisionParabola::get_class_type(),
295  get_type());
296  return NULL;
297 }
298 
299 ////////////////////////////////////////////////////////////////////
300 // Function: CollisionSolid::test_intersection_from_box
301 // Access: Protected, Virtual
302 // Description: This is part of the double-dispatch implementation of
303 // test_intersection(). It is called when the "from"
304 // object is a box.
305 ////////////////////////////////////////////////////////////////////
306 PT(CollisionEntry) CollisionSolid::
307 test_intersection_from_box(const CollisionEntry &) const {
308  report_undefined_intersection_test(CollisionBox::get_class_type(),
309  get_type());
310  return NULL;
311 }
312 
313 
314 #ifndef NDEBUG
315 class CollisionSolidUndefinedPair {
316 public:
317  CollisionSolidUndefinedPair(TypeHandle a, TypeHandle b) :
318  _a(a), _b(b)
319  {}
320  bool operator < (const CollisionSolidUndefinedPair &other) const {
321  if (_a != other._a) {
322  return _a < other._a;
323  }
324  return _b < other._b;
325  }
326 
327  TypeHandle _a;
328  TypeHandle _b;
329 };
330 #endif // NDEBUG
331 
332 ////////////////////////////////////////////////////////////////////
333 // Function: CollisionSolid::report_undefined_intersection_test
334 // Access: Protected, Static
335 // Description: Outputs a message the first time an intersection test
336 // is attempted that isn't defined, and explains a bit
337 // about what it means.
338 ////////////////////////////////////////////////////////////////////
339 void CollisionSolid::
340 report_undefined_intersection_test(TypeHandle from_type, TypeHandle into_type) {
341 #ifndef NDEBUG
342  typedef pset<CollisionSolidUndefinedPair> Reported;
343  static Reported reported;
344 
345  if (reported.insert(CollisionSolidUndefinedPair(from_type, into_type)).second) {
346  collide_cat.error()
347  << "Invalid attempt to detect collision from " << from_type << " into "
348  << into_type << "!\n\n"
349 
350  "This means that a " << from_type << " object attempted to test for an\n"
351  "intersection into a " << into_type << " object. This intersection\n"
352  "test has not yet been defined; it is possible the " << into_type << "\n"
353  "object is not intended to be collidable. Consider calling\n"
354  "set_into_collide_mask(0) on the " << into_type << " object, or\n"
355  "set_from_collide_mask(0) on the " << from_type << " object.\n\n";
356  }
357 #endif // NDEBUG
358 }
359 
360 ////////////////////////////////////////////////////////////////////
361 // Function: CollisionSolid::report_undefined_from_intersection
362 // Access: Protected, Static
363 // Description: Outputs a message the first time an intersection test
364 // is attempted that isn't defined, and explains a bit
365 // about what it means.
366 ////////////////////////////////////////////////////////////////////
367 void CollisionSolid::
368 report_undefined_from_intersection(TypeHandle from_type) {
369 #ifndef NDEBUG
370  typedef pset<TypeHandle> Reported;
371  static Reported reported;
372 
373  if (reported.insert(from_type).second) {
374  collide_cat.error()
375  << "Invalid attempt to detect collision from " << from_type << "!\n\n"
376 
377  "This means that a " << from_type << " object was added to a\n"
378  "CollisionTraverser as if it were a colliding object. However,\n"
379  "no implementation for this kind of object has yet been defined\n"
380  "to collide with other objects.\n\n";
381  }
382 #endif // NDEBUG
383 }
384 
385 ////////////////////////////////////////////////////////////////////
386 // Function: CollisionSolid::write_datagram
387 // Access: Public
388 // Description: Function to write the important information in
389 // the particular object to a Datagram
390 ////////////////////////////////////////////////////////////////////
391 void CollisionSolid::
393  // For now, we need only 8 bits of flags. If we need to expand this
394  // later, we will have to increase the bam version.
395  LightMutexHolder holder(_lock);
396  me.add_uint8(_flags);
397  if ((_flags & F_effective_normal) != 0) {
398  _effective_normal.write_datagram(me);
399  }
400 }
401 
402 ////////////////////////////////////////////////////////////////////
403 // Function: CollisionSolid::fillin
404 // Access: Protected
405 // Description: Function that reads out of the datagram (or asks
406 // manager to read) all of the data that is needed to
407 // re-create this object and stores it in the appropiate
408 // place
409 ////////////////////////////////////////////////////////////////////
410 void CollisionSolid::
411 fillin(DatagramIterator &scan, BamReader *manager) {
412  _flags = scan.get_uint8();
413  if ((_flags & F_effective_normal) != 0) {
414  _effective_normal.read_datagram(scan);
415  }
416 
417  // The viz is always stale after reading from a bam file. So is the
418  // bounding volume.
419  _flags |= F_viz_geom_stale | F_internal_bounds_stale;
420 }
421 
422 
423 ////////////////////////////////////////////////////////////////////
424 // Function: CollisionSolid::fill_viz_geom
425 // Access: Protected, Virtual
426 // Description: Fills the _viz_geom GeomNode up with Geoms suitable
427 // for rendering this solid.
428 ////////////////////////////////////////////////////////////////////
429 void CollisionSolid::
430 fill_viz_geom() {
431 }
432 
433 ////////////////////////////////////////////////////////////////////
434 // Function: CollisionSolid::get_solid_viz_state
435 // Access: Protected
436 // Description: Returns a RenderState for rendering collision
437 // visualizations in solid. This automatically returns
438 // the appropriate state according to the setting of
439 // _tangible.
440 //
441 // Assumes the lock is already held.
442 ////////////////////////////////////////////////////////////////////
443 CPT(RenderState) CollisionSolid::
444 get_solid_viz_state() {
445  // Once someone asks for this pointer, we hold its reference count
446  // and never free it.
447  static CPT(RenderState) base_state = (const RenderState *)NULL;
448  if (base_state == (const RenderState *)NULL) {
449  base_state = RenderState::make
450  (CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise),
451  RenderModeAttrib::make(RenderModeAttrib::M_filled),
452  TransparencyAttrib::make(TransparencyAttrib::M_alpha));
453  }
454 
455  if (!do_is_tangible()) {
456  static CPT(RenderState) intangible_state = (const RenderState *)NULL;
457  if (intangible_state == (const RenderState *)NULL) {
458  intangible_state = base_state->add_attrib
459  (ColorAttrib::make_flat(LColor(1.0f, 0.3, 0.5f, 0.5f)));
460  }
461  return intangible_state;
462 
463  } else if (do_has_effective_normal()) {
464  static CPT(RenderState) fakenormal_state = (const RenderState *)NULL;
465  if (fakenormal_state == (const RenderState *)NULL) {
466  fakenormal_state = base_state->add_attrib
467  (ColorAttrib::make_flat(LColor(0.5f, 0.5f, 1.0f, 0.5f)));
468  }
469  return fakenormal_state;
470 
471  } else {
472  static CPT(RenderState) tangible_state = (const RenderState *)NULL;
473  if (tangible_state == (const RenderState *)NULL) {
474  tangible_state = base_state->add_attrib
475  (ColorAttrib::make_flat(LColor(1.0f, 1.0f, 1.0f, 0.5f)));
476  }
477  return tangible_state;
478  }
479 }
480 
481 
482 ////////////////////////////////////////////////////////////////////
483 // Function: CollisionSolid::get_wireframe_viz_state
484 // Access: Protected
485 // Description: Returns a RenderState for rendering collision
486 // visualizations in wireframe. This automatically returns
487 // the appropriate state according to the setting of
488 // _tangible.
489 //
490 // Assumes the lock is already held.
491 ////////////////////////////////////////////////////////////////////
492 CPT(RenderState) CollisionSolid::
493 get_wireframe_viz_state() {
494  // Once someone asks for this pointer, we hold its reference count
495  // and never free it.
496  static CPT(RenderState) base_state = (const RenderState *)NULL;
497  if (base_state == (const RenderState *)NULL) {
498  base_state = RenderState::make
499  (CullFaceAttrib::make(CullFaceAttrib::M_cull_none),
500  RenderModeAttrib::make(RenderModeAttrib::M_wireframe),
501  TransparencyAttrib::make(TransparencyAttrib::M_none));
502  }
503 
504  if (!do_is_tangible()) {
505  static CPT(RenderState) intangible_state = (const RenderState *)NULL;
506  if (intangible_state == (const RenderState *)NULL) {
507  intangible_state = base_state->add_attrib
508  (ColorAttrib::make_flat(LColor(1.0f, 1.0f, 0.0f, 1.0f)));
509  }
510  return intangible_state;
511 
512  } else if (do_has_effective_normal()) {
513  static CPT(RenderState) fakenormal_state = (const RenderState *)NULL;
514  if (fakenormal_state == (const RenderState *)NULL) {
515  fakenormal_state = base_state->add_attrib
516  (ColorAttrib::make_flat(LColor(0.0f, 0.0f, 1.0f, 1.0f)));
517  }
518  return fakenormal_state;
519 
520  } else {
521  static CPT(RenderState) tangible_state = (const RenderState *)NULL;
522  if (tangible_state == (const RenderState *)NULL) {
523  tangible_state = base_state->add_attrib
524  (ColorAttrib::make_flat(LColor(0.0f, 0.0f, 1.0f, 1.0f)));
525  }
526  return tangible_state;
527  }
528 }
529 
530 
531 ////////////////////////////////////////////////////////////////////
532 // Function: CollisionSolid::get_other_viz_state
533 // Access: Protected
534 // Description: Returns a RenderState for rendering collision
535 // visualizations for things that are neither solid nor
536 // exactly wireframe, like rays and segments.
537 //
538 // Assumes the lock is already held.
539 ////////////////////////////////////////////////////////////////////
540 CPT(RenderState) CollisionSolid::
541 get_other_viz_state() {
542  // Once someone asks for this pointer, we hold its reference count
543  // and never free it.
544  static CPT(RenderState) base_state = (const RenderState *)NULL;
545  if (base_state == (const RenderState *)NULL) {
546  base_state = RenderState::make
547  (CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise),
548  RenderModeAttrib::make(RenderModeAttrib::M_filled),
549  TransparencyAttrib::make(TransparencyAttrib::M_alpha));
550  }
551 
552  // We don't bother to make a distinction here between tangible and
553  // intangible.
554  return base_state;
555 }
556 
557 ////////////////////////////////////////////////////////////////////
558 // Function: CollisionSolid::get_solid_bounds_viz_state
559 // Access: Protected
560 // Description: Returns a RenderState for rendering collision
561 // visualizations in solid. This automatically returns
562 // the appropriate state according to the setting of
563 // _tangible.
564 //
565 // Assumes the lock is already held.
566 ////////////////////////////////////////////////////////////////////
567 CPT(RenderState) CollisionSolid::
568 get_solid_bounds_viz_state() {
569  // Once someone asks for this pointer, we hold its reference count
570  // and never free it.
571  static CPT(RenderState) base_state = (const RenderState *)NULL;
572  if (base_state == (const RenderState *)NULL) {
573  base_state = RenderState::make
574  (CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise),
575  RenderModeAttrib::make(RenderModeAttrib::M_filled),
576  TransparencyAttrib::make(TransparencyAttrib::M_alpha));
577  }
578 
579  if (!do_is_tangible()) {
580  static CPT(RenderState) intangible_state = (const RenderState *)NULL;
581  if (intangible_state == (const RenderState *)NULL) {
582  intangible_state = base_state->add_attrib
583  (ColorAttrib::make_flat(LColor(1.0f, 1.0f, 0.5f, 0.3)));
584  }
585  return intangible_state;
586 
587  } else if (do_has_effective_normal()) {
588  static CPT(RenderState) fakenormal_state = (const RenderState *)NULL;
589  if (fakenormal_state == (const RenderState *)NULL) {
590  fakenormal_state = base_state->add_attrib
591  (ColorAttrib::make_flat(LColor(0.5f, 0.5f, 1.0f, 0.3)));
592  }
593  return fakenormal_state;
594 
595  } else {
596  static CPT(RenderState) tangible_state = (const RenderState *)NULL;
597  if (tangible_state == (const RenderState *)NULL) {
598  tangible_state = base_state->add_attrib
599  (ColorAttrib::make_flat(LColor(1.0f, 1.0f, 0.5f, 0.3)));
600  }
601  return tangible_state;
602  }
603 }
604 
605 
606 ////////////////////////////////////////////////////////////////////
607 // Function: CollisionSolid::get_wireframe_bounds_viz_state
608 // Access: Protected
609 // Description: Returns a RenderState for rendering collision
610 // visualizations in wireframe. This automatically returns
611 // the appropriate state according to the setting of
612 // _tangible.
613 //
614 // Assumes the lock is already held.
615 ////////////////////////////////////////////////////////////////////
616 CPT(RenderState) CollisionSolid::
617 get_wireframe_bounds_viz_state() {
618  // Once someone asks for this pointer, we hold its reference count
619  // and never free it.
620  static CPT(RenderState) base_state = (const RenderState *)NULL;
621  if (base_state == (const RenderState *)NULL) {
622  base_state = RenderState::make
623  (CullFaceAttrib::make(CullFaceAttrib::M_cull_none),
624  RenderModeAttrib::make(RenderModeAttrib::M_wireframe),
625  TransparencyAttrib::make(TransparencyAttrib::M_none),
626  ColorAttrib::make_flat(LColor(1.0f, 0.0f, 0.0f, 1.0f)));
627  }
628 
629  return base_state;
630 }
631 
632 
633 ////////////////////////////////////////////////////////////////////
634 // Function: CollisionSolid::get_other_bounds_viz_state
635 // Access: Protected
636 // Description: Returns a RenderState for rendering collision
637 // visualizations for things that are neither solid nor
638 // exactly wireframe, like rays and segments.
639 //
640 // Assumes the lock is already held.
641 ////////////////////////////////////////////////////////////////////
642 CPT(RenderState) CollisionSolid::
643 get_other_bounds_viz_state() {
644  // Once someone asks for this pointer, we hold its reference count
645  // and never free it.
646  static CPT(RenderState) base_state = (const RenderState *)NULL;
647  if (base_state == (const RenderState *)NULL) {
648  base_state = RenderState::make
649  (CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise),
650  RenderModeAttrib::make(RenderModeAttrib::M_filled),
651  TransparencyAttrib::make(TransparencyAttrib::M_alpha));
652  }
653 
654  // We don't bother to make a distinction here between tangible and
655  // intangible.
656  return base_state;
657 }
658 
A basic node of the scene graph or data graph.
Definition: pandaNode.h:72
void add_uint8(PN_uint8 value)
Adds an unsigned 8-bit integer to the datagram.
Definition: datagram.I:138
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:122
The abstract base class for all things that can collide with other things in the world, and all the things they can collide with (except geometry).
This defines a bounding sphere, consisting of a center and a radius.
This collects together the pieces of data that are accumulated for each node while walking the scene ...
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:73
PN_uint8 get_uint8()
Extracts an unsigned 8-bit integer.
virtual void write_datagram(BamWriter *manager, Datagram &me)
Function to write the important information in the particular object to a Datagram.
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
A lightweight class that represents a single element that may be timed and/or counted via stats...
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:451
Similar to MutexHolder, but for a light mutex.
Defines a single collision event.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:53
This is the base class for all three-component vectors and points.
Definition: lvecBase4.h:111
This base class provides basic reference counting, but also can be used with a CopyOnWritePointer to ...
virtual PStatCollector & get_test_pcollector()
Returns a PStatCollector that is used to count the number of intersection tests made against a solid ...
This is our own Panda specialization on the default STL set.
Definition: pset.h:52
A class to retrieve the individual data elements previously stored in a Datagram. ...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
bool normalize()
Normalizes the vector in place.
Definition: lvecBase3.h:783
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:43
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling...
Definition: cullTraverser.h:48
A node that holds Geom objects, renderable pieces of geometry.
Definition: geomNode.h:37