1
#include "btInternalEdgeUtility.h"
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"
10
//#define DEBUG_INTERNAL_EDGE
13
#ifdef DEBUG_INTERNAL_EDGE
15
#endif //DEBUG_INTERNAL_EDGE
18
#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
19
static btIDebugDraw* gDebugDrawer = 0;
21
void btSetDebugDrawer(btIDebugDraw* debugDrawer)
23
gDebugDrawer = debugDrawer;
26
static void btDebugDrawLine(const btVector3& from,const btVector3& to, const btVector3& color)
29
gDebugDrawer->drawLine(from,to,color);
31
#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
34
static int btGetHash(int partId, int triangleIndex)
36
int hash = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
42
static btScalar btGetAngle(const btVector3& edgeA, const btVector3& normalA,const btVector3& normalB)
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));
52
struct btConnectivityProcessor : public btTriangleCallback
56
btVector3* m_triangleVerticesA;
57
btTriangleInfoMap* m_triangleInfoMap;
60
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
62
//skip self-collisions
63
if ((m_partIdA == partId) && (m_triangleIndexA == triangleIndex))
66
//skip duplicates (disabled for now)
67
//if ((m_partIdA <= partId) && (m_triangleIndexA <= triangleIndex))
70
//search for shared vertices and edges
72
int sharedVertsA[3]={-1,-1,-1};
73
int sharedVertsB[3]={-1,-1,-1};
75
///skip degenerate triangles
76
btScalar crossBSqr = ((triangle[1]-triangle[0]).cross(triangle[2]-triangle[0])).length2();
77
if (crossBSqr < m_triangleInfoMap->m_equalVertexThreshold)
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)
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());
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());
101
for (int j=0;j<3;j++)
103
if ( (m_triangleVerticesA[i]-triangle[j]).length2() < m_triangleInfoMap->m_equalVertexThreshold)
105
sharedVertsA[numshared] = i;
106
sharedVertsB[numshared] = j;
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)
136
int tmp = sharedVertsB[1];
137
sharedVertsB[1] = sharedVertsB[0];
138
sharedVertsB[0] = tmp;
141
int hash = btGetHash(m_partIdA,m_triangleIndexA);
143
btTriangleInfo* info = m_triangleInfoMap->find(hash);
147
m_triangleInfoMap->insert(hash,tmp);
148
info = m_triangleInfoMap->find(hash);
151
int sumvertsA = sharedVertsA[0]+sharedVertsA[1];
152
int otherIndexA = 3-sumvertsA;
155
btVector3 edge(m_triangleVerticesA[sharedVertsA[1]]-m_triangleVerticesA[sharedVertsA[0]]);
157
btTriangleShape tA(m_triangleVerticesA[0],m_triangleVerticesA[1],m_triangleVerticesA[2]);
158
int otherIndexB = 3-(sharedVertsB[0]+sharedVertsB[1]);
160
btTriangleShape tB(triangle[sharedVertsB[1]],triangle[sharedVertsB[0]],triangle[otherIndexB]);
161
//btTriangleShape tB(triangle[0],triangle[1],triangle[2]);
165
tA.calcNormal(normalA);
166
tB.calcNormal(normalB);
168
btVector3 edgeCrossA = edge.cross(normalA).normalize();
171
btVector3 tmp = m_triangleVerticesA[otherIndexA]-m_triangleVerticesA[sharedVertsA[0]];
172
if (edgeCrossA.dot(tmp) < 0)
178
btVector3 edgeCrossB = edge.cross(normalB).normalize();
181
btVector3 tmp = triangle[otherIndexB]-triangle[sharedVertsB[0]];
182
if (edgeCrossB.dot(tmp) < 0)
192
btVector3 calculatedEdge = edgeCrossA.cross(edgeCrossB);
193
btScalar len2 = calculatedEdge.length2();
195
btScalar correctedAngle(0);
196
btVector3 calculatedNormalB = normalA;
197
bool isConvex = false;
199
if (len2<m_triangleInfoMap->m_planarEpsilon)
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.);
215
correctedAngle = isConvex ? ang4 : -ang4;
216
btQuaternion orn2(calculatedEdge,-correctedAngle);
217
calculatedNormalB = btMatrix3x3(orn2)*normalA;
227
//btVector3 calculatedNormalB2 = quatRotate(orn,normalA);
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);
241
info->m_flags |= TRI_INFO_V0V1_SWAP_NORMALB;
243
#ifdef DEBUG_INTERNAL_EDGE
244
if ((computedNormalB-normalB).length()>0.0001)
246
printf("warning: normals not identical\n");
248
#endif//DEBUG_INTERNAL_EDGE
250
info->m_edgeV0V1Angle = -correctedAngle;
253
info->m_flags |= TRI_INFO_V0V1_CONVEX;
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)
264
info->m_flags |= TRI_INFO_V2V0_SWAP_NORMALB;
267
#ifdef DEBUG_INTERNAL_EDGE
268
if ((computedNormalB-normalB).length()>0.0001)
270
printf("warning: normals not identical\n");
272
#endif //DEBUG_INTERNAL_EDGE
273
info->m_edgeV2V0Angle = -correctedAngle;
275
info->m_flags |= TRI_INFO_V2V0_CONVEX;
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)
285
info->m_flags |= TRI_INFO_V1V2_SWAP_NORMALB;
288
#ifdef DEBUG_INTERNAL_EDGE
289
if ((computedNormalB-normalB).length()>0.0001)
291
printf("warning: normals not identical\n");
293
#endif //DEBUG_INTERNAL_EDGE
294
info->m_edgeV1V2Angle = -correctedAngle;
297
info->m_flags |= TRI_INFO_V1V2_CONVEX;
306
// printf("warning: duplicate triangle\n");
312
/////////////////////////////////////////////////////////
313
/////////////////////////////////////////////////////////
315
void btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*trimeshShape, btTriangleInfoMap* triangleInfoMap)
317
//the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there!
318
if (trimeshShape->getTriangleInfoMap())
321
trimeshShape->setTriangleInfoMap(triangleInfoMap);
323
btStridingMeshInterface* meshInterface = trimeshShape->getMeshInterface();
324
const btVector3& meshScaling = meshInterface->getScaling();
326
for (int partId = 0; partId< meshInterface->getNumSubParts();partId++)
328
const unsigned char *vertexbase = 0;
330
PHY_ScalarType type = PHY_INTEGER;
332
const unsigned char *indexbase = 0;
335
PHY_ScalarType indicestype = PHY_INTEGER;
336
//PHY_ScalarType indexType=0;
338
btVector3 triangleVerts[3];
339
meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,partId);
340
btVector3 aabbMin,aabbMax;
342
for (int triangleIndex = 0 ; triangleIndex < numfaces;triangleIndex++)
344
unsigned int* gfxbase = (unsigned int*)(indexbase+triangleIndex*indexstride);
346
for (int j=2;j>=0;j--)
349
int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
350
if (type == PHY_FLOAT)
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());
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()));
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]);
373
btConnectivityProcessor connectivityProcessor;
374
connectivityProcessor.m_partIdA = partId;
375
connectivityProcessor.m_triangleIndexA = triangleIndex;
376
connectivityProcessor.m_triangleVerticesA = &triangleVerts[0];
377
connectivityProcessor.m_triangleInfoMap = triangleInfoMap;
379
trimeshShape->processAllTriangles(&connectivityProcessor,aabbMin,aabbMax);
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)
393
btVector3 lineDelta = line1 - line0;
395
// Handle degenerate lines
396
if ( lineDelta.fuzzyZero())
398
nearestPoint = line0;
402
btScalar delta = (point-line0).dot(lineDelta) / (lineDelta).dot(lineDelta);
404
// Clamp the point to conform to the segment's endpoints
407
else if ( delta > 1 )
410
nearestPoint = line0 + lineDelta*delta;
417
bool btClampNormal(const btVector3& edge,const btVector3& tri_normal_org,const btVector3& localContactNormalOnB, btScalar correctedEdgeAngle, btVector3 & clampedLocalNormal)
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
423
btVector3 edgeCross = edge.cross(tri_normal).normalize();
424
btScalar curAngle = btGetAngle(edgeCross,tri_normal,localContactNormalOnB);
426
if (correctedEdgeAngle<0)
428
if (curAngle < correctedEdgeAngle)
430
btScalar diffAngle = correctedEdgeAngle-curAngle;
431
btQuaternion rotation(edge,diffAngle );
432
clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB;
437
if (correctedEdgeAngle>=0)
439
if (curAngle > correctedEdgeAngle)
441
btScalar diffAngle = correctedEdgeAngle-curAngle;
442
btQuaternion rotation(edge,diffAngle );
443
clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB;
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)
455
//btAssert(colObj0->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE);
456
if (colObj0->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE)
459
btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)colObj0->getRootCollisionShape();
460
btTriangleInfoMap* triangleInfoMapPtr = (btTriangleInfoMap*) trimesh->getTriangleInfoMap();
461
if (!triangleInfoMapPtr)
464
int hash = btGetHash(partId0,index0);
467
btTriangleInfo* info = triangleInfoMapPtr->find(hash);
471
btScalar frontFacing = (normalAdjustFlags & BT_TRIANGLE_CONVEX_BACKFACE_MODE)==0? 1.f : -1.f;
473
const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0->getCollisionShape());
475
tri_shape->getVertex(0,v0);
476
tri_shape->getVertex(1,v1);
477
tri_shape->getVertex(2,v2);
479
btVector3 center = (v0+v1+v2)*btScalar(1./3.);
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);
485
//btScalar dot = tri_normal.dot(cp.m_normalWorldOnB);
487
btNearestPointInLineSegment(cp.m_localPointB,v0,v1,nearest);
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
497
bool isNearEdge = false;
499
int numConcaveEdgeHits = 0;
500
int numConvexEdgeHits = 0;
502
btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
503
localContactNormalOnB.normalize();//is this necessary?
505
if ((info->m_edgeV0V1Angle)< SIMD_2_PI)
507
#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
508
btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black);
510
btScalar len = (contact-nearest).length();
511
if(len<triangleInfoMapPtr->m_edgeDistanceThreshold)
513
btVector3 edge(v0-v1);
516
if (info->m_edgeV0V1Angle==btScalar(0))
518
numConcaveEdgeHits++;
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
528
btVector3 nA = swapFactor * tri_normal;
530
btQuaternion orn(edge,info->m_edgeV0V1Angle);
531
btVector3 computedNormalB = quatRotate(orn,tri_normal);
532
if (info->m_flags & TRI_INFO_V0V1_SWAP_NORMALB)
534
btVector3 nB = swapFactor*computedNormalB;
536
btScalar NdotA = localContactNormalOnB.dot(nA);
537
btScalar NdotB = localContactNormalOnB.dot(nB);
538
bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon);
540
#ifdef DEBUG_INTERNAL_EDGE
543
btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red);
545
#endif //DEBUG_INTERNAL_EDGE
548
if (backFacingNormal)
550
numConcaveEdgeHits++;
555
btVector3 clampedLocalNormal;
556
bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, info->m_edgeV0V1Angle,clampedLocalNormal);
559
if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0))
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);
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
580
if ((info->m_edgeV1V2Angle)< SIMD_2_PI)
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
588
btScalar len = (contact-nearest).length();
589
if(len<triangleInfoMapPtr->m_edgeDistanceThreshold)
592
#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
593
btDebugDrawLine(tr*nearest,tr*(nearest+tri_normal*10),white);
594
#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
596
btVector3 edge(v1-v2);
600
if (info->m_edgeV1V2Angle == btScalar(0))
602
numConcaveEdgeHits++;
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
611
btVector3 nA = swapFactor * tri_normal;
613
btQuaternion orn(edge,info->m_edgeV1V2Angle);
614
btVector3 computedNormalB = quatRotate(orn,tri_normal);
615
if (info->m_flags & TRI_INFO_V1V2_SWAP_NORMALB)
617
btVector3 nB = swapFactor*computedNormalB;
619
#ifdef DEBUG_INTERNAL_EDGE
621
btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red);
623
#endif //DEBUG_INTERNAL_EDGE
626
btScalar NdotA = localContactNormalOnB.dot(nA);
627
btScalar NdotB = localContactNormalOnB.dot(nB);
628
bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon);
630
if (backFacingNormal)
632
numConcaveEdgeHits++;
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);
642
if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0))
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);
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
662
if ((info->m_edgeV2V0Angle)< SIMD_2_PI)
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
669
btScalar len = (contact-nearest).length();
670
if(len<triangleInfoMapPtr->m_edgeDistanceThreshold)
673
#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
674
btDebugDrawLine(tr*nearest,tr*(nearest+tri_normal*10),white);
675
#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
677
btVector3 edge(v2-v0);
679
if (info->m_edgeV2V0Angle==btScalar(0))
681
numConcaveEdgeHits++;
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
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)
696
btVector3 nB = swapFactor*computedNormalB;
698
#ifdef DEBUG_INTERNAL_EDGE
700
btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red);
702
#endif //DEBUG_INTERNAL_EDGE
704
btScalar NdotA = localContactNormalOnB.dot(nA);
705
btScalar NdotB = localContactNormalOnB.dot(nB);
706
bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon);
708
if (backFacingNormal)
710
numConcaveEdgeHits++;
715
// printf("hitting convex edge\n");
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);
723
if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0))
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);
740
#ifdef DEBUG_INTERNAL_EDGE
742
btVector3 color(0,1,1);
743
btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+cp.m_normalWorldOnB*10,color);
745
#endif //DEBUG_INTERNAL_EDGE
750
if (numConcaveEdgeHits>0)
752
if ((normalAdjustFlags & BT_TRIANGLE_CONCAVE_DOUBLE_SIDED)!=0)
754
//fix tri_normal so it pointing the same direction as the current local contact normal
755
if (tri_normal.dot(localContactNormalOnB) < 0)
759
cp.m_normalWorldOnB = colObj0->getWorldTransform().getBasis()*tri_normal;
762
//modify the normal to be the triangle normal (or backfacing normal)
763
cp.m_normalWorldOnB = colObj0->getWorldTransform().getBasis() *(tri_normal *frontFacing);
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);