00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
00044
00045
00046
00047 CollisionSolid::
00048 CollisionSolid() : _lock("CollisionSolid") {
00049 _flags = F_viz_geom_stale | F_tangible | F_internal_bounds_stale;
00050 }
00051
00052
00053
00054
00055
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
00070
00071
00072
00073 CollisionSolid::
00074 ~CollisionSolid() {
00075 }
00076
00077
00078
00079
00080
00081
00082 PT(CopyOnWriteObject) CollisionSolid::
00083 make_cow_copy() {
00084 return make_copy();
00085 }
00086
00087
00088
00089
00090
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
00104
00105
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
00116
00117
00118
00119
00120
00121
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
00131
00132
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
00147
00148
00149
00150
00151
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
00177
00178
00179
00180
00181
00182 PStatCollector &CollisionSolid::
00183 get_volume_pcollector() {
00184 return _volume_pcollector;
00185 }
00186
00187
00188
00189
00190
00191
00192
00193
00194 PStatCollector &CollisionSolid::
00195 get_test_pcollector() {
00196 return _test_pcollector;
00197 }
00198
00199
00200
00201
00202
00203
00204 void CollisionSolid::
00205 output(ostream &out) const {
00206 out << get_type();
00207 }
00208
00209
00210
00211
00212
00213
00214 void CollisionSolid::
00215 write(ostream &out, int indent_level) const {
00216 indent(out, indent_level) << (*this) << "\n";
00217 }
00218
00219
00220
00221
00222
00223
00224 PT(BoundingVolume) CollisionSolid::
00225 compute_internal_bounds() const {
00226 return new BoundingSphere;
00227 }
00228
00229
00230
00231
00232
00233
00234
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
00245
00246
00247
00248
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
00259
00260
00261
00262
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
00273
00274
00275
00276
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
00287
00288
00289
00290
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
00301
00302
00303
00304
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
00334
00335
00336
00337
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
00362
00363
00364
00365
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
00387
00388
00389
00390
00391 void CollisionSolid::
00392 write_datagram(BamWriter *, Datagram &me) {
00393
00394
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
00404
00405
00406
00407
00408
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
00418
00419 _flags |= F_viz_geom_stale | F_internal_bounds_stale;
00420 }
00421
00422
00423
00424
00425
00426
00427
00428
00429 void CollisionSolid::
00430 fill_viz_geom() {
00431 }
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443 CPT(RenderState) CollisionSolid::
00444 get_solid_viz_state() {
00445
00446
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
00484
00485
00486
00487
00488
00489
00490
00491
00492 CPT(RenderState) CollisionSolid::
00493 get_wireframe_viz_state() {
00494
00495
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
00533
00534
00535
00536
00537
00538
00539
00540 CPT(RenderState) CollisionSolid::
00541 get_other_viz_state() {
00542
00543
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
00553
00554 return base_state;
00555 }
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567 CPT(RenderState) CollisionSolid::
00568 get_solid_bounds_viz_state() {
00569
00570
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
00608
00609
00610
00611
00612
00613
00614
00615
00616 CPT(RenderState) CollisionSolid::
00617 get_wireframe_bounds_viz_state() {
00618
00619
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
00635
00636
00637
00638
00639
00640
00641
00642 CPT(RenderState) CollisionSolid::
00643 get_other_bounds_viz_state() {
00644
00645
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
00655
00656 return base_state;
00657 }
00658