00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef CTriangleH
00023 #define CTriangleH
00024
00025 #include "math/CMaths.h"
00026 #include "graphics/CVertex.h"
00027 #include "scenegraph/CMesh.h"
00028 #include "collisions/CCollisionBasics.h"
00029
00030
00031
00039
00040
00041
00050
00051 class cTriangle
00052 {
00053 public:
00054
00055
00056
00057
00058
00059
00068
00069 cTriangle(cMesh* a_parent, const unsigned int a_indexVertex0,
00070 const unsigned int a_indexVertex1, const unsigned int a_indexVertex2) :
00071 m_indexVertex0(a_indexVertex0), m_indexVertex1(a_indexVertex1),
00072 m_indexVertex2(a_indexVertex2), m_parent(a_parent), m_allocated(false),
00073 m_tag(0), m_neighbors(0), m_index(0)
00074 { }
00075
00076
00080
00081 cTriangle() : m_indexVertex0(0), m_indexVertex1(0), m_indexVertex2(0),
00082 m_index(0), m_parent(0), m_allocated(false), m_tag(0), m_neighbors(0)
00083 { }
00084
00085
00086
00090
00091 ~cTriangle() {
00092 if (m_neighbors) {
00093 m_neighbors->clear();
00094
00095
00096 }
00097 }
00098
00099
00100
00101
00102
00103
00104
00113
00114 inline void setVertices(const unsigned int a_indexVertex0,
00115 const unsigned int a_indexVertex1,
00116 const unsigned int a_indexVertex2)
00117 {
00118 m_indexVertex0 = a_indexVertex0;
00119 m_indexVertex1 = a_indexVertex1;
00120 m_indexVertex2 = a_indexVertex2;
00121 }
00122
00123
00124
00130
00131 inline cVertex* getVertex0() const
00132 {
00133
00134 vector<cVertex>* vertex_vector = m_parent->pVertices();
00135 cVertex* vertex_array = (cVertex*) &((*vertex_vector)[0]);
00136 return vertex_array+m_indexVertex0;
00137 };
00138
00139
00140
00146
00147 inline cVertex* getVertex1() const
00148 {
00149
00150 vector<cVertex>* vertex_vector = m_parent->pVertices();
00151 cVertex* vertex_array = (cVertex*) &((*vertex_vector)[0]);
00152 return vertex_array+m_indexVertex1;
00153 };
00154
00155
00156
00162
00163 inline cVertex* getVertex2() const
00164 {
00165
00166 vector<cVertex>* vertex_vector = m_parent->pVertices();
00167 cVertex* vertex_array = (cVertex*) &((*vertex_vector)[0]);
00168 return vertex_array+m_indexVertex2;
00169 };
00170
00171
00172
00180
00181 inline cVertex* getVertex(int vi) const
00182 {
00183
00184
00185 vector<cVertex>* vertex_vector = m_parent->pVertices();
00186 cVertex* vertex_array = (cVertex*) &((*vertex_vector)[0]);
00187
00188 switch (vi)
00189 {
00190 case 0 : return vertex_array+m_indexVertex0;
00191 case 1 : return vertex_array+m_indexVertex1;
00192 case 2 : return vertex_array+m_indexVertex2;
00193 }
00194 return NULL;
00195 }
00196
00197
00198
00205
00206 inline unsigned int getVertexIndex(int vi) const
00207 {
00208 switch (vi)
00209 {
00210 case 0 : return m_indexVertex0;
00211 case 1 : return m_indexVertex1;
00212 case 2 : return m_indexVertex2;
00213 }
00214 return 0;
00215 }
00216
00217
00224
00225 inline unsigned int getIndexVertex0() const
00226 {
00227 return (m_indexVertex0);
00228 };
00229
00230
00231
00238
00239 inline unsigned int getIndexVertex1() const
00240 {
00241 return (m_indexVertex1);
00242 };
00243
00244
00245
00252
00253 inline unsigned int getIndexVertex2() const
00254 {
00255 return (m_indexVertex2);
00256 };
00257
00258
00259
00266
00267 inline unsigned int getIndex() const
00268 {
00269 return (m_index);
00270 };
00271
00272
00273
00279
00280 inline cMesh* getParent() const
00281 {
00282 return (m_parent);
00283 };
00284
00285
00289
00290 inline void setParent(cMesh* parent)
00291 {
00292 m_parent = parent;
00293 };
00294
00295
00296
00303
00304 inline bool allocated() const
00305 {
00306 return (m_allocated);
00307 };
00308
00309
00310
00311
00330
00331 inline bool computeCollision(cVector3d& a_segmentPointA,
00332 cVector3d& a_segmentPointB,
00333 cCollisionRecorder& a_recorder,
00334 cCollisionSettings& a_settings) const
00335 {
00336
00337 bool hit = false;
00338 cVector3d collisionPoint;
00339 cVector3d collisionNormal;
00340 double collisionDistanceSq = CHAI_LARGE;
00341
00342
00343 vector<cVertex>* vertex_vector = m_parent->pVertices();
00344 cVertex* vertex_array = (cVertex*) &((*vertex_vector)[0]);
00345 cVector3d vertex0 = vertex_array[m_indexVertex0].getPos();
00346 cVector3d vertex1 = vertex_array[m_indexVertex1].getPos();
00347 cVector3d vertex2 = vertex_array[m_indexVertex2].getPos();
00348
00349
00350
00351 if (a_settings.m_collisionRadius == 0)
00352 {
00353
00354 if (cIntersectionSegmentTriangle(a_segmentPointA,
00355 a_segmentPointB,
00356 vertex0,
00357 vertex1,
00358 vertex2,
00359 collisionPoint,
00360 collisionNormal))
00361 {
00362 hit = true;
00363 collisionDistanceSq = cDistanceSq(a_segmentPointA, collisionPoint);
00364 }
00365 }
00366
00367
00368
00369
00370
00371 else
00372 {
00373 cVector3d t_collisionPoint, t_collisionNormal;
00374 double t_collisionDistanceSq;
00375 cVector3d normal = cComputeSurfaceNormal(vertex0, vertex1, vertex2);
00376 cVector3d offset; normal.mulr(a_settings.m_collisionRadius, offset);
00377 cVector3d t_vertex0, t_vertex1, t_vertex2;
00378
00379
00380 vertex0.addr(offset, t_vertex0);
00381 vertex1.addr(offset, t_vertex1);
00382 vertex2.addr(offset, t_vertex2);
00383 if (cIntersectionSegmentTriangle(a_segmentPointA,
00384 a_segmentPointB,
00385 t_vertex0,
00386 t_vertex1,
00387 t_vertex2,
00388 collisionPoint,
00389 collisionNormal))
00390 {
00391 hit = true;
00392 collisionDistanceSq = cDistanceSq(a_segmentPointA, collisionPoint);
00393 }
00394
00395
00396 vertex0.subr(offset, t_vertex0);
00397 vertex1.subr(offset, t_vertex1);
00398 vertex2.subr(offset, t_vertex2);
00399 if (cIntersectionSegmentTriangle(a_segmentPointA,
00400 a_segmentPointB,
00401 t_vertex0,
00402 t_vertex1,
00403 t_vertex2,
00404 t_collisionPoint,
00405 t_collisionNormal))
00406 {
00407 hit = true;
00408 t_collisionDistanceSq = cDistanceSq(a_segmentPointA, t_collisionPoint);
00409 if (t_collisionDistanceSq < collisionDistanceSq)
00410 {
00411 collisionPoint = t_collisionPoint;
00412 collisionNormal = t_collisionNormal;
00413 collisionDistanceSq = t_collisionDistanceSq;
00414 }
00415 }
00416
00417
00418 cVector3d t_p, t_n;
00419 if (cIntersectionSegmentSphere(a_segmentPointA,
00420 a_segmentPointB,
00421 vertex0,
00422 a_settings.m_collisionRadius,
00423 t_collisionPoint,
00424 t_collisionNormal,
00425 t_p,
00426 t_n) > 0)
00427 {
00428 hit = true;
00429 t_collisionDistanceSq = cDistanceSq(a_segmentPointA, t_collisionPoint);
00430 if (t_collisionDistanceSq < collisionDistanceSq)
00431 {
00432 collisionPoint = t_collisionPoint;
00433 collisionNormal = t_collisionNormal;
00434 collisionDistanceSq = t_collisionDistanceSq;
00435 }
00436 }
00437
00438
00439 if (cIntersectionSegmentSphere(a_segmentPointA,
00440 a_segmentPointB,
00441 vertex1,
00442 a_settings.m_collisionRadius,
00443 t_collisionPoint,
00444 t_collisionNormal,
00445 t_p,
00446 t_n) > 0)
00447 {
00448 hit = true;
00449 t_collisionDistanceSq = cDistanceSq(a_segmentPointA, t_collisionPoint);
00450 if (t_collisionDistanceSq < collisionDistanceSq)
00451 {
00452 collisionPoint = t_collisionPoint;
00453 collisionNormal = t_collisionNormal;
00454 collisionDistanceSq = t_collisionDistanceSq;
00455 }
00456 }
00457
00458
00459 if (cIntersectionSegmentSphere(a_segmentPointA,
00460 a_segmentPointB,
00461 vertex2,
00462 a_settings.m_collisionRadius,
00463 t_collisionPoint,
00464 t_collisionNormal,
00465 t_p,
00466 t_n) > 0)
00467 {
00468 hit = true;
00469 t_collisionDistanceSq = cDistanceSq(a_segmentPointA, t_collisionPoint);
00470 if (t_collisionDistanceSq < collisionDistanceSq)
00471 {
00472 collisionPoint = t_collisionPoint;
00473 collisionNormal = t_collisionNormal;
00474 collisionDistanceSq = t_collisionDistanceSq;
00475 }
00476 }
00477
00478
00479 if (cIntersectionSegmentToplessCylinder(a_segmentPointA,
00480 a_segmentPointB,
00481 vertex0,
00482 vertex1,
00483 a_settings.m_collisionRadius,
00484 t_collisionPoint,
00485 t_collisionNormal,
00486 t_p,
00487 t_n) > 0)
00488 {
00489 hit = true;
00490 t_collisionDistanceSq = cDistanceSq(a_segmentPointA, t_collisionPoint);
00491 if (t_collisionDistanceSq < collisionDistanceSq)
00492 {
00493 collisionPoint = t_collisionPoint;
00494 collisionNormal = t_collisionNormal;
00495 collisionDistanceSq = t_collisionDistanceSq;
00496 }
00497 }
00498
00499
00500 if (cIntersectionSegmentToplessCylinder(a_segmentPointA,
00501 a_segmentPointB,
00502 vertex0,
00503 vertex2,
00504 a_settings.m_collisionRadius,
00505 t_collisionPoint,
00506 t_collisionNormal,
00507 t_p,
00508 t_n) > 0)
00509 {
00510 hit = true;
00511 t_collisionDistanceSq = cDistanceSq(a_segmentPointA, t_collisionPoint);
00512 if (t_collisionDistanceSq < collisionDistanceSq)
00513 {
00514 collisionPoint = t_collisionPoint;
00515 collisionNormal = t_collisionNormal;
00516 collisionDistanceSq = t_collisionDistanceSq;
00517 }
00518 }
00519
00520
00521 if (cIntersectionSegmentToplessCylinder(a_segmentPointA,
00522 a_segmentPointB,
00523 vertex1,
00524 vertex2,
00525 a_settings.m_collisionRadius,
00526 t_collisionPoint,
00527 t_collisionNormal,
00528 t_p,
00529 t_n) > 0)
00530 {
00531 hit = true;
00532 t_collisionDistanceSq = cDistanceSq(a_segmentPointA, t_collisionPoint);
00533 if (t_collisionDistanceSq < collisionDistanceSq)
00534 {
00535 collisionPoint = t_collisionPoint;
00536 collisionNormal = t_collisionNormal;
00537 collisionDistanceSq = t_collisionDistanceSq;
00538 }
00539 }
00540 }
00541
00542
00543 if (hit)
00544 {
00545
00546
00547
00548 bool hit_confirmed;
00549 if (a_settings.m_checkBothSidesOfTriangles)
00550 {
00551
00552
00553 hit_confirmed = true;
00554 }
00555 else
00556 {
00557
00558
00559 cVector3d segmentAB;
00560 a_segmentPointB.subr(a_segmentPointA, segmentAB);
00561
00562 cVector3d v01, v02, triangleNormal;
00563 vertex2.subr(vertex0, v02);
00564 vertex1.subr(vertex0, v01);
00565 v01.crossr(v02, triangleNormal);
00566
00567 double value = cCosAngle(segmentAB, triangleNormal);
00568 if (value <= 0.0)
00569 {
00570 hit_confirmed = true;
00571 }
00572 else
00573 {
00574 hit_confirmed = false;
00575 }
00576 }
00577
00578
00579
00580 if (hit_confirmed)
00581 {
00582
00583
00584 if (a_settings.m_checkForNearestCollisionOnly)
00585 {
00586
00587
00588 if(collisionDistanceSq < a_recorder.m_nearestCollision.m_squareDistance)
00589 {
00590
00591 a_recorder.m_nearestCollision.m_object = m_parent;
00592 a_recorder.m_nearestCollision.m_triangle = (cTriangle*)this;
00593 a_recorder.m_nearestCollision.m_localPos = collisionPoint;
00594 a_recorder.m_nearestCollision.m_localNormal = collisionNormal;
00595 a_recorder.m_nearestCollision.m_squareDistance = collisionDistanceSq;
00596 a_recorder.m_nearestCollision.m_adjustedSegmentAPoint = a_segmentPointA;
00597
00598
00599 if (!a_settings.m_returnMinimalCollisionData)
00600 {
00601 a_recorder.m_nearestCollision.m_globalPos = cAdd(m_parent->getGlobalPos(),
00602 cMul(m_parent->getGlobalRot(),
00603 a_recorder.m_nearestCollision.m_localPos));
00604 a_recorder.m_nearestCollision.m_globalNormal = cMul(m_parent->getGlobalRot(),
00605 a_recorder.m_nearestCollision.m_localNormal);
00606 }
00607
00608 }
00609 }
00610 else
00611 {
00612 cCollisionEvent newCollisionEvent;
00613
00614
00615 newCollisionEvent.m_object = m_parent;
00616 newCollisionEvent.m_triangle = (cTriangle*)this;
00617 newCollisionEvent.m_localPos = collisionPoint;
00618 newCollisionEvent.m_localNormal = collisionNormal;
00619 newCollisionEvent.m_squareDistance = collisionDistanceSq;
00620 newCollisionEvent.m_adjustedSegmentAPoint = a_segmentPointA;
00621
00622
00623 if (!a_settings.m_returnMinimalCollisionData)
00624 {
00625 newCollisionEvent.m_globalPos = cAdd(m_parent->getGlobalPos(),
00626 cMul(m_parent->getGlobalRot(),
00627 newCollisionEvent.m_localPos));
00628 newCollisionEvent.m_globalNormal = cMul(m_parent->getGlobalRot(),
00629 newCollisionEvent.m_localNormal);
00630 }
00631
00632
00633 a_recorder.m_collisions.push_back(newCollisionEvent);
00634
00635
00636 if(collisionDistanceSq < a_recorder.m_nearestCollision.m_squareDistance)
00637 {
00638 a_recorder.m_nearestCollision = newCollisionEvent;
00639 }
00640 }
00641 }
00642
00643
00644 return (hit_confirmed);
00645 }
00646 else
00647 {
00648 return (false);
00649 }
00650 }
00651
00652
00653
00659
00660 double computeArea()
00661 {
00662
00663 cVector3d u = cSub(getVertex(1)->getPos(),getVertex(0)->getPos());
00664 cVector3d v = cSub(getVertex(2)->getPos(),getVertex(0)->getPos());
00665 return (0.5 * (cCross(u,v).length()));
00666 }
00667
00668
00669 public:
00670
00671
00672
00673
00674
00676 unsigned int m_indexVertex0;
00677
00679 unsigned int m_indexVertex1;
00680
00682 unsigned int m_indexVertex2;
00683
00685 unsigned int m_index;
00686
00688 cMesh* m_parent;
00689
00691 bool m_allocated;
00692
00694 int m_tag;
00695
00697 std::vector<cTriangle*>* m_neighbors;
00698 };
00699
00700
00701 #endif
00702
00703
00704