| 1 | #include "btInternalEdgeUtility.h" | 
|---|
| 2 |  | 
|---|
| 3 | #include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" | 
|---|
| 4 | #include "BulletCollision/CollisionShapes/btTriangleShape.h" | 
|---|
| 5 | #include "BulletCollision/CollisionDispatch/btCollisionObject.h" | 
|---|
| 6 | #include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" | 
|---|
| 7 | #include "LinearMath/btIDebugDraw.h" | 
|---|
| 8 |  | 
|---|
| 9 |  | 
|---|
| 10 | //#define DEBUG_INTERNAL_EDGE | 
|---|
| 11 |  | 
|---|
| 12 |  | 
|---|
| 13 | #ifdef DEBUG_INTERNAL_EDGE | 
|---|
| 14 | #include <stdio.h> | 
|---|
| 15 | #endif //DEBUG_INTERNAL_EDGE | 
|---|
| 16 |  | 
|---|
| 17 |  | 
|---|
| 18 | #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 19 | static btIDebugDraw* gDebugDrawer = 0; | 
|---|
| 20 |  | 
|---|
| 21 | void    btSetDebugDrawer(btIDebugDraw* debugDrawer) | 
|---|
| 22 | { | 
|---|
| 23 |         gDebugDrawer = debugDrawer; | 
|---|
| 24 | } | 
|---|
| 25 |  | 
|---|
| 26 | static void    btDebugDrawLine(const btVector3& from,const btVector3& to, const btVector3& color) | 
|---|
| 27 | { | 
|---|
| 28 |         if (gDebugDrawer) | 
|---|
| 29 |                 gDebugDrawer->drawLine(from,to,color); | 
|---|
| 30 | } | 
|---|
| 31 | #endif //BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 32 |  | 
|---|
| 33 |  | 
|---|
| 34 | static int      btGetHash(int partId, int triangleIndex) | 
|---|
| 35 | { | 
|---|
| 36 |         int hash = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex; | 
|---|
| 37 |         return hash; | 
|---|
| 38 | } | 
|---|
| 39 |  | 
|---|
| 40 |  | 
|---|
| 41 |  | 
|---|
| 42 | static btScalar btGetAngle(const btVector3& edgeA, const btVector3& normalA,const btVector3& normalB) | 
|---|
| 43 | { | 
|---|
| 44 |         const btVector3 refAxis0  = edgeA; | 
|---|
| 45 |         const btVector3 refAxis1  = normalA; | 
|---|
| 46 |         const btVector3 swingAxis = normalB; | 
|---|
| 47 |         btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1)); | 
|---|
| 48 |         return  angle; | 
|---|
| 49 | } | 
|---|
| 50 |  | 
|---|
| 51 |  | 
|---|
| 52 | struct btConnectivityProcessor : public btTriangleCallback | 
|---|
| 53 | { | 
|---|
| 54 |         int                             m_partIdA; | 
|---|
| 55 |         int                             m_triangleIndexA; | 
|---|
| 56 |         btVector3*              m_triangleVerticesA; | 
|---|
| 57 |         btTriangleInfoMap*      m_triangleInfoMap; | 
|---|
| 58 |  | 
|---|
| 59 |  | 
|---|
| 60 |         virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) | 
|---|
| 61 |         { | 
|---|
| 62 |                 //skip self-collisions | 
|---|
| 63 |                 if ((m_partIdA == partId) && (m_triangleIndexA == triangleIndex)) | 
|---|
| 64 |                         return; | 
|---|
| 65 |  | 
|---|
| 66 |                 //skip duplicates (disabled for now) | 
|---|
| 67 |                 //if ((m_partIdA <= partId) && (m_triangleIndexA <= triangleIndex)) | 
|---|
| 68 |                 //      return; | 
|---|
| 69 |  | 
|---|
| 70 |                 //search for shared vertices and edges | 
|---|
| 71 |                 int numshared = 0; | 
|---|
| 72 |                 int sharedVertsA[3]={-1,-1,-1}; | 
|---|
| 73 |                 int sharedVertsB[3]={-1,-1,-1}; | 
|---|
| 74 |  | 
|---|
| 75 |                 ///skip degenerate triangles | 
|---|
| 76 |                 btScalar crossBSqr = ((triangle[1]-triangle[0]).cross(triangle[2]-triangle[0])).length2(); | 
|---|
| 77 |                 if (crossBSqr < m_triangleInfoMap->m_equalVertexThreshold) | 
|---|
| 78 |                         return; | 
|---|
| 79 |  | 
|---|
| 80 |  | 
|---|
| 81 |                 btScalar crossASqr = ((m_triangleVerticesA[1]-m_triangleVerticesA[0]).cross(m_triangleVerticesA[2]-m_triangleVerticesA[0])).length2(); | 
|---|
| 82 |                 ///skip degenerate triangles | 
|---|
| 83 |                 if (crossASqr< m_triangleInfoMap->m_equalVertexThreshold) | 
|---|
| 84 |                         return; | 
|---|
| 85 |  | 
|---|
| 86 | #if 0 | 
|---|
| 87 |                 printf("triangle A[0]   =       (%f,%f,%f)\ntriangle A[1]       =       (%f,%f,%f)\ntriangle A[2]       =       (%f,%f,%f)\n", | 
|---|
| 88 |                         m_triangleVerticesA[0].getX(),m_triangleVerticesA[0].getY(),m_triangleVerticesA[0].getZ(), | 
|---|
| 89 |                         m_triangleVerticesA[1].getX(),m_triangleVerticesA[1].getY(),m_triangleVerticesA[1].getZ(), | 
|---|
| 90 |                         m_triangleVerticesA[2].getX(),m_triangleVerticesA[2].getY(),m_triangleVerticesA[2].getZ()); | 
|---|
| 91 |  | 
|---|
| 92 |                 printf("partId=%d, triangleIndex=%d\n",partId,triangleIndex); | 
|---|
| 93 |                 printf("triangle B[0]   =       (%f,%f,%f)\ntriangle B[1]       =       (%f,%f,%f)\ntriangle B[2]       =       (%f,%f,%f)\n", | 
|---|
| 94 |                         triangle[0].getX(),triangle[0].getY(),triangle[0].getZ(), | 
|---|
| 95 |                         triangle[1].getX(),triangle[1].getY(),triangle[1].getZ(), | 
|---|
| 96 |                         triangle[2].getX(),triangle[2].getY(),triangle[2].getZ()); | 
|---|
| 97 | #endif | 
|---|
| 98 |  | 
|---|
| 99 |                 for (int i=0;i<3;i++) | 
|---|
| 100 |                 { | 
|---|
| 101 |                         for (int j=0;j<3;j++) | 
|---|
| 102 |                         { | 
|---|
| 103 |                                 if ( (m_triangleVerticesA[i]-triangle[j]).length2() < m_triangleInfoMap->m_equalVertexThreshold) | 
|---|
| 104 |                                 { | 
|---|
| 105 |                                         sharedVertsA[numshared] = i; | 
|---|
| 106 |                                         sharedVertsB[numshared] = j; | 
|---|
| 107 |                                         numshared++; | 
|---|
| 108 |                                         ///degenerate case | 
|---|
| 109 |                                         if(numshared >= 3) | 
|---|
| 110 |                                                 return; | 
|---|
| 111 |                                 } | 
|---|
| 112 |                         } | 
|---|
| 113 |                         ///degenerate case | 
|---|
| 114 |                         if(numshared >= 3) | 
|---|
| 115 |                                 return; | 
|---|
| 116 |                 } | 
|---|
| 117 |                 switch (numshared) | 
|---|
| 118 |                 { | 
|---|
| 119 |                 case 0: | 
|---|
| 120 |                         { | 
|---|
| 121 |                                 break; | 
|---|
| 122 |                         } | 
|---|
| 123 |                 case 1: | 
|---|
| 124 |                         { | 
|---|
| 125 |                                 //shared vertex | 
|---|
| 126 |                                 break; | 
|---|
| 127 |                         } | 
|---|
| 128 |                 case 2: | 
|---|
| 129 |                         { | 
|---|
| 130 |                                 //shared edge | 
|---|
| 131 |                                 //we need to make sure the edge is in the order V2V0 and not V0V2 so that the signs are correct | 
|---|
| 132 |                                 if (sharedVertsA[0] == 0 && sharedVertsA[1] == 2) | 
|---|
| 133 |                                 { | 
|---|
| 134 |                                         sharedVertsA[0] = 2; | 
|---|
| 135 |                                         sharedVertsA[1] = 0; | 
|---|
| 136 |                                         int tmp = sharedVertsB[1]; | 
|---|
| 137 |                                         sharedVertsB[1] = sharedVertsB[0]; | 
|---|
| 138 |                                         sharedVertsB[0] = tmp; | 
|---|
| 139 |                                 } | 
|---|
| 140 |  | 
|---|
| 141 |                                 int hash = btGetHash(m_partIdA,m_triangleIndexA); | 
|---|
| 142 |  | 
|---|
| 143 |                                 btTriangleInfo* info = m_triangleInfoMap->find(hash); | 
|---|
| 144 |                                 if (!info) | 
|---|
| 145 |                                 { | 
|---|
| 146 |                                         btTriangleInfo tmp; | 
|---|
| 147 |                                         m_triangleInfoMap->insert(hash,tmp); | 
|---|
| 148 |                                         info = m_triangleInfoMap->find(hash); | 
|---|
| 149 |                                 } | 
|---|
| 150 |  | 
|---|
| 151 |                                 int sumvertsA = sharedVertsA[0]+sharedVertsA[1]; | 
|---|
| 152 |                                 int otherIndexA = 3-sumvertsA; | 
|---|
| 153 |  | 
|---|
| 154 |                                  | 
|---|
| 155 |                                 btVector3 edge(m_triangleVerticesA[sharedVertsA[1]]-m_triangleVerticesA[sharedVertsA[0]]); | 
|---|
| 156 |  | 
|---|
| 157 |                                 btTriangleShape tA(m_triangleVerticesA[0],m_triangleVerticesA[1],m_triangleVerticesA[2]); | 
|---|
| 158 |                                 int otherIndexB = 3-(sharedVertsB[0]+sharedVertsB[1]); | 
|---|
| 159 |  | 
|---|
| 160 |                                 btTriangleShape tB(triangle[sharedVertsB[1]],triangle[sharedVertsB[0]],triangle[otherIndexB]); | 
|---|
| 161 |                                 //btTriangleShape tB(triangle[0],triangle[1],triangle[2]); | 
|---|
| 162 |  | 
|---|
| 163 |                                 btVector3 normalA; | 
|---|
| 164 |                                 btVector3 normalB; | 
|---|
| 165 |                                 tA.calcNormal(normalA); | 
|---|
| 166 |                                 tB.calcNormal(normalB); | 
|---|
| 167 |                                 edge.normalize(); | 
|---|
| 168 |                                 btVector3 edgeCrossA = edge.cross(normalA).normalize(); | 
|---|
| 169 |  | 
|---|
| 170 |                                 { | 
|---|
| 171 |                                         btVector3 tmp = m_triangleVerticesA[otherIndexA]-m_triangleVerticesA[sharedVertsA[0]]; | 
|---|
| 172 |                                         if (edgeCrossA.dot(tmp) < 0) | 
|---|
| 173 |                                         { | 
|---|
| 174 |                                                 edgeCrossA*=-1; | 
|---|
| 175 |                                         } | 
|---|
| 176 |                                 } | 
|---|
| 177 |  | 
|---|
| 178 |                                 btVector3 edgeCrossB = edge.cross(normalB).normalize(); | 
|---|
| 179 |  | 
|---|
| 180 |                                 { | 
|---|
| 181 |                                         btVector3 tmp = triangle[otherIndexB]-triangle[sharedVertsB[0]]; | 
|---|
| 182 |                                         if (edgeCrossB.dot(tmp) < 0) | 
|---|
| 183 |                                         { | 
|---|
| 184 |                                                 edgeCrossB*=-1; | 
|---|
| 185 |                                         } | 
|---|
| 186 |                                 } | 
|---|
| 187 |  | 
|---|
| 188 |                                 btScalar        angle2 = 0; | 
|---|
| 189 |                                 btScalar        ang4 = 0.f; | 
|---|
| 190 |  | 
|---|
| 191 |  | 
|---|
| 192 |                                 btVector3 calculatedEdge = edgeCrossA.cross(edgeCrossB); | 
|---|
| 193 |                                 btScalar len2 = calculatedEdge.length2(); | 
|---|
| 194 |  | 
|---|
| 195 |                                 btScalar correctedAngle(0); | 
|---|
| 196 |                                 btVector3 calculatedNormalB = normalA; | 
|---|
| 197 |                                 bool isConvex = false; | 
|---|
| 198 |  | 
|---|
| 199 |                                 if (len2<m_triangleInfoMap->m_planarEpsilon) | 
|---|
| 200 |                                 { | 
|---|
| 201 |                                         angle2 = 0.f; | 
|---|
| 202 |                                         ang4 = 0.f; | 
|---|
| 203 |                                 } else | 
|---|
| 204 |                                 { | 
|---|
| 205 |  | 
|---|
| 206 |                                         calculatedEdge.normalize(); | 
|---|
| 207 |                                         btVector3 calculatedNormalA = calculatedEdge.cross(edgeCrossA); | 
|---|
| 208 |                                         calculatedNormalA.normalize(); | 
|---|
| 209 |                                         angle2 = btGetAngle(calculatedNormalA,edgeCrossA,edgeCrossB); | 
|---|
| 210 |                                         ang4 = SIMD_PI-angle2; | 
|---|
| 211 |                                         btScalar dotA = normalA.dot(edgeCrossB); | 
|---|
| 212 |                                         ///@todo: check if we need some epsilon, due to floating point imprecision | 
|---|
| 213 |                                         isConvex = (dotA<0.); | 
|---|
| 214 |  | 
|---|
| 215 |                                         correctedAngle = isConvex ? ang4 : -ang4; | 
|---|
| 216 |                                         btQuaternion orn2(calculatedEdge,-correctedAngle); | 
|---|
| 217 |                                         calculatedNormalB = btMatrix3x3(orn2)*normalA; | 
|---|
| 218 |  | 
|---|
| 219 |  | 
|---|
| 220 |                                 } | 
|---|
| 221 |  | 
|---|
| 222 |                                  | 
|---|
| 223 |  | 
|---|
| 224 |                                  | 
|---|
| 225 |                                                          | 
|---|
| 226 |                                 //alternatively use  | 
|---|
| 227 |                                 //btVector3 calculatedNormalB2 = quatRotate(orn,normalA); | 
|---|
| 228 |  | 
|---|
| 229 |  | 
|---|
| 230 |                                 switch (sumvertsA) | 
|---|
| 231 |                                 { | 
|---|
| 232 |                                 case 1: | 
|---|
| 233 |                                         { | 
|---|
| 234 |                                                 btVector3 edge = m_triangleVerticesA[0]-m_triangleVerticesA[1]; | 
|---|
| 235 |                                                 btQuaternion orn(edge,-correctedAngle); | 
|---|
| 236 |                                                 btVector3 computedNormalB = quatRotate(orn,normalA); | 
|---|
| 237 |                                                 btScalar bla = computedNormalB.dot(normalB); | 
|---|
| 238 |                                                 if (bla<0) | 
|---|
| 239 |                                                 { | 
|---|
| 240 |                                                         computedNormalB*=-1; | 
|---|
| 241 |                                                         info->m_flags |= TRI_INFO_V0V1_SWAP_NORMALB; | 
|---|
| 242 |                                                 } | 
|---|
| 243 | #ifdef DEBUG_INTERNAL_EDGE | 
|---|
| 244 |                                                 if ((computedNormalB-normalB).length()>0.0001) | 
|---|
| 245 |                                                 { | 
|---|
| 246 |                                                         printf("warning: normals not identical\n"); | 
|---|
| 247 |                                                 } | 
|---|
| 248 | #endif//DEBUG_INTERNAL_EDGE | 
|---|
| 249 |  | 
|---|
| 250 |                                                 info->m_edgeV0V1Angle = -correctedAngle; | 
|---|
| 251 |  | 
|---|
| 252 |                                                 if (isConvex) | 
|---|
| 253 |                                                         info->m_flags |= TRI_INFO_V0V1_CONVEX; | 
|---|
| 254 |                                                 break; | 
|---|
| 255 |                                         } | 
|---|
| 256 |                                 case 2: | 
|---|
| 257 |                                         { | 
|---|
| 258 |                                                 btVector3 edge = m_triangleVerticesA[2]-m_triangleVerticesA[0]; | 
|---|
| 259 |                                                 btQuaternion orn(edge,-correctedAngle); | 
|---|
| 260 |                                                 btVector3 computedNormalB = quatRotate(orn,normalA); | 
|---|
| 261 |                                                 if (computedNormalB.dot(normalB)<0) | 
|---|
| 262 |                                                 { | 
|---|
| 263 |                                                         computedNormalB*=-1; | 
|---|
| 264 |                                                         info->m_flags |= TRI_INFO_V2V0_SWAP_NORMALB; | 
|---|
| 265 |                                                 } | 
|---|
| 266 |  | 
|---|
| 267 | #ifdef DEBUG_INTERNAL_EDGE | 
|---|
| 268 |                                                 if ((computedNormalB-normalB).length()>0.0001) | 
|---|
| 269 |                                                 { | 
|---|
| 270 |                                                         printf("warning: normals not identical\n"); | 
|---|
| 271 |                                                 } | 
|---|
| 272 | #endif //DEBUG_INTERNAL_EDGE | 
|---|
| 273 |                                                 info->m_edgeV2V0Angle = -correctedAngle; | 
|---|
| 274 |                                                 if (isConvex) | 
|---|
| 275 |                                                         info->m_flags |= TRI_INFO_V2V0_CONVEX; | 
|---|
| 276 |                                                 break;   | 
|---|
| 277 |                                         } | 
|---|
| 278 |                                 case 3: | 
|---|
| 279 |                                         { | 
|---|
| 280 |                                                 btVector3 edge = m_triangleVerticesA[1]-m_triangleVerticesA[2]; | 
|---|
| 281 |                                                 btQuaternion orn(edge,-correctedAngle); | 
|---|
| 282 |                                                 btVector3 computedNormalB = quatRotate(orn,normalA); | 
|---|
| 283 |                                                 if (computedNormalB.dot(normalB)<0) | 
|---|
| 284 |                                                 { | 
|---|
| 285 |                                                         info->m_flags |= TRI_INFO_V1V2_SWAP_NORMALB; | 
|---|
| 286 |                                                         computedNormalB*=-1; | 
|---|
| 287 |                                                 } | 
|---|
| 288 | #ifdef DEBUG_INTERNAL_EDGE | 
|---|
| 289 |                                                 if ((computedNormalB-normalB).length()>0.0001) | 
|---|
| 290 |                                                 { | 
|---|
| 291 |                                                         printf("warning: normals not identical\n"); | 
|---|
| 292 |                                                 } | 
|---|
| 293 | #endif //DEBUG_INTERNAL_EDGE | 
|---|
| 294 |                                                 info->m_edgeV1V2Angle = -correctedAngle; | 
|---|
| 295 |  | 
|---|
| 296 |                                                 if (isConvex) | 
|---|
| 297 |                                                         info->m_flags |= TRI_INFO_V1V2_CONVEX; | 
|---|
| 298 |                                                 break; | 
|---|
| 299 |                                         } | 
|---|
| 300 |                                 } | 
|---|
| 301 |  | 
|---|
| 302 |                                 break; | 
|---|
| 303 |                         } | 
|---|
| 304 |                 default: | 
|---|
| 305 |                         { | 
|---|
| 306 |                                 //                              printf("warning: duplicate triangle\n"); | 
|---|
| 307 |                         } | 
|---|
| 308 |  | 
|---|
| 309 |                 } | 
|---|
| 310 |         } | 
|---|
| 311 | }; | 
|---|
| 312 | ///////////////////////////////////////////////////////// | 
|---|
| 313 | ///////////////////////////////////////////////////////// | 
|---|
| 314 |  | 
|---|
| 315 | void btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*trimeshShape, btTriangleInfoMap* triangleInfoMap) | 
|---|
| 316 | { | 
|---|
| 317 |         //the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there! | 
|---|
| 318 |         if (trimeshShape->getTriangleInfoMap()) | 
|---|
| 319 |                 return; | 
|---|
| 320 |  | 
|---|
| 321 |         trimeshShape->setTriangleInfoMap(triangleInfoMap); | 
|---|
| 322 |  | 
|---|
| 323 |         btStridingMeshInterface* meshInterface = trimeshShape->getMeshInterface(); | 
|---|
| 324 |         const btVector3& meshScaling = meshInterface->getScaling(); | 
|---|
| 325 |  | 
|---|
| 326 |         for (int partId = 0; partId< meshInterface->getNumSubParts();partId++) | 
|---|
| 327 |         { | 
|---|
| 328 |                 const unsigned char *vertexbase = 0; | 
|---|
| 329 |                 int numverts = 0; | 
|---|
| 330 |                 PHY_ScalarType type = PHY_INTEGER; | 
|---|
| 331 |                 int stride = 0; | 
|---|
| 332 |                 const unsigned char *indexbase = 0; | 
|---|
| 333 |                 int indexstride = 0; | 
|---|
| 334 |                 int numfaces = 0; | 
|---|
| 335 |                 PHY_ScalarType indicestype = PHY_INTEGER; | 
|---|
| 336 |                 //PHY_ScalarType indexType=0; | 
|---|
| 337 |  | 
|---|
| 338 |                 btVector3 triangleVerts[3]; | 
|---|
| 339 |                 meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,   type,stride,&indexbase,indexstride,numfaces,indicestype,partId); | 
|---|
| 340 |                 btVector3 aabbMin,aabbMax; | 
|---|
| 341 |  | 
|---|
| 342 |                 for (int triangleIndex = 0 ; triangleIndex < numfaces;triangleIndex++) | 
|---|
| 343 |                 { | 
|---|
| 344 |                         unsigned int* gfxbase = (unsigned int*)(indexbase+triangleIndex*indexstride); | 
|---|
| 345 |  | 
|---|
| 346 |                         for (int j=2;j>=0;j--) | 
|---|
| 347 |                         { | 
|---|
| 348 |  | 
|---|
| 349 |                                 int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; | 
|---|
| 350 |                                 if (type == PHY_FLOAT) | 
|---|
| 351 |                                 { | 
|---|
| 352 |                                         float* graphicsbase = (float*)(vertexbase+graphicsindex*stride); | 
|---|
| 353 |                                         triangleVerts[j] = btVector3( | 
|---|
| 354 |                                                 graphicsbase[0]*meshScaling.getX(), | 
|---|
| 355 |                                                 graphicsbase[1]*meshScaling.getY(), | 
|---|
| 356 |                                                 graphicsbase[2]*meshScaling.getZ()); | 
|---|
| 357 |                                 } | 
|---|
| 358 |                                 else | 
|---|
| 359 |                                 { | 
|---|
| 360 |                                         double* graphicsbase = (double*)(vertexbase+graphicsindex*stride); | 
|---|
| 361 |                                         triangleVerts[j] = btVector3( btScalar(graphicsbase[0]*meshScaling.getX()), btScalar(graphicsbase[1]*meshScaling.getY()), btScalar(graphicsbase[2]*meshScaling.getZ())); | 
|---|
| 362 |                                 } | 
|---|
| 363 |                         } | 
|---|
| 364 |                         aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); | 
|---|
| 365 |                         aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));  | 
|---|
| 366 |                         aabbMin.setMin(triangleVerts[0]); | 
|---|
| 367 |                         aabbMax.setMax(triangleVerts[0]); | 
|---|
| 368 |                         aabbMin.setMin(triangleVerts[1]); | 
|---|
| 369 |                         aabbMax.setMax(triangleVerts[1]); | 
|---|
| 370 |                         aabbMin.setMin(triangleVerts[2]); | 
|---|
| 371 |                         aabbMax.setMax(triangleVerts[2]); | 
|---|
| 372 |  | 
|---|
| 373 |                         btConnectivityProcessor connectivityProcessor; | 
|---|
| 374 |                         connectivityProcessor.m_partIdA = partId; | 
|---|
| 375 |                         connectivityProcessor.m_triangleIndexA = triangleIndex; | 
|---|
| 376 |                         connectivityProcessor.m_triangleVerticesA = &triangleVerts[0]; | 
|---|
| 377 |                         connectivityProcessor.m_triangleInfoMap  = triangleInfoMap; | 
|---|
| 378 |  | 
|---|
| 379 |                         trimeshShape->processAllTriangles(&connectivityProcessor,aabbMin,aabbMax); | 
|---|
| 380 |                 } | 
|---|
| 381 |  | 
|---|
| 382 |         } | 
|---|
| 383 |  | 
|---|
| 384 | } | 
|---|
| 385 |  | 
|---|
| 386 |  | 
|---|
| 387 |  | 
|---|
| 388 |  | 
|---|
| 389 | // Given a point and a line segment (defined by two points), compute the closest point | 
|---|
| 390 | // in the line.  Cap the point at the endpoints of the line segment. | 
|---|
| 391 | void btNearestPointInLineSegment(const btVector3 &point, const btVector3& line0, const btVector3& line1, btVector3& nearestPoint) | 
|---|
| 392 | { | 
|---|
| 393 |         btVector3 lineDelta     = line1 - line0; | 
|---|
| 394 |  | 
|---|
| 395 |         // Handle degenerate lines | 
|---|
| 396 |         if ( lineDelta.fuzzyZero()) | 
|---|
| 397 |         { | 
|---|
| 398 |                 nearestPoint = line0; | 
|---|
| 399 |         } | 
|---|
| 400 |         else | 
|---|
| 401 |         { | 
|---|
| 402 |                 btScalar delta = (point-line0).dot(lineDelta) / (lineDelta).dot(lineDelta); | 
|---|
| 403 |  | 
|---|
| 404 |                 // Clamp the point to conform to the segment's endpoints | 
|---|
| 405 |                 if ( delta < 0 ) | 
|---|
| 406 |                         delta = 0; | 
|---|
| 407 |                 else if ( delta > 1 ) | 
|---|
| 408 |                         delta = 1; | 
|---|
| 409 |  | 
|---|
| 410 |                 nearestPoint = line0 + lineDelta*delta; | 
|---|
| 411 |         } | 
|---|
| 412 | } | 
|---|
| 413 |  | 
|---|
| 414 |  | 
|---|
| 415 |  | 
|---|
| 416 |  | 
|---|
| 417 | bool    btClampNormal(const btVector3& edge,const btVector3& tri_normal_org,const btVector3& localContactNormalOnB, btScalar correctedEdgeAngle, btVector3 & clampedLocalNormal) | 
|---|
| 418 | { | 
|---|
| 419 |         btVector3 tri_normal = tri_normal_org; | 
|---|
| 420 |         //we only have a local triangle normal, not a local contact normal -> only normal in world space... | 
|---|
| 421 |         //either compute the current angle all in local space, or all in world space | 
|---|
| 422 |  | 
|---|
| 423 |         btVector3 edgeCross = edge.cross(tri_normal).normalize(); | 
|---|
| 424 |         btScalar curAngle = btGetAngle(edgeCross,tri_normal,localContactNormalOnB); | 
|---|
| 425 |  | 
|---|
| 426 |         if (correctedEdgeAngle<0) | 
|---|
| 427 |         { | 
|---|
| 428 |                 if (curAngle < correctedEdgeAngle) | 
|---|
| 429 |                 { | 
|---|
| 430 |                         btScalar diffAngle = correctedEdgeAngle-curAngle; | 
|---|
| 431 |                         btQuaternion rotation(edge,diffAngle ); | 
|---|
| 432 |                         clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB; | 
|---|
| 433 |                         return true; | 
|---|
| 434 |                 } | 
|---|
| 435 |         } | 
|---|
| 436 |  | 
|---|
| 437 |         if (correctedEdgeAngle>=0) | 
|---|
| 438 |         { | 
|---|
| 439 |                 if (curAngle > correctedEdgeAngle) | 
|---|
| 440 |                 { | 
|---|
| 441 |                         btScalar diffAngle = correctedEdgeAngle-curAngle; | 
|---|
| 442 |                         btQuaternion rotation(edge,diffAngle ); | 
|---|
| 443 |                         clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB; | 
|---|
| 444 |                         return true; | 
|---|
| 445 |                 } | 
|---|
| 446 |         } | 
|---|
| 447 |         return false; | 
|---|
| 448 | } | 
|---|
| 449 |  | 
|---|
| 450 |  | 
|---|
| 451 |  | 
|---|
| 452 | /// Changes a btManifoldPoint collision normal to the normal from the mesh. | 
|---|
| 453 | void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* colObj0,const btCollisionObject* colObj1, int partId0, int index0, int normalAdjustFlags) | 
|---|
| 454 | { | 
|---|
| 455 |         //btAssert(colObj0->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE); | 
|---|
| 456 |         if (colObj0->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE) | 
|---|
| 457 |                 return; | 
|---|
| 458 |  | 
|---|
| 459 |         btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)colObj0->getRootCollisionShape(); | 
|---|
| 460 |         btTriangleInfoMap* triangleInfoMapPtr = (btTriangleInfoMap*) trimesh->getTriangleInfoMap(); | 
|---|
| 461 |         if (!triangleInfoMapPtr) | 
|---|
| 462 |                 return; | 
|---|
| 463 |  | 
|---|
| 464 |         int hash = btGetHash(partId0,index0); | 
|---|
| 465 |  | 
|---|
| 466 |  | 
|---|
| 467 |         btTriangleInfo* info = triangleInfoMapPtr->find(hash); | 
|---|
| 468 |         if (!info) | 
|---|
| 469 |                 return; | 
|---|
| 470 |  | 
|---|
| 471 |         btScalar frontFacing = (normalAdjustFlags & BT_TRIANGLE_CONVEX_BACKFACE_MODE)==0? 1.f : -1.f; | 
|---|
| 472 |          | 
|---|
| 473 |         const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0->getCollisionShape()); | 
|---|
| 474 |         btVector3 v0,v1,v2; | 
|---|
| 475 |         tri_shape->getVertex(0,v0); | 
|---|
| 476 |         tri_shape->getVertex(1,v1); | 
|---|
| 477 |         tri_shape->getVertex(2,v2); | 
|---|
| 478 |  | 
|---|
| 479 |         btVector3 center = (v0+v1+v2)*btScalar(1./3.); | 
|---|
| 480 |  | 
|---|
| 481 |         btVector3 red(1,0,0), green(0,1,0),blue(0,0,1),white(1,1,1),black(0,0,0); | 
|---|
| 482 |         btVector3 tri_normal; | 
|---|
| 483 |         tri_shape->calcNormal(tri_normal); | 
|---|
| 484 |  | 
|---|
| 485 |         //btScalar dot = tri_normal.dot(cp.m_normalWorldOnB); | 
|---|
| 486 |         btVector3 nearest; | 
|---|
| 487 |         btNearestPointInLineSegment(cp.m_localPointB,v0,v1,nearest); | 
|---|
| 488 |  | 
|---|
| 489 |         btVector3 contact = cp.m_localPointB; | 
|---|
| 490 | #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 491 |         const btTransform& tr = colObj0->getWorldTransform(); | 
|---|
| 492 |         btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,red); | 
|---|
| 493 | #endif //BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 494 |  | 
|---|
| 495 |  | 
|---|
| 496 |  | 
|---|
| 497 |         bool isNearEdge = false; | 
|---|
| 498 |  | 
|---|
| 499 |         int numConcaveEdgeHits = 0; | 
|---|
| 500 |         int numConvexEdgeHits = 0; | 
|---|
| 501 |  | 
|---|
| 502 |         btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB; | 
|---|
| 503 |         localContactNormalOnB.normalize();//is this necessary? | 
|---|
| 504 |  | 
|---|
| 505 |         if ((info->m_edgeV0V1Angle)< SIMD_2_PI) | 
|---|
| 506 |         { | 
|---|
| 507 | #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 508 |                 btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black); | 
|---|
| 509 | #endif | 
|---|
| 510 |                 btScalar len = (contact-nearest).length(); | 
|---|
| 511 |                 if(len<triangleInfoMapPtr->m_edgeDistanceThreshold) | 
|---|
| 512 |                 { | 
|---|
| 513 |                         btVector3 edge(v0-v1); | 
|---|
| 514 |                         isNearEdge = true; | 
|---|
| 515 |  | 
|---|
| 516 |                         if (info->m_edgeV0V1Angle==btScalar(0)) | 
|---|
| 517 |                         { | 
|---|
| 518 |                                 numConcaveEdgeHits++; | 
|---|
| 519 |                         } else | 
|---|
| 520 |                         { | 
|---|
| 521 |  | 
|---|
| 522 |                                 bool isEdgeConvex = (info->m_flags & TRI_INFO_V0V1_CONVEX); | 
|---|
| 523 |                                 btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1); | 
|---|
| 524 |         #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 525 |                                 btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white); | 
|---|
| 526 |         #endif //BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 527 |  | 
|---|
| 528 |                                 btVector3 nA = swapFactor * tri_normal; | 
|---|
| 529 |  | 
|---|
| 530 |                                 btQuaternion orn(edge,info->m_edgeV0V1Angle); | 
|---|
| 531 |                                 btVector3 computedNormalB = quatRotate(orn,tri_normal); | 
|---|
| 532 |                                 if (info->m_flags & TRI_INFO_V0V1_SWAP_NORMALB) | 
|---|
| 533 |                                         computedNormalB*=-1; | 
|---|
| 534 |                                 btVector3 nB = swapFactor*computedNormalB; | 
|---|
| 535 |  | 
|---|
| 536 |                                 btScalar        NdotA = localContactNormalOnB.dot(nA); | 
|---|
| 537 |                                 btScalar        NdotB = localContactNormalOnB.dot(nB); | 
|---|
| 538 |                                 bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon); | 
|---|
| 539 |  | 
|---|
| 540 | #ifdef DEBUG_INTERNAL_EDGE | 
|---|
| 541 |                                 { | 
|---|
| 542 |                                          | 
|---|
| 543 |                                         btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red); | 
|---|
| 544 |                                 } | 
|---|
| 545 | #endif //DEBUG_INTERNAL_EDGE | 
|---|
| 546 |  | 
|---|
| 547 |  | 
|---|
| 548 |                                 if (backFacingNormal) | 
|---|
| 549 |                                 { | 
|---|
| 550 |                                         numConcaveEdgeHits++; | 
|---|
| 551 |                                 } | 
|---|
| 552 |                                 else | 
|---|
| 553 |                                 { | 
|---|
| 554 |                                         numConvexEdgeHits++; | 
|---|
| 555 |                                         btVector3 clampedLocalNormal; | 
|---|
| 556 |                                         bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, info->m_edgeV0V1Angle,clampedLocalNormal); | 
|---|
| 557 |                                         if (isClamped) | 
|---|
| 558 |                                         { | 
|---|
| 559 |                                                 if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0)) | 
|---|
| 560 |                                                 { | 
|---|
| 561 |                                                         btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal; | 
|---|
| 562 |                                                         //                                      cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB); | 
|---|
| 563 |                                                         cp.m_normalWorldOnB = newNormal; | 
|---|
| 564 |                                                         // Reproject collision point along normal. (what about cp.m_distance1?) | 
|---|
| 565 |                                                         cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1; | 
|---|
| 566 |                                                         cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB); | 
|---|
| 567 |                                                          | 
|---|
| 568 |                                                 } | 
|---|
| 569 |                                         } | 
|---|
| 570 |                                 } | 
|---|
| 571 |                         } | 
|---|
| 572 |                 } | 
|---|
| 573 |         } | 
|---|
| 574 |  | 
|---|
| 575 |         btNearestPointInLineSegment(contact,v1,v2,nearest); | 
|---|
| 576 | #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 577 |         btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,green); | 
|---|
| 578 | #endif //BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 579 |  | 
|---|
| 580 |         if ((info->m_edgeV1V2Angle)< SIMD_2_PI) | 
|---|
| 581 |         { | 
|---|
| 582 | #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 583 |                 btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black); | 
|---|
| 584 | #endif //BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 585 |  | 
|---|
| 586 |  | 
|---|
| 587 |  | 
|---|
| 588 |                 btScalar len = (contact-nearest).length(); | 
|---|
| 589 |                 if(len<triangleInfoMapPtr->m_edgeDistanceThreshold) | 
|---|
| 590 |                 { | 
|---|
| 591 |                         isNearEdge = true; | 
|---|
| 592 | #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 593 |                         btDebugDrawLine(tr*nearest,tr*(nearest+tri_normal*10),white); | 
|---|
| 594 | #endif //BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 595 |  | 
|---|
| 596 |                         btVector3 edge(v1-v2); | 
|---|
| 597 |  | 
|---|
| 598 |                         isNearEdge = true; | 
|---|
| 599 |  | 
|---|
| 600 |                         if (info->m_edgeV1V2Angle == btScalar(0)) | 
|---|
| 601 |                         { | 
|---|
| 602 |                                 numConcaveEdgeHits++; | 
|---|
| 603 |                         } else | 
|---|
| 604 |                         { | 
|---|
| 605 |                                 bool isEdgeConvex = (info->m_flags & TRI_INFO_V1V2_CONVEX)!=0; | 
|---|
| 606 |                                 btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1); | 
|---|
| 607 |         #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 608 |                                 btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white); | 
|---|
| 609 |         #endif //BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 610 |  | 
|---|
| 611 |                                 btVector3 nA = swapFactor * tri_normal; | 
|---|
| 612 |                                  | 
|---|
| 613 |                                 btQuaternion orn(edge,info->m_edgeV1V2Angle); | 
|---|
| 614 |                                 btVector3 computedNormalB = quatRotate(orn,tri_normal); | 
|---|
| 615 |                                 if (info->m_flags & TRI_INFO_V1V2_SWAP_NORMALB) | 
|---|
| 616 |                                         computedNormalB*=-1; | 
|---|
| 617 |                                 btVector3 nB = swapFactor*computedNormalB; | 
|---|
| 618 |  | 
|---|
| 619 | #ifdef DEBUG_INTERNAL_EDGE | 
|---|
| 620 |                                 { | 
|---|
| 621 |                                         btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red); | 
|---|
| 622 |                                 } | 
|---|
| 623 | #endif //DEBUG_INTERNAL_EDGE | 
|---|
| 624 |  | 
|---|
| 625 |  | 
|---|
| 626 |                                 btScalar        NdotA = localContactNormalOnB.dot(nA); | 
|---|
| 627 |                                 btScalar        NdotB = localContactNormalOnB.dot(nB); | 
|---|
| 628 |                                 bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon); | 
|---|
| 629 |  | 
|---|
| 630 |                                 if (backFacingNormal) | 
|---|
| 631 |                                 { | 
|---|
| 632 |                                         numConcaveEdgeHits++; | 
|---|
| 633 |                                 } | 
|---|
| 634 |                                 else | 
|---|
| 635 |                                 { | 
|---|
| 636 |                                         numConvexEdgeHits++; | 
|---|
| 637 |                                         btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB; | 
|---|
| 638 |                                         btVector3 clampedLocalNormal; | 
|---|
| 639 |                                         bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, info->m_edgeV1V2Angle,clampedLocalNormal); | 
|---|
| 640 |                                         if (isClamped) | 
|---|
| 641 |                                         { | 
|---|
| 642 |                                                 if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0)) | 
|---|
| 643 |                                                 { | 
|---|
| 644 |                                                         btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal; | 
|---|
| 645 |                                                         //                                      cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB); | 
|---|
| 646 |                                                         cp.m_normalWorldOnB = newNormal; | 
|---|
| 647 |                                                         // Reproject collision point along normal. | 
|---|
| 648 |                                                         cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1; | 
|---|
| 649 |                                                         cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB); | 
|---|
| 650 |                                                 } | 
|---|
| 651 |                                         } | 
|---|
| 652 |                                 } | 
|---|
| 653 |                         } | 
|---|
| 654 |                 } | 
|---|
| 655 |         } | 
|---|
| 656 |  | 
|---|
| 657 |         btNearestPointInLineSegment(contact,v2,v0,nearest); | 
|---|
| 658 | #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 659 |         btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,blue); | 
|---|
| 660 | #endif //BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 661 |  | 
|---|
| 662 |         if ((info->m_edgeV2V0Angle)< SIMD_2_PI) | 
|---|
| 663 |         { | 
|---|
| 664 |  | 
|---|
| 665 | #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 666 |                 btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black); | 
|---|
| 667 | #endif //BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 668 |  | 
|---|
| 669 |                 btScalar len = (contact-nearest).length(); | 
|---|
| 670 |                 if(len<triangleInfoMapPtr->m_edgeDistanceThreshold) | 
|---|
| 671 |                 { | 
|---|
| 672 |                         isNearEdge = true; | 
|---|
| 673 | #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 674 |                         btDebugDrawLine(tr*nearest,tr*(nearest+tri_normal*10),white); | 
|---|
| 675 | #endif //BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 676 |  | 
|---|
| 677 |                         btVector3 edge(v2-v0); | 
|---|
| 678 |  | 
|---|
| 679 |                         if (info->m_edgeV2V0Angle==btScalar(0)) | 
|---|
| 680 |                         { | 
|---|
| 681 |                                 numConcaveEdgeHits++; | 
|---|
| 682 |                         } else | 
|---|
| 683 |                         { | 
|---|
| 684 |  | 
|---|
| 685 |                                 bool isEdgeConvex = (info->m_flags & TRI_INFO_V2V0_CONVEX)!=0; | 
|---|
| 686 |                                 btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1); | 
|---|
| 687 |         #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 688 |                                 btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white); | 
|---|
| 689 |         #endif //BT_INTERNAL_EDGE_DEBUG_DRAW | 
|---|
| 690 |  | 
|---|
| 691 |                                 btVector3 nA = swapFactor * tri_normal; | 
|---|
| 692 |                                 btQuaternion orn(edge,info->m_edgeV2V0Angle); | 
|---|
| 693 |                                 btVector3 computedNormalB = quatRotate(orn,tri_normal); | 
|---|
| 694 |                                 if (info->m_flags & TRI_INFO_V2V0_SWAP_NORMALB) | 
|---|
| 695 |                                         computedNormalB*=-1; | 
|---|
| 696 |                                 btVector3 nB = swapFactor*computedNormalB; | 
|---|
| 697 |  | 
|---|
| 698 | #ifdef DEBUG_INTERNAL_EDGE | 
|---|
| 699 |                                 { | 
|---|
| 700 |                                         btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red); | 
|---|
| 701 |                                 } | 
|---|
| 702 | #endif //DEBUG_INTERNAL_EDGE | 
|---|
| 703 |  | 
|---|
| 704 |                                 btScalar        NdotA = localContactNormalOnB.dot(nA); | 
|---|
| 705 |                                 btScalar        NdotB = localContactNormalOnB.dot(nB); | 
|---|
| 706 |                                 bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon); | 
|---|
| 707 |  | 
|---|
| 708 |                                 if (backFacingNormal) | 
|---|
| 709 |                                 { | 
|---|
| 710 |                                         numConcaveEdgeHits++; | 
|---|
| 711 |                                 } | 
|---|
| 712 |                                 else | 
|---|
| 713 |                                 { | 
|---|
| 714 |                                         numConvexEdgeHits++; | 
|---|
| 715 |                                         //                              printf("hitting convex edge\n"); | 
|---|
| 716 |  | 
|---|
| 717 |  | 
|---|
| 718 |                                         btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB; | 
|---|
| 719 |                                         btVector3 clampedLocalNormal; | 
|---|
| 720 |                                         bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB,info->m_edgeV2V0Angle,clampedLocalNormal); | 
|---|
| 721 |                                         if (isClamped) | 
|---|
| 722 |                                         { | 
|---|
| 723 |                                                 if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0)) | 
|---|
| 724 |                                                 { | 
|---|
| 725 |                                                         btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal; | 
|---|
| 726 |                                                         //                                      cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB); | 
|---|
| 727 |                                                         cp.m_normalWorldOnB = newNormal; | 
|---|
| 728 |                                                         // Reproject collision point along normal. | 
|---|
| 729 |                                                         cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1; | 
|---|
| 730 |                                                         cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB); | 
|---|
| 731 |                                                 } | 
|---|
| 732 |                                         } | 
|---|
| 733 |                                 }  | 
|---|
| 734 |                         } | 
|---|
| 735 |                          | 
|---|
| 736 |  | 
|---|
| 737 |                 } | 
|---|
| 738 |         } | 
|---|
| 739 |  | 
|---|
| 740 | #ifdef DEBUG_INTERNAL_EDGE | 
|---|
| 741 |         { | 
|---|
| 742 |                 btVector3 color(0,1,1); | 
|---|
| 743 |                 btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+cp.m_normalWorldOnB*10,color); | 
|---|
| 744 |         } | 
|---|
| 745 | #endif //DEBUG_INTERNAL_EDGE | 
|---|
| 746 |  | 
|---|
| 747 |         if (isNearEdge) | 
|---|
| 748 |         { | 
|---|
| 749 |  | 
|---|
| 750 |                 if (numConcaveEdgeHits>0) | 
|---|
| 751 |                 { | 
|---|
| 752 |                         if ((normalAdjustFlags & BT_TRIANGLE_CONCAVE_DOUBLE_SIDED)!=0) | 
|---|
| 753 |                         { | 
|---|
| 754 |                                 //fix tri_normal so it pointing the same direction as the current local contact normal | 
|---|
| 755 |                                 if (tri_normal.dot(localContactNormalOnB) < 0) | 
|---|
| 756 |                                 { | 
|---|
| 757 |                                         tri_normal *= -1; | 
|---|
| 758 |                                 } | 
|---|
| 759 |                                 cp.m_normalWorldOnB = colObj0->getWorldTransform().getBasis()*tri_normal; | 
|---|
| 760 |                         } else | 
|---|
| 761 |                         { | 
|---|
| 762 |                                 //modify the normal to be the triangle normal (or backfacing normal) | 
|---|
| 763 |                                 cp.m_normalWorldOnB = colObj0->getWorldTransform().getBasis() *(tri_normal *frontFacing); | 
|---|
| 764 |                         } | 
|---|
| 765 |                          | 
|---|
| 766 |                          | 
|---|
| 767 |                         // Reproject collision point along normal. | 
|---|
| 768 |                         cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1; | 
|---|
| 769 |                         cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB); | 
|---|
| 770 |                 } | 
|---|
| 771 |         } | 
|---|
| 772 | } | 
|---|