- Main Page
- Modules
- Classes
- Files

- File List
- File Members

# D:/CHAI3D/build-2-0-0/2.0.0/win32/src/graphics/CTriangle.h

Go to the documentation of this file.

    00001 //===========================================================================
    00002 /*
    00003     This file is part of the CHAI 3D visualization and haptics libraries.
    00004     Copyright (C) 2003-2009 by CHAI 3D. All rights reserved.
    00005
    00006     This library is free software; you can redistribute it and/or modify
    00007     it under the terms of the GNU General Public License("GPL") version 2
    00008     as published by the Free Software Foundation.
    00009
    00010     For using the CHAI 3D libraries with software that can not be combined
    00011     with the GNU GPL, and for taking advantage of the additional benefits
    00012     of our support services, please contact CHAI 3D about acquiring a
    00013     Professional Edition License.
    00014
    00015     \author    <http://www.chai3d.org>
    00016     \author    Francois Conti
    00017     \version   2.0.0 $Rev: 270 $
    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     // CONSTRUCTOR & DESTRUCTOR:
    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         //delete m_neighbors;
    00095         //m_neighbors = 0;
    00096       }
    00097     }
    00098
    00099
    00100         //-----------------------------------------------------------------------
    00101     // METHODS:
    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         // Where does the vertex array live?
    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         // Where does the vertex array live?
    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         // Where does the vertex array live?
    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         // Where does the vertex array live?
    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         // temp variables
    00337         bool hit = false;
    00338         cVector3d collisionPoint;
    00339         cVector3d collisionNormal;
    00340         double collisionDistanceSq = CHAI_LARGE;
    00341
    00342         // Get the position of the triangle's vertices
    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         // If m_collisionRadius == 0, we search for a possible intersection between
    00350         // the segment AB and the triangle defined by its three vertices V0, V1, V2.
    00351         if (a_settings.m_collisionRadius == 0)
    00352         {
    00353             // check for collision between segment and triangle only
    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         // If m_collisionRadius > 0, we search for a possible intersection between
    00369         // the segment AB and the shell of the current triangle which is described
    00370         // by its three vertices and m_collisionRadius.
    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             // check for collision between segment and triangle upper shell
    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             // check for collision between segment and triangle lower shell
    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             // check for collision between sphere located at vertex 0
    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             // check for collision between sphere located at vertex 1
    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             // check for collision between sphere located at vertex 2
    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             // check for collision between segment and triangle edge01 shell
    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             // check for collision between segment and triangle edge02 shell
    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             // check for collision between segment and triangle edge12 shell
    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         // report collision
    00543         if (hit)
    00544         {
    00545             // before reporting the new collision, we need to check if
    00546             // the collision settings require us to verify the side of the
    00547             // triangle which has been hit.
    00548             bool hit_confirmed;
    00549             if (a_settings.m_checkBothSidesOfTriangles)
    00550             {
    00551                 // settings specify that a collision can occur on both sides
    00552                 // of the triangle, so the new collision is reported.
    00553                 hit_confirmed = true;
    00554             }
    00555             else
    00556             {
    00557                 // we need check on which side of the triangle the collision occurred
    00558                 // and see it needs to be reported.
    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             // here we finally report the new collision to the collision event handler.
    00580             if (hit_confirmed)
    00581             {
    00582                 // we verify if anew collision needs to be created or if we simply
    00583                 // need to update the nearest collision.
    00584                 if (a_settings.m_checkForNearestCollisionOnly)
    00585                 {
    00586                     // no new collision event is create. We just check if we need
    00587                     // to update the nearest collision
    00588                     if(collisionDistanceSq < a_recorder.m_nearestCollision.m_squareDistance)
    00589                     {
    00590                         // report basic collision data
    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                         // report advanced collision data
    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                     // report basic collision data
    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                     // report advanced collision data
    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                     // add new collision even to collision list
    00633                     a_recorder.m_collisions.push_back(newCollisionEvent);
    00634
    00635                     // check if this new collision is a candidate for "nearest one"
    00636                     if(collisionDistanceSq < a_recorder.m_nearestCollision.m_squareDistance)
    00637                     {
    00638                         a_recorder.m_nearestCollision = newCollisionEvent;
    00639                     }
    00640                 }
    00641             }
    00642
    00643             // return result
    00644             return (hit_confirmed);
    00645         }
    00646         else
    00647         {
    00648             return (false);
    00649         }
    00650     }
    00651
    00652
    00653     //-----------------------------------------------------------------------
    00659     //-----------------------------------------------------------------------
    00660     double computeArea()
    00661     {
    00662         // A = 0.5 * | u x v |
    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     // MEMBERS:
    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

CHAI3D 2.0.0 documentation
Please address any questions to support@chai3d.org
(C) 2003-2009 - CHAI 3D
All Rights Reserved.