Bullet Collision Detection & Physics Library

btRaycastCallback.cpp

Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose, 
00008 including commercial applications, and to alter it and redistribute it freely, 
00009 subject to the following restrictions:
00010 
00011 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
00014 */
00015 
00016 //#include <stdio.h>
00017 
00018 #include "BulletCollision/CollisionShapes/btConvexShape.h"
00019 #include "BulletCollision/CollisionShapes/btTriangleShape.h"
00020 #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
00021 #include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
00022 #include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
00023 #include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
00024 #include "btRaycastCallback.h"
00025 
00026 btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to, unsigned int flags)
00027         :
00028         m_from(from),
00029         m_to(to),
00030    //@BP Mod
00031    m_flags(flags),
00032         m_hitFraction(btScalar(1.))
00033 {
00034 
00035 }
00036 
00037 
00038 
00039 void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
00040 {
00041         const btVector3 &vert0=triangle[0];
00042         const btVector3 &vert1=triangle[1];
00043         const btVector3 &vert2=triangle[2];
00044 
00045         btVector3 v10; v10 = vert1 - vert0 ;
00046         btVector3 v20; v20 = vert2 - vert0 ;
00047 
00048         btVector3 triangleNormal; triangleNormal = v10.cross( v20 );
00049         
00050         const btScalar dist = vert0.dot(triangleNormal);
00051         btScalar dist_a = triangleNormal.dot(m_from) ;
00052         dist_a-= dist;
00053         btScalar dist_b = triangleNormal.dot(m_to);
00054         dist_b -= dist;
00055 
00056         if ( dist_a * dist_b >= btScalar(0.0) )
00057         {
00058                 return ; // same sign
00059         }
00060    //@BP Mod - Backface filtering
00061    if (((m_flags & kF_FilterBackfaces) != 0) && (dist_a > btScalar(0.0)))
00062    {
00063       // Backface, skip check
00064       return;
00065    }
00066         
00067         const btScalar proj_length=dist_a-dist_b;
00068         const btScalar distance = (dist_a)/(proj_length);
00069         // Now we have the intersection point on the plane, we'll see if it's inside the triangle
00070         // Add an epsilon as a tolerance for the raycast,
00071         // in case the ray hits exacly on the edge of the triangle.
00072         // It must be scaled for the triangle size.
00073         
00074         if(distance < m_hitFraction)
00075         {
00076                 
00077 
00078                 btScalar edge_tolerance =triangleNormal.length2();              
00079                 edge_tolerance *= btScalar(-0.0001);
00080                 btVector3 point; point.setInterpolate3( m_from, m_to, distance);
00081                 {
00082                         btVector3 v0p; v0p = vert0 - point;
00083                         btVector3 v1p; v1p = vert1 - point;
00084                         btVector3 cp0; cp0 = v0p.cross( v1p );
00085 
00086                         if ( (btScalar)(cp0.dot(triangleNormal)) >=edge_tolerance) 
00087                         {
00088                                                 
00089 
00090                                 btVector3 v2p; v2p = vert2 -  point;
00091                                 btVector3 cp1;
00092                                 cp1 = v1p.cross( v2p);
00093                                 if ( (btScalar)(cp1.dot(triangleNormal)) >=edge_tolerance) 
00094                                 {
00095                                         btVector3 cp2;
00096                                         cp2 = v2p.cross(v0p);
00097                                         
00098                                         if ( (btScalar)(cp2.dot(triangleNormal)) >=edge_tolerance) 
00099                                         {
00100                   //@BP Mod
00101                   // Triangle normal isn't normalized
00102                                       triangleNormal.normalize();
00103 
00104                   //@BP Mod - Allow for unflipped normal when raycasting against backfaces
00105                   if (((m_flags & kF_KeepUnflippedNormal) != 0) || (dist_a <= btScalar(0.0)))
00106                                                 {
00107                                                         m_hitFraction = reportHit(-triangleNormal,distance,partId,triangleIndex);
00108                                                 }
00109                                                 else
00110                                                 {
00111                      m_hitFraction = reportHit(triangleNormal,distance,partId,triangleIndex);
00112                                                 }
00113                                         }
00114                                 }
00115                         }
00116                 }
00117         }
00118 }
00119 
00120 
00121 btTriangleConvexcastCallback::btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin)
00122 {
00123         m_convexShape = convexShape;
00124         m_convexShapeFrom = convexShapeFrom;
00125         m_convexShapeTo = convexShapeTo;
00126         m_triangleToWorld = triangleToWorld;
00127         m_hitFraction = 1.0f;
00128         m_triangleCollisionMargin = triangleCollisionMargin;
00129         m_allowedPenetration = 0.f;
00130 }
00131 
00132 void
00133 btTriangleConvexcastCallback::processTriangle (btVector3* triangle, int partId, int triangleIndex)
00134 {
00135         btTriangleShape triangleShape (triangle[0], triangle[1], triangle[2]);
00136     triangleShape.setMargin(m_triangleCollisionMargin);
00137 
00138         btVoronoiSimplexSolver  simplexSolver;
00139         btGjkEpaPenetrationDepthSolver  gjkEpaPenetrationSolver;
00140 
00141 //#define  USE_SUBSIMPLEX_CONVEX_CAST 1
00142 //if you reenable USE_SUBSIMPLEX_CONVEX_CAST see commented out code below
00143 #ifdef USE_SUBSIMPLEX_CONVEX_CAST
00144         btSubsimplexConvexCast convexCaster(m_convexShape, &triangleShape, &simplexSolver);
00145 #else
00146         //btGjkConvexCast       convexCaster(m_convexShape,&triangleShape,&simplexSolver);
00147         btContinuousConvexCollision convexCaster(m_convexShape,&triangleShape,&simplexSolver,&gjkEpaPenetrationSolver);
00148 #endif //#USE_SUBSIMPLEX_CONVEX_CAST
00149         
00150         btConvexCast::CastResult castResult;
00151         castResult.m_fraction = btScalar(1.);
00152         castResult.m_allowedPenetration = m_allowedPenetration;
00153         if (convexCaster.calcTimeOfImpact(m_convexShapeFrom,m_convexShapeTo,m_triangleToWorld, m_triangleToWorld, castResult))
00154         {
00155                 //add hit
00156                 if (castResult.m_normal.length2() > btScalar(0.0001))
00157                 {                                       
00158                         if (castResult.m_fraction < m_hitFraction)
00159                         {
00160 /* btContinuousConvexCast's normal is already in world space */
00161 /*
00162 #ifdef USE_SUBSIMPLEX_CONVEX_CAST
00163                                 //rotate normal into worldspace
00164                                 castResult.m_normal = m_convexShapeFrom.getBasis() * castResult.m_normal;
00165 #endif //USE_SUBSIMPLEX_CONVEX_CAST
00166 */
00167                                 castResult.m_normal.normalize();
00168 
00169                                 reportHit (castResult.m_normal,
00170                                                         castResult.m_hitPoint,
00171                                                         castResult.m_fraction,
00172                                                         partId,
00173                                                         triangleIndex);
00174                         }
00175                 }
00176         }
00177 }